github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/persistence/plugin.go (about)

     1  package persistence
     2  
     3  import (
     4  	"github.com/asynkron/protoactor-go/actor"
     5  	"google.golang.org/protobuf/proto"
     6  )
     7  
     8  type persistent interface {
     9  	init(provider Provider, context actor.Context)
    10  	PersistReceive(message proto.Message)
    11  	PersistSnapshot(snapshot proto.Message)
    12  	Recovering() bool
    13  	Name() string
    14  }
    15  
    16  type Mixin struct {
    17  	eventIndex    int
    18  	providerState ProviderState
    19  	name          string
    20  	receiver      receiver
    21  	recovering    bool
    22  }
    23  
    24  // enforces that Mixin implements persistent interface
    25  // (if they diverge, code breaks in other packages)
    26  var _ persistent = (*Mixin)(nil)
    27  
    28  func (mixin *Mixin) Recovering() bool {
    29  	return mixin.recovering
    30  }
    31  
    32  func (mixin *Mixin) Name() string {
    33  	return mixin.name
    34  }
    35  
    36  func (mixin *Mixin) PersistReceive(message proto.Message) {
    37  	mixin.providerState.PersistEvent(mixin.Name(), mixin.eventIndex, message)
    38  	if mixin.eventIndex%mixin.providerState.GetSnapshotInterval() == 0 {
    39  		mixin.receiver.Receive(&actor.MessageEnvelope{Message: &RequestSnapshot{}})
    40  	}
    41  	mixin.eventIndex++
    42  }
    43  
    44  func (mixin *Mixin) PersistSnapshot(snapshot proto.Message) {
    45  	mixin.providerState.PersistSnapshot(mixin.Name(), mixin.eventIndex, snapshot)
    46  }
    47  
    48  func (mixin *Mixin) init(provider Provider, context actor.Context) {
    49  	if mixin.providerState == nil {
    50  		mixin.providerState = provider.GetState()
    51  	}
    52  
    53  	receiver := context.(receiver)
    54  
    55  	mixin.name = context.Self().Id
    56  	mixin.eventIndex = 0
    57  	mixin.receiver = receiver
    58  	mixin.recovering = true
    59  
    60  	mixin.providerState.Restart()
    61  	if snapshot, eventIndex, ok := mixin.providerState.GetSnapshot(mixin.Name()); ok {
    62  		mixin.eventIndex = eventIndex
    63  		receiver.Receive(&actor.MessageEnvelope{Message: snapshot})
    64  	}
    65  	mixin.providerState.GetEvents(mixin.Name(), mixin.eventIndex, 0 /* 0 means max */, func(e interface{}) {
    66  		receiver.Receive(&actor.MessageEnvelope{Message: e})
    67  		mixin.eventIndex++
    68  	})
    69  	mixin.recovering = false
    70  	receiver.Receive(&actor.MessageEnvelope{Message: &ReplayComplete{}})
    71  }
    72  
    73  type receiver interface {
    74  	Receive(message *actor.MessageEnvelope)
    75  }