github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/23_proto_actor/persistence/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  
     8  	console "github.com/AsynkronIT/goconsole"
     9  	"github.com/AsynkronIT/protoactor-go/actor"
    10  	"github.com/AsynkronIT/protoactor-go/persistence"
    11  )
    12  
    13  type Provider struct {
    14  	providerState persistence.ProviderState
    15  }
    16  
    17  func NewProvider(snapshotInterval int) *Provider {
    18  	return &Provider{
    19  		providerState: persistence.NewInMemoryProvider(snapshotInterval),
    20  	}
    21  }
    22  
    23  func (p *Provider) InitState(actorName string, eventNum, eventIndexAfterSnapshot int) {
    24  	for i := 0; i < eventNum; i++ {
    25  		p.providerState.PersistEvent(
    26  			actorName,
    27  			i,
    28  			&Message{protoMsg: protoMsg{state: "state" + strconv.Itoa(i)}},
    29  		)
    30  	}
    31  	p.providerState.PersistSnapshot(
    32  		actorName,
    33  		eventIndexAfterSnapshot,
    34  		&Snapshot{protoMsg: protoMsg{state: "state" + strconv.Itoa(eventIndexAfterSnapshot-1)}},
    35  	)
    36  }
    37  
    38  func (p *Provider) GetState() persistence.ProviderState {
    39  	return p.providerState
    40  }
    41  
    42  type protoMsg struct{ state string }
    43  
    44  func (p *protoMsg) Reset()         {}
    45  func (p *protoMsg) String() string { return p.state }
    46  func (p *protoMsg) ProtoMessage()  {}
    47  
    48  type Message struct{ protoMsg }
    49  type Snapshot struct{ protoMsg }
    50  
    51  type Actor struct {
    52  	persistence.Mixin
    53  	state string
    54  }
    55  
    56  func (a *Actor) Receive(ctx actor.Context) {
    57  	switch msg := ctx.Message().(type) {
    58  	case *actor.Started:
    59  		log.Println("actor started")
    60  	case *persistence.RequestSnapshot:
    61  		log.Printf("snapshot internal state '%v'", a.state)
    62  		a.PersistSnapshot(&Snapshot{protoMsg: protoMsg{state: a.state}})
    63  	case *Snapshot:
    64  		a.state = msg.state
    65  		log.Printf("recovered from snapshot, internal state changed to '%v'", a.state)
    66  	case *persistence.ReplayComplete:
    67  		log.Printf("replay completed, internal state changed to '%v'", a.state)
    68  	case *Message:
    69  		scenario := "received replayed event"
    70  		if !a.Recovering() {
    71  			a.PersistReceive(msg)
    72  			scenario = "received new message"
    73  		}
    74  		a.state = msg.state
    75  		log.Printf("%s, internal state changed to '%v'\n", scenario, a.state)
    76  	}
    77  }
    78  
    79  func main() {
    80  	provider := NewProvider(3)
    81  	provider.InitState("persistent", 4, 3)
    82  
    83  	rootContext := actor.EmptyRootContext
    84  	props := actor.PropsFromProducer(func() actor.Actor { return &Actor{} }).
    85  		WithReceiverMiddleware(persistence.Using(provider))
    86  	pid, _ := rootContext.SpawnNamed(props, "persistent")
    87  	rootContext.Send(pid, &Message{protoMsg: protoMsg{state: "state4"}})
    88  	rootContext.Send(pid, &Message{protoMsg: protoMsg{state: "state5"}})
    89  	rootContext.Send(pid, &Message{protoMsg: protoMsg{state: "state7"}})
    90  	rootContext.Send(pid, &Message{protoMsg: protoMsg{state: "state8"}})
    91  
    92  	rootContext.PoisonFuture(pid).Wait()
    93  	fmt.Printf("*** restart ***\n")
    94  	pid, _ = rootContext.SpawnNamed(props, "persistent")
    95  
    96  	console.ReadLine()
    97  }