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 }