diff --git a/Earthfile b/Earthfile index 9629b21..0758c20 100644 --- a/Earthfile +++ b/Earthfile @@ -15,7 +15,7 @@ protogen: --path protos/ego # save artifact to - SAVE ARTIFACT gen/ego/v2 AS LOCAL egopb + SAVE ARTIFACT gen/ego/v3 AS LOCAL egopb testprotogen: # copy the proto files to generate diff --git a/actor.go b/actor.go index d823917..dc64479 100644 --- a/actor.go +++ b/actor.go @@ -39,10 +39,10 @@ import ( "github.com/tochemey/goakt/v2/actors" "github.com/tochemey/goakt/v2/goaktpb" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/eventstream" - "github.com/tochemey/ego/v2/internal/telemetry" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/eventstream" + "github.com/tochemey/ego/v3/internal/telemetry" ) var ( @@ -50,12 +50,12 @@ var ( ) // actor is an event sourced based actor -type actor[T State] struct { - EntityBehavior[T] +type actor struct { + EntityBehavior // specifies the events store eventsStore eventstore.EventsStore // specifies the current state - currentState T + currentState State eventsCounter *atomic.Uint64 lastCommandTime time.Time @@ -64,12 +64,12 @@ type actor[T State] struct { } // enforce compilation error -var _ actors.Actor = &actor[State]{} +var _ actors.Actor = (*actor)(nil) // newActor creates an instance of actor provided the eventSourcedHandler and the events store -func newActor[T State](behavior EntityBehavior[T], eventsStore eventstore.EventsStore, eventsStream eventstream.Stream) *actor[T] { +func newActor(behavior EntityBehavior, eventsStore eventstore.EventsStore, eventsStream eventstream.Stream) *actor { // create an instance of entity and return it - return &actor[T]{ + return &actor{ eventsStore: eventsStore, EntityBehavior: behavior, eventsCounter: atomic.NewUint64(0), @@ -80,7 +80,7 @@ func newActor[T State](behavior EntityBehavior[T], eventsStore eventstore.Events // PreStart pre-starts the actor // At this stage we connect to the various stores -func (entity *actor[T]) PreStart(ctx context.Context) error { +func (entity *actor) PreStart(ctx context.Context) error { spanCtx, span := telemetry.SpanContext(ctx, "PreStart") defer span.End() entity.mu.Lock() @@ -98,7 +98,7 @@ func (entity *actor[T]) PreStart(ctx context.Context) error { } // Receive processes any message dropped into the actor mailbox. -func (entity *actor[T]) Receive(ctx actors.ReceiveContext) { +func (entity *actor) Receive(ctx actors.ReceiveContext) { _, span := telemetry.SpanContext(ctx.Context(), "Receive") defer span.End() @@ -119,7 +119,7 @@ func (entity *actor[T]) Receive(ctx actors.ReceiveContext) { } // PostStop prepares the actor to gracefully shutdown -func (entity *actor[T]) PostStop(ctx context.Context) error { +func (entity *actor) PostStop(ctx context.Context) error { _, span := telemetry.SpanContext(ctx, "PostStop") defer span.End() @@ -131,7 +131,7 @@ func (entity *actor[T]) PostStop(ctx context.Context) error { // recoverFromSnapshot reset the persistent actor to the latest snapshot in case there is one // this is vital when the entity actor is restarting. -func (entity *actor[T]) recoverFromSnapshot(ctx context.Context) error { +func (entity *actor) recoverFromSnapshot(ctx context.Context) error { spanCtx, span := telemetry.SpanContext(ctx, "RecoverFromSnapshot") defer span.End() @@ -157,7 +157,7 @@ func (entity *actor[T]) recoverFromSnapshot(ctx context.Context) error { } // sendErrorReply sends an error as a reply message -func (entity *actor[T]) sendErrorReply(ctx actors.ReceiveContext, err error) { +func (entity *actor) sendErrorReply(ctx actors.ReceiveContext, err error) { reply := &egopb.CommandReply{ Reply: &egopb.CommandReply_ErrorReply{ ErrorReply: &egopb.ErrorReply{ @@ -170,7 +170,7 @@ func (entity *actor[T]) sendErrorReply(ctx actors.ReceiveContext, err error) { } // getStateAndReply returns the current state of the entity -func (entity *actor[T]) getStateAndReply(ctx actors.ReceiveContext) { +func (entity *actor) getStateAndReply(ctx actors.ReceiveContext) { latestEvent, err := entity.eventsStore.GetLatestEvent(ctx.Context(), entity.ID()) if err != nil { entity.sendErrorReply(ctx, err) @@ -193,7 +193,7 @@ func (entity *actor[T]) getStateAndReply(ctx actors.ReceiveContext) { } // processCommandAndReply processes the incoming command -func (entity *actor[T]) processCommandAndReply(ctx actors.ReceiveContext, command Command) { +func (entity *actor) processCommandAndReply(ctx actors.ReceiveContext, command Command) { goCtx := ctx.Context() events, err := entity.HandleCommand(goCtx, command, entity.currentState) if err != nil { diff --git a/actor_test.go b/actor_test.go index ec41302..b2d465c 100644 --- a/actor_test.go +++ b/actor_test.go @@ -39,11 +39,11 @@ import ( "github.com/tochemey/goakt/v2/log" "github.com/tochemey/gopack/postgres" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore/memory" - pgeventstore "github.com/tochemey/ego/v2/eventstore/postgres" - "github.com/tochemey/ego/v2/eventstream" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore/memory" + pgeventstore "github.com/tochemey/ego/v3/eventstore/postgres" + "github.com/tochemey/ego/v3/eventstream" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) func TestActor(t *testing.T) { @@ -76,7 +76,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - actor := newActor[*testpb.Account](behavior, eventStore, eventStream) + actor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor) require.NotNil(t, pid) @@ -174,7 +174,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream) + persistentActor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NotNil(t, pid) @@ -259,7 +259,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream) + persistentActor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NotNil(t, pid) @@ -340,7 +340,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - persistentActor := newActor[*testpb.Account](behavior, eventStore, eventStream) + persistentActor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, err := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NoError(t, err) @@ -464,7 +464,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - actor := newActor[*testpb.Account](behavior, eventStore, eventStream) + actor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor) require.NotNil(t, pid) @@ -582,7 +582,7 @@ func TestActor(t *testing.T) { eventStream := eventstream.New() // create the persistence actor using the behavior previously created - actor := newActor[*testpb.Account](behavior, eventStore, eventStream) + actor := newActor(behavior, eventStore, eventStream) // spawn the actor pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor) require.NotNil(t, pid) diff --git a/behavior.go b/behavior.go index 127e777..30fd1a7 100644 --- a/behavior.go +++ b/behavior.go @@ -35,13 +35,13 @@ type Event proto.Message type State proto.Message // EntityBehavior defines an event sourced behavior when modeling a CQRS EntityBehavior. -type EntityBehavior[T State] interface { +type EntityBehavior interface { // ID defines the id that will be used in the event journal. // This helps track the entity in the events store. ID() string // InitialState returns the event sourced actor initial state. // This is set as the initial state when there are no snapshots found the entity - InitialState() T + InitialState() State // HandleCommand helps handle commands received by the event sourced actor. The command handlers define how to handle each incoming command, // which validations must be applied, and finally, which events will be persisted if any. When there is no event to be persisted a nil can // be returned as a no-op. Command handlers are the meat of the event sourced actor. @@ -53,8 +53,8 @@ type EntityBehavior[T State] interface { // Every event emitted are processed one after the other in the same order they were emitted to guarantee consistency. // It is at the discretion of the application developer to know in which order a given command should return the list of events // This is really powerful when a command needs to return two events. For instance, an OpenAccount command can result in two events: one is AccountOpened and the second is AccountCredited - HandleCommand(ctx context.Context, command Command, priorState T) (events []Event, err error) + HandleCommand(ctx context.Context, command Command, priorState State) (events []Event, err error) // HandleEvent handle events emitted by the command handlers. The event handlers are used to mutate the state of the event sourced actor by applying the events to it. // Event handlers must be pure functions as they will be used when instantiating the event sourced actor and replaying the event journal. - HandleEvent(ctx context.Context, event Event, priorState T) (state T, err error) + HandleEvent(ctx context.Context, event Event, priorState State) (state State, err error) } diff --git a/egopb/ego.pb.go b/egopb/ego.pb.go index 986acb7..bc1bd37 100644 --- a/egopb/ego.pb.go +++ b/egopb/ego.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.31.0 // protoc (unknown) -// source: ego/v2/ego.proto +// source: ego/v3/ego.proto package egopb @@ -46,7 +46,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[0] + mi := &file_ego_v3_ego_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -59,7 +59,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[0] + mi := &file_ego_v3_ego_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -72,7 +72,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{0} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{0} } func (x *Event) GetPersistenceId() string { @@ -143,7 +143,7 @@ type CommandReply struct { func (x *CommandReply) Reset() { *x = CommandReply{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[1] + mi := &file_ego_v3_ego_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -156,7 +156,7 @@ func (x *CommandReply) String() string { func (*CommandReply) ProtoMessage() {} func (x *CommandReply) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[1] + mi := &file_ego_v3_ego_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -169,7 +169,7 @@ func (x *CommandReply) ProtoReflect() protoreflect.Message { // Deprecated: Use CommandReply.ProtoReflect.Descriptor instead. func (*CommandReply) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{1} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{1} } func (m *CommandReply) GetReply() isCommandReply_Reply { @@ -231,7 +231,7 @@ type StateReply struct { func (x *StateReply) Reset() { *x = StateReply{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[2] + mi := &file_ego_v3_ego_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -244,7 +244,7 @@ func (x *StateReply) String() string { func (*StateReply) ProtoMessage() {} func (x *StateReply) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[2] + mi := &file_ego_v3_ego_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -257,7 +257,7 @@ func (x *StateReply) ProtoReflect() protoreflect.Message { // Deprecated: Use StateReply.ProtoReflect.Descriptor instead. func (*StateReply) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{2} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{2} } func (x *StateReply) GetPersistenceId() string { @@ -302,7 +302,7 @@ type ErrorReply struct { func (x *ErrorReply) Reset() { *x = ErrorReply{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[3] + mi := &file_ego_v3_ego_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -315,7 +315,7 @@ func (x *ErrorReply) String() string { func (*ErrorReply) ProtoMessage() {} func (x *ErrorReply) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[3] + mi := &file_ego_v3_ego_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -328,7 +328,7 @@ func (x *ErrorReply) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrorReply.ProtoReflect.Descriptor instead. func (*ErrorReply) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{3} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{3} } func (x *ErrorReply) GetMessage() string { @@ -348,7 +348,7 @@ type NoReply struct { func (x *NoReply) Reset() { *x = NoReply{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[4] + mi := &file_ego_v3_ego_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -361,7 +361,7 @@ func (x *NoReply) String() string { func (*NoReply) ProtoMessage() {} func (x *NoReply) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[4] + mi := &file_ego_v3_ego_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -374,7 +374,7 @@ func (x *NoReply) ProtoReflect() protoreflect.Message { // Deprecated: Use NoReply.ProtoReflect.Descriptor instead. func (*NoReply) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{4} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{4} } // GetStateCommand tells the Aggregate @@ -388,7 +388,7 @@ type GetStateCommand struct { func (x *GetStateCommand) Reset() { *x = GetStateCommand{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[5] + mi := &file_ego_v3_ego_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -401,7 +401,7 @@ func (x *GetStateCommand) String() string { func (*GetStateCommand) ProtoMessage() {} func (x *GetStateCommand) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[5] + mi := &file_ego_v3_ego_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -414,7 +414,7 @@ func (x *GetStateCommand) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStateCommand.ProtoReflect.Descriptor instead. func (*GetStateCommand) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{5} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{5} } // Offset defines the projection offset @@ -436,7 +436,7 @@ type Offset struct { func (x *Offset) Reset() { *x = Offset{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[6] + mi := &file_ego_v3_ego_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -449,7 +449,7 @@ func (x *Offset) String() string { func (*Offset) ProtoMessage() {} func (x *Offset) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[6] + mi := &file_ego_v3_ego_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -462,7 +462,7 @@ func (x *Offset) ProtoReflect() protoreflect.Message { // Deprecated: Use Offset.ProtoReflect.Descriptor instead. func (*Offset) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{6} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{6} } func (x *Offset) GetShardNumber() uint64 { @@ -508,7 +508,7 @@ type ProjectionId struct { func (x *ProjectionId) Reset() { *x = ProjectionId{} if protoimpl.UnsafeEnabled { - mi := &file_ego_v2_ego_proto_msgTypes[7] + mi := &file_ego_v3_ego_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -521,7 +521,7 @@ func (x *ProjectionId) String() string { func (*ProjectionId) ProtoMessage() {} func (x *ProjectionId) ProtoReflect() protoreflect.Message { - mi := &file_ego_v2_ego_proto_msgTypes[7] + mi := &file_ego_v3_ego_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -534,7 +534,7 @@ func (x *ProjectionId) ProtoReflect() protoreflect.Message { // Deprecated: Use ProjectionId.ProtoReflect.Descriptor instead. func (*ProjectionId) Descriptor() ([]byte, []int) { - return file_ego_v2_ego_proto_rawDescGZIP(), []int{7} + return file_ego_v3_ego_proto_rawDescGZIP(), []int{7} } func (x *ProjectionId) GetProjectionName() string { @@ -551,10 +551,10 @@ func (x *ProjectionId) GetShardNumber() uint64 { return 0 } -var File_ego_v2_ego_proto protoreflect.FileDescriptor +var File_ego_v3_ego_proto protoreflect.FileDescriptor -var file_ego_v2_ego_proto_rawDesc = []byte{ - 0x0a, 0x10, 0x65, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x65, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, +var file_ego_v3_ego_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x65, 0x67, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x65, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x65, 0x67, 0x6f, 0x2e, 0x76, 0x31, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x02, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, @@ -616,7 +616,7 @@ var file_ego_v2_ego_proto_rawDesc = []byte{ 0x6f, 0x6d, 0x2e, 0x65, 0x67, 0x6f, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x45, 0x67, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x65, 0x67, 0x6f, - 0x2f, 0x76, 0x32, 0x3b, 0x65, 0x67, 0x6f, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x45, 0x58, 0x58, 0xaa, + 0x2f, 0x76, 0x33, 0x3b, 0x65, 0x67, 0x6f, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x45, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x45, 0x67, 0x6f, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x45, 0x67, 0x6f, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x45, 0x67, 0x6f, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x45, 0x67, 0x6f, 0x3a, 0x3a, 0x56, 0x31, @@ -624,19 +624,19 @@ var file_ego_v2_ego_proto_rawDesc = []byte{ } var ( - file_ego_v2_ego_proto_rawDescOnce sync.Once - file_ego_v2_ego_proto_rawDescData = file_ego_v2_ego_proto_rawDesc + file_ego_v3_ego_proto_rawDescOnce sync.Once + file_ego_v3_ego_proto_rawDescData = file_ego_v3_ego_proto_rawDesc ) -func file_ego_v2_ego_proto_rawDescGZIP() []byte { - file_ego_v2_ego_proto_rawDescOnce.Do(func() { - file_ego_v2_ego_proto_rawDescData = protoimpl.X.CompressGZIP(file_ego_v2_ego_proto_rawDescData) +func file_ego_v3_ego_proto_rawDescGZIP() []byte { + file_ego_v3_ego_proto_rawDescOnce.Do(func() { + file_ego_v3_ego_proto_rawDescData = protoimpl.X.CompressGZIP(file_ego_v3_ego_proto_rawDescData) }) - return file_ego_v2_ego_proto_rawDescData + return file_ego_v3_ego_proto_rawDescData } -var file_ego_v2_ego_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_ego_v2_ego_proto_goTypes = []interface{}{ +var file_ego_v3_ego_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_ego_v3_ego_proto_goTypes = []interface{}{ (*Event)(nil), // 0: ego.v1.Event (*CommandReply)(nil), // 1: ego.v1.CommandReply (*StateReply)(nil), // 2: ego.v1.StateReply @@ -647,7 +647,7 @@ var file_ego_v2_ego_proto_goTypes = []interface{}{ (*ProjectionId)(nil), // 7: ego.v1.ProjectionId (*anypb.Any)(nil), // 8: google.protobuf.Any } -var file_ego_v2_ego_proto_depIdxs = []int32{ +var file_ego_v3_ego_proto_depIdxs = []int32{ 8, // 0: ego.v1.Event.event:type_name -> google.protobuf.Any 8, // 1: ego.v1.Event.resulting_state:type_name -> google.protobuf.Any 2, // 2: ego.v1.CommandReply.state_reply:type_name -> ego.v1.StateReply @@ -660,13 +660,13 @@ var file_ego_v2_ego_proto_depIdxs = []int32{ 0, // [0:5] is the sub-list for field type_name } -func init() { file_ego_v2_ego_proto_init() } -func file_ego_v2_ego_proto_init() { - if File_ego_v2_ego_proto != nil { +func init() { file_ego_v3_ego_proto_init() } +func file_ego_v3_ego_proto_init() { + if File_ego_v3_ego_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_ego_v2_ego_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Event); i { case 0: return &v.state @@ -678,7 +678,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CommandReply); i { case 0: return &v.state @@ -690,7 +690,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StateReply); i { case 0: return &v.state @@ -702,7 +702,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ErrorReply); i { case 0: return &v.state @@ -714,7 +714,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NoReply); i { case 0: return &v.state @@ -726,7 +726,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetStateCommand); i { case 0: return &v.state @@ -738,7 +738,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Offset); i { case 0: return &v.state @@ -750,7 +750,7 @@ func file_ego_v2_ego_proto_init() { return nil } } - file_ego_v2_ego_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_ego_v3_ego_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ProjectionId); i { case 0: return &v.state @@ -763,7 +763,7 @@ func file_ego_v2_ego_proto_init() { } } } - file_ego_v2_ego_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_ego_v3_ego_proto_msgTypes[1].OneofWrappers = []interface{}{ (*CommandReply_StateReply)(nil), (*CommandReply_ErrorReply)(nil), } @@ -771,18 +771,18 @@ func file_ego_v2_ego_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_ego_v2_ego_proto_rawDesc, + RawDescriptor: file_ego_v3_ego_proto_rawDesc, NumEnums: 0, NumMessages: 8, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_ego_v2_ego_proto_goTypes, - DependencyIndexes: file_ego_v2_ego_proto_depIdxs, - MessageInfos: file_ego_v2_ego_proto_msgTypes, + GoTypes: file_ego_v3_ego_proto_goTypes, + DependencyIndexes: file_ego_v3_ego_proto_depIdxs, + MessageInfos: file_ego_v3_ego_proto_msgTypes, }.Build() - File_ego_v2_ego_proto = out.File - file_ego_v2_ego_proto_rawDesc = nil - file_ego_v2_ego_proto_goTypes = nil - file_ego_v2_ego_proto_depIdxs = nil + File_ego_v3_ego_proto = out.File + file_ego_v3_ego_proto_rawDesc = nil + file_ego_v3_ego_proto_goTypes = nil + file_ego_v3_ego_proto_depIdxs = nil } diff --git a/engine.go b/engine.go index 9d3a65c..dac3b10 100644 --- a/engine.go +++ b/engine.go @@ -28,21 +28,35 @@ import ( "context" "fmt" "os" + "sync" "time" "github.com/pkg/errors" "go.uber.org/atomic" + "google.golang.org/protobuf/proto" "github.com/tochemey/goakt/v2/actors" "github.com/tochemey/goakt/v2/discovery" "github.com/tochemey/goakt/v2/log" "github.com/tochemey/goakt/v2/telemetry" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/eventstream" - egotel "github.com/tochemey/ego/v2/internal/telemetry" - "github.com/tochemey/ego/v2/offsetstore" - "github.com/tochemey/ego/v2/projection" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/eventstream" + egotel "github.com/tochemey/ego/v3/internal/telemetry" + "github.com/tochemey/ego/v3/offsetstore" + "github.com/tochemey/ego/v3/projection" +) + +var ( + // ErrEngineRequired is returned when the eGo engine is not set + ErrEngineRequired = errors.New("eGo engine is not defined") + // ErrEngineNotStarted is returned when the eGo engine has not started + ErrEngineNotStarted = errors.New("eGo engine has not started") + // ErrUndefinedEntityID is returned when sending a command to an undefined entity + ErrUndefinedEntityID = errors.New("eGo entity id is not defined") + // ErrCommandReplyUnmarshalling is returned when unmarshalling command reply failed + ErrCommandReplyUnmarshalling = errors.New("failed to parse command reply") ) // Engine represents the engine that empowers the various entities @@ -62,6 +76,7 @@ type Engine struct { remotingPort int minimumPeersQuorum uint16 eventStream eventstream.Stream + locker *sync.Mutex } // NewEngine creates an instance of Engine @@ -73,6 +88,7 @@ func NewEngine(name string, eventsStore eventstore.EventsStore, opts ...Option) logger: log.DefaultLogger, telemetry: telemetry.New(), eventStream: eventstream.New(), + locker: &sync.Mutex{}, } for _, opt := range opts { @@ -99,9 +115,9 @@ func (x *Engine) Start(ctx context.Context) error { x.hostName, _ = os.Hostname() } - replicatCount := 1 + replicaCount := 1 if x.minimumPeersQuorum > 1 { - replicatCount = 2 + replicaCount = 2 } clusterConfig := actors. @@ -110,9 +126,9 @@ func (x *Engine) Start(ctx context.Context) error { WithGossipPort(x.gossipPort). WithPeersPort(x.peersPort). WithMinimumPeersQuorum(uint32(x.minimumPeersQuorum)). - WithReplicaCount(uint32(replicatCount)). + WithReplicaCount(uint32(replicaCount)). WithPartitionCount(x.partitionsCount). - WithKinds(new(actor[State])) + WithKinds(new(actor)) opts = append(opts, actors.WithCluster(clusterConfig), @@ -140,16 +156,25 @@ func (x *Engine) AddProjection(ctx context.Context, name string, handler project spanCtx, span := egotel.SpanContext(ctx, "AddProjection") defer span.End() - if !x.started.Load() { - return errors.New("eGo engine has not started") + x.locker.Lock() + started := x.started.Load() + x.locker.Unlock() + if !started { + return ErrEngineNotStarted } actor := projection.New(name, handler, x.eventsStore, offsetStore, opts...) - var pid actors.PID - var err error + var ( + pid actors.PID + err error + ) - if pid, err = x.actorSystem.Spawn(spanCtx, name, actor); err != nil { + x.locker.Lock() + actorSystem := x.actorSystem + x.locker.Unlock() + + if pid, err = actorSystem.Spawn(spanCtx, name, actor); err != nil { x.logger.Error(errors.Wrapf(err, "failed to register the projection=(%s)", name)) return err } @@ -174,11 +199,18 @@ func (x *Engine) Subscribe(ctx context.Context) (eventstream.Subscriber, error) _, span := egotel.SpanContext(ctx, "Subscribe") defer span.End() - if !x.started.Load() { - return nil, errors.New("eGo engine has not started") + x.locker.Lock() + started := x.started.Load() + x.locker.Unlock() + if !started { + return nil, ErrEngineNotStarted } - subscriber := x.eventStream.AddSubscriber() + x.locker.Lock() + eventStream := x.eventStream + x.locker.Unlock() + + subscriber := eventStream.AddSubscriber() for i := 0; i < int(x.partitionsCount); i++ { topic := fmt.Sprintf(eventsTopic, i) x.eventStream.Subscribe(subscriber, topic) @@ -186,3 +218,112 @@ func (x *Engine) Subscribe(ctx context.Context) (eventstream.Subscriber, error) return subscriber, nil } + +// Entity creates an entity. This will return the entity path +// that can be used to send command to the entity +func (x *Engine) Entity(ctx context.Context, behavior EntityBehavior) error { + x.locker.Lock() + started := x.started.Load() + x.locker.Unlock() + if !started { + return ErrEngineNotStarted + } + + x.locker.Lock() + actorSystem := x.actorSystem + eventsStore := x.eventsStore + eventStream := x.eventStream + x.locker.Unlock() + + _, err := actorSystem.Spawn(ctx, + behavior.ID(), + newActor(behavior, eventsStore, eventStream)) + if err != nil { + return err + } + + return nil +} + +// SendCommand sends command to a given entity ref. +// This will return: +// 1. the resulting state after the command has been handled and the emitted event persisted +// 2. nil when there is no resulting state or no event persisted +// 3. an error in case of error +func (x *Engine) SendCommand(ctx context.Context, entityID string, cmd Command, timeout time.Duration) (resultingState State, revision uint64, err error) { + ctx, span := egotel.SpanContext(ctx, "SendCommand") + defer span.End() + + x.locker.Lock() + started := x.started.Load() + x.locker.Unlock() + if !started { + return nil, 0, ErrEngineNotStarted + } + + // entityID is not defined + if entityID == "" { + return nil, 0, ErrUndefinedEntityID + } + + x.locker.Lock() + actorSystem := x.actorSystem + x.locker.Unlock() + + // locate the given actor + addr, pid, err := actorSystem.ActorOf(ctx, entityID) + if err != nil { + return nil, 0, err + } + + var reply proto.Message + if pid != nil { + // put the given command to the underlying actor of the entity + reply, err = actors.Ask(ctx, pid, cmd, timeout) + } else if addr != nil { + // send the command to the given address + res, err := actors.RemoteAsk(ctx, addr, cmd, timeout) + if err == nil { + // let us unmarshal the response + reply, err = res.UnmarshalNew() + } + } + + if err != nil { + return nil, 0, err + } + + // cast the reply as it supposes + commandReply, ok := reply.(*egopb.CommandReply) + if ok { + return parseCommandReply(commandReply) + } + return nil, 0, ErrCommandReplyUnmarshalling +} + +// parseCommandReply parses the command reply +func parseCommandReply(reply *egopb.CommandReply) (State, uint64, error) { + var ( + state State + err error + ) + + switch r := reply.GetReply().(type) { + case *egopb.CommandReply_StateReply: + msg, err := r.StateReply.GetState().UnmarshalNew() + if err != nil { + return state, 0, err + } + + switch v := msg.(type) { + case State: + return v, r.StateReply.GetSequenceNumber(), nil + default: + return state, 0, fmt.Errorf("got %s", r.StateReply.GetState().GetTypeUrl()) + } + case *egopb.CommandReply_ErrorReply: + err = errors.New(r.ErrorReply.GetMessage()) + return state, 0, err + } + return state, 0, errors.New("no state received") +} diff --git a/engine_test.go b/engine_test.go index 81eee67..6de9596 100644 --- a/engine_test.go +++ b/engine_test.go @@ -35,17 +35,18 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tochemey/goakt/v2/actors" "github.com/travisjeffery/go-dynaport" "google.golang.org/protobuf/proto" "github.com/tochemey/goakt/v2/log" mockdisco "github.com/tochemey/goakt/v2/mocks/discovery" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore/memory" - samplepb "github.com/tochemey/ego/v2/example/pbs/sample/pb/v1" - offsetstore "github.com/tochemey/ego/v2/offsetstore/memory" - "github.com/tochemey/ego/v2/projection" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore/memory" + samplepb "github.com/tochemey/ego/v3/example/pbs/sample/pb/v1" + offsetstore "github.com/tochemey/ego/v3/offsetstore/memory" + "github.com/tochemey/ego/v3/projection" ) func TestEgo(t *testing.T) { @@ -82,20 +83,20 @@ func TestEgo(t *testing.T) { // create a projection message handler handler := projection.NewDiscardHandler(log.DefaultLogger) // create the ego engine - e := NewEngine("Sample", eventStore, + engine := NewEngine("Sample", eventStore, WithCluster(provider, 4, 1, host, remotingPort, gossipPort, clusterPort)) // start ego engine - err := e.Start(ctx) + err := engine.Start(ctx) // wait for the cluster to fully start time.Sleep(time.Second) // add projection - err = e.AddProjection(ctx, "discard", handler, offsetStore) + err = engine.AddProjection(ctx, "discard", handler, offsetStore) require.NoError(t, err) // subscribe to events - subscriber, err := e.Subscribe(ctx) + subscriber, err := engine.Subscribe(ctx) require.NoError(t, err) require.NotNil(t, subscriber) @@ -105,7 +106,7 @@ func TestEgo(t *testing.T) { // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - entity, err := NewEntity[*samplepb.Account](ctx, behavior, e) + err = engine.Entity(ctx, behavior) require.NoError(t, err) // send some commands to the pid var command proto.Message @@ -119,11 +120,13 @@ func TestEgo(t *testing.T) { time.Sleep(time.Second) // send the command to the actor. Please don't ignore the error in production grid code - resultingState, revision, err := entity.SendCommand(ctx, command) + resultingState, revision, err := engine.SendCommand(ctx, entityID, command, time.Minute) require.NoError(t, err) + account, ok := resultingState.(*samplepb.Account) + require.True(t, ok) - assert.EqualValues(t, 500.00, resultingState.GetAccountBalance()) - assert.Equal(t, entityID, resultingState.GetAccountId()) + assert.EqualValues(t, 500.00, account.GetAccountBalance()) + assert.Equal(t, entityID, account.GetAccountId()) assert.EqualValues(t, 1, revision) // send another command to credit the balance @@ -131,11 +134,14 @@ func TestEgo(t *testing.T) { AccountId: entityID, Balance: 250, } - newState, revision, err := entity.SendCommand(ctx, command) + + newState, revision, err := engine.SendCommand(ctx, entityID, command, time.Minute) require.NoError(t, err) + newAccount, ok := newState.(*samplepb.Account) + require.True(t, ok) - assert.EqualValues(t, 750.00, newState.GetAccountBalance()) - assert.Equal(t, entityID, newState.GetAccountId()) + assert.EqualValues(t, 750.00, newAccount.GetAccountBalance()) + assert.Equal(t, entityID, newAccount.GetAccountId()) assert.EqualValues(t, 2, revision) for message := range subscriber.Iterator() { @@ -154,7 +160,7 @@ func TestEgo(t *testing.T) { // free resources assert.NoError(t, eventStore.Disconnect(ctx)) assert.NoError(t, offsetStore.Disconnect(ctx)) - assert.NoError(t, e.Stop(ctx)) + assert.NoError(t, engine.Stop(ctx)) }) t.Run("With no cluster enabled", func(t *testing.T) { ctx := context.TODO() @@ -163,16 +169,16 @@ func TestEgo(t *testing.T) { // connect to the event store require.NoError(t, eventStore.Connect(ctx)) // create the ego engine - e := NewEngine("Sample", eventStore) + engine := NewEngine("Sample", eventStore) // start ego engine - err := e.Start(ctx) + err := engine.Start(ctx) require.NoError(t, err) // create a persistence id entityID := uuid.NewString() // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - entity, err := NewEntity[*samplepb.Account](ctx, behavior, e) + err = engine.Entity(ctx, behavior) require.NoError(t, err) // send some commands to the pid var command proto.Message @@ -182,11 +188,13 @@ func TestEgo(t *testing.T) { AccountBalance: 500.00, } // send the command to the actor. Please don't ignore the error in production grid code - resultingState, revision, err := entity.SendCommand(ctx, command) + resultingState, revision, err := engine.SendCommand(ctx, entityID, command, time.Minute) require.NoError(t, err) + account, ok := resultingState.(*samplepb.Account) + require.True(t, ok) - assert.EqualValues(t, 500.00, resultingState.GetAccountBalance()) - assert.Equal(t, entityID, resultingState.GetAccountId()) + assert.EqualValues(t, 500.00, account.GetAccountBalance()) + assert.Equal(t, entityID, account.GetAccountId()) assert.EqualValues(t, 1, revision) // send another command to credit the balance @@ -194,16 +202,77 @@ func TestEgo(t *testing.T) { AccountId: entityID, Balance: 250, } - newState, revision, err := entity.SendCommand(ctx, command) + newState, revision, err := engine.SendCommand(ctx, entityID, command, time.Minute) require.NoError(t, err) + newAccount, ok := newState.(*samplepb.Account) + require.True(t, ok) - assert.EqualValues(t, 750.00, newState.GetAccountBalance()) - assert.Equal(t, entityID, newState.GetAccountId()) + assert.EqualValues(t, 750.00, newAccount.GetAccountBalance()) + assert.Equal(t, entityID, newAccount.GetAccountId()) assert.EqualValues(t, 2, revision) // free resources assert.NoError(t, eventStore.Disconnect(ctx)) - assert.NoError(t, e.Stop(ctx)) + assert.NoError(t, engine.Stop(ctx)) + }) + t.Run("With SendCommand when not started", func(t *testing.T) { + ctx := context.TODO() + // create the event store + eventStore := memory.NewEventsStore() + require.NoError(t, eventStore.Connect(ctx)) + + // create the ego engine + engine := NewEngine("Sample", eventStore) + // create a persistence id + entityID := uuid.NewString() + + _, _, err := engine.SendCommand(ctx, entityID, new(samplepb.CreateAccount), time.Minute) + require.Error(t, err) + assert.EqualError(t, err, ErrEngineNotStarted.Error()) + + assert.NoError(t, eventStore.Disconnect(ctx)) + }) + t.Run("With SendCommand when entityID is not set", func(t *testing.T) { + ctx := context.TODO() + // create the event store + eventStore := memory.NewEventsStore() + require.NoError(t, eventStore.Connect(ctx)) + + // create the ego engine + engine := NewEngine("Sample", eventStore) + err := engine.Start(ctx) + require.NoError(t, err) + + // create a persistence id + entityID := "" + + _, _, err = engine.SendCommand(ctx, entityID, new(samplepb.CreateAccount), time.Minute) + require.Error(t, err) + assert.EqualError(t, err, ErrUndefinedEntityID.Error()) + + assert.NoError(t, eventStore.Disconnect(ctx)) + assert.NoError(t, engine.Stop(ctx)) + }) + t.Run("With SendCommand when entity is not found", func(t *testing.T) { + ctx := context.TODO() + // create the event store + eventStore := memory.NewEventsStore() + require.NoError(t, eventStore.Connect(ctx)) + + // create the ego engine + engine := NewEngine("Sample", eventStore) + err := engine.Start(ctx) + require.NoError(t, err) + + // create a persistence id + entityID := uuid.NewString() + + _, _, err = engine.SendCommand(ctx, entityID, new(samplepb.CreateAccount), time.Minute) + require.Error(t, err) + assert.EqualError(t, err, actors.ErrActorNotFound(entityID).Error()) + + assert.NoError(t, eventStore.Disconnect(ctx)) + assert.NoError(t, engine.Stop(ctx)) }) } @@ -213,7 +282,7 @@ type AccountBehavior struct { } // make sure that AccountBehavior is a true persistence behavior -var _ EntityBehavior[*samplepb.Account] = &AccountBehavior{} +var _ EntityBehavior = &AccountBehavior{} // NewAccountBehavior creates an instance of AccountBehavior func NewAccountBehavior(id string) *AccountBehavior { @@ -226,12 +295,12 @@ func (a *AccountBehavior) ID() string { } // InitialState returns the initial state -func (a *AccountBehavior) InitialState() *samplepb.Account { - return new(samplepb.Account) +func (a *AccountBehavior) InitialState() State { + return State(new(samplepb.Account)) } // HandleCommand handles every command that is sent to the persistent behavior -func (a *AccountBehavior) HandleCommand(_ context.Context, command Command, _ *samplepb.Account) (events []Event, err error) { +func (a *AccountBehavior) HandleCommand(_ context.Context, command Command, _ State) (events []Event, err error) { switch cmd := command.(type) { case *samplepb.CreateAccount: // TODO in production grid app validate the command using the prior state @@ -257,7 +326,7 @@ func (a *AccountBehavior) HandleCommand(_ context.Context, command Command, _ *s } // HandleEvent handles every event emitted -func (a *AccountBehavior) HandleEvent(_ context.Context, event Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { +func (a *AccountBehavior) HandleEvent(_ context.Context, event Event, priorState State) (state State, err error) { switch evt := event.(type) { case *samplepb.AccountCreated: return &samplepb.Account{ @@ -266,7 +335,8 @@ func (a *AccountBehavior) HandleEvent(_ context.Context, event Event, priorState }, nil case *samplepb.AccountCredited: - bal := priorState.GetAccountBalance() + evt.GetAccountBalance() + account := priorState.(*samplepb.Account) + bal := account.GetAccountBalance() + evt.GetAccountBalance() return &samplepb.Account{ AccountId: evt.GetAccountId(), AccountBalance: bal, diff --git a/entity.go b/entity.go deleted file mode 100644 index 5e346db..0000000 --- a/entity.go +++ /dev/null @@ -1,122 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-2024 Tochemey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package ego - -import ( - "context" - "fmt" - "time" - - "github.com/pkg/errors" - - "github.com/tochemey/goakt/v2/actors" - - "github.com/tochemey/ego/v2/egopb" -) - -var ( - // ErrEngineRequired is returned when the eGo engine is not set - ErrEngineRequired = errors.New("eGo engine is not defined") - // ErrEngineNotStarted is returned when the eGo engine has not started - ErrEngineNotStarted = errors.New("eGo engine has not started") - // ErrUndefinedEntity is returned when sending a command to an undefined entity - ErrUndefinedEntity = errors.New("eGo entity is not defined") -) - -// Entity defines the event sourced persistent entity -// This handles commands in order -type Entity[T State] struct { - actor actors.PID -} - -// NewEntity creates an instance of Entity -func NewEntity[T State](ctx context.Context, behavior EntityBehavior[T], engine *Engine) (*Entity[T], error) { - if engine == nil { - return nil, ErrEngineRequired - } - - if !engine.started.Load() { - return nil, ErrEngineNotStarted - } - - pid, err := engine.actorSystem.Spawn(ctx, behavior.ID(), newActor(behavior, engine.eventsStore, engine.eventStream)) - if err != nil { - return nil, err - } - return &Entity[T]{ - actor: pid, - }, nil -} - -// SendCommand sends command to a given entity ref. This will return: -// 1. the resulting state after the command has been handled and the emitted event persisted -// 2. nil when there is no resulting state or no event persisted -// 3. an error in case of error -func (x Entity[T]) SendCommand(ctx context.Context, command Command) (resultingState T, revision uint64, err error) { - var nilOfT T - - if x.actor == nil || !x.actor.IsRunning() { - return nilOfT, 0, ErrUndefinedEntity - } - - reply, err := actors.Ask(ctx, x.actor, command, time.Second) - if err != nil { - return nilOfT, 0, err - } - - commandReply, ok := reply.(*egopb.CommandReply) - if ok { - return parseCommandReply[T](commandReply) - } - - return nilOfT, 0, errors.New("failed to parse command reply") -} - -// parseCommandReply parses the command reply -func parseCommandReply[T State](reply *egopb.CommandReply) (T, uint64, error) { - var ( - state T - err error - ) - - switch r := reply.GetReply().(type) { - case *egopb.CommandReply_StateReply: - msg, err := r.StateReply.GetState().UnmarshalNew() - if err != nil { - return state, 0, err - } - - switch v := msg.(type) { - case T: - return v, r.StateReply.GetSequenceNumber(), nil - default: - return state, 0, fmt.Errorf("got %s", r.StateReply.GetState().GetTypeUrl()) - } - case *egopb.CommandReply_ErrorReply: - err = errors.New(r.ErrorReply.GetMessage()) - return state, 0, err - } - return state, 0, errors.New("no state received") -} diff --git a/entity_test.go b/entity_test.go deleted file mode 100644 index 96a3cf2..0000000 --- a/entity_test.go +++ /dev/null @@ -1,74 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2022-2024 Tochemey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package ego - -import ( - "context" - "testing" - - "github.com/google/uuid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/tochemey/ego/v2/eventstore/memory" - samplepb "github.com/tochemey/ego/v2/example/pbs/sample/pb/v1" -) - -func TestNewEntity(t *testing.T) { - t.Run("With engine not defined", func(t *testing.T) { - ctx := context.TODO() - behavior := NewAccountBehavior(uuid.NewString()) - // create an entity - entity, err := NewEntity[*samplepb.Account](ctx, behavior, nil) - require.Error(t, err) - require.Nil(t, entity) - assert.EqualError(t, err, ErrEngineRequired.Error()) - }) - t.Run("With engine not started", func(t *testing.T) { - ctx := context.TODO() - // create the event store - eventStore := memory.NewEventsStore() - // create the ego engine - engine := NewEngine("Sample", eventStore) - behavior := NewAccountBehavior(uuid.NewString()) - // create an entity - entity, err := NewEntity[*samplepb.Account](ctx, behavior, engine) - require.Error(t, err) - require.Nil(t, entity) - assert.EqualError(t, err, ErrEngineNotStarted.Error()) - }) -} - -func TestSendCommand(t *testing.T) { - t.Run("With entity not defined", func(t *testing.T) { - ctx := context.TODO() - entity := &Entity[*samplepb.Account]{} - resultingState, revision, err := entity.SendCommand(ctx, new(samplepb.CreateAccount)) - require.Nil(t, resultingState) - require.Zero(t, revision) - require.Error(t, err) - assert.EqualError(t, err, ErrUndefinedEntity.Error()) - }) -} diff --git a/eventstore/iface.go b/eventstore/iface.go index d42cd92..004a885 100644 --- a/eventstore/iface.go +++ b/eventstore/iface.go @@ -27,7 +27,7 @@ package eventstore import ( "context" - "github.com/tochemey/ego/v2/egopb" + "github.com/tochemey/ego/v3/egopb" ) // EventsStore defines the API to write to the events store diff --git a/eventstore/memory/memory.go b/eventstore/memory/memory.go index d42e14c..2e54aa2 100644 --- a/eventstore/memory/memory.go +++ b/eventstore/memory/memory.go @@ -39,9 +39,9 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/known/anypb" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/internal/telemetry" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/internal/telemetry" ) // EventsStore keep in memory every journal diff --git a/eventstore/memory/memory_test.go b/eventstore/memory/memory_test.go index 593902d..a75669a 100644 --- a/eventstore/memory/memory_test.go +++ b/eventstore/memory/memory_test.go @@ -35,9 +35,9 @@ import ( "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/timestamppb" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) func TestEventsStore(t *testing.T) { diff --git a/eventstore/postgres/postgres.go b/eventstore/postgres/postgres.go index b0127eb..af3cd28 100644 --- a/eventstore/postgres/postgres.go +++ b/eventstore/postgres/postgres.go @@ -35,9 +35,9 @@ import ( "github.com/tochemey/gopack/postgres" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/internal/telemetry" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/internal/telemetry" ) var ( diff --git a/eventstore/postgres/postgres_test.go b/eventstore/postgres/postgres_test.go index 3bb729c..82ddcb5 100644 --- a/eventstore/postgres/postgres_test.go +++ b/eventstore/postgres/postgres_test.go @@ -37,9 +37,9 @@ import ( "github.com/tochemey/gopack/postgres" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) func TestPostgresEventsStore(t *testing.T) { diff --git a/eventstore/postgres/row.go b/eventstore/postgres/row.go index 698f4dd..bb9d0c4 100644 --- a/eventstore/postgres/row.go +++ b/eventstore/postgres/row.go @@ -33,7 +33,7 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/known/anypb" - "github.com/tochemey/ego/v2/egopb" + "github.com/tochemey/ego/v3/egopb" ) // row represents the events store row diff --git a/eventstream/subscriber.go b/eventstream/subscriber.go index 0ed2cf2..69a2c3d 100644 --- a/eventstream/subscriber.go +++ b/eventstream/subscriber.go @@ -29,7 +29,7 @@ import ( "github.com/google/uuid" - "github.com/tochemey/ego/v2/internal/queue" + "github.com/tochemey/ego/v3/internal/queue" ) // Subscriber defines the Subscriber Interface diff --git a/example/main.go b/example/main.go index 922129e..498661c 100644 --- a/example/main.go +++ b/example/main.go @@ -31,13 +31,14 @@ import ( "os" "os/signal" "syscall" + "time" "github.com/google/uuid" "google.golang.org/protobuf/proto" - "github.com/tochemey/ego/v2" - "github.com/tochemey/ego/v2/eventstore/memory" - samplepb "github.com/tochemey/ego/v2/example/pbs/sample/pb/v1" + "github.com/tochemey/ego/v3" + "github.com/tochemey/ego/v3/eventstore/memory" + samplepb "github.com/tochemey/ego/v3/example/pbs/sample/pb/v1" ) func main() { @@ -48,15 +49,15 @@ func main() { // connect the event store _ = eventStore.Connect(ctx) // create the ego engine - e := ego.NewEngine("Sample", eventStore) + engine := ego.NewEngine("Sample", eventStore) // start ego engine - _ = e.Start(ctx) + _ = engine.Start(ctx) // create a persistence id entityID := uuid.NewString() // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - entity, _ := ego.NewEntity[*samplepb.Account](ctx, behavior, e) + _ = engine.Entity(ctx, behavior) // send some commands to the pid var command proto.Message @@ -66,8 +67,8 @@ func main() { AccountBalance: 500.00, } // send the command to the actor. Please don't ignore the error in production grid code - account, _, _ := entity.SendCommand(ctx, command) - + reply, _, _ := engine.SendCommand(ctx, entityID, command, time.Minute) + account := reply.(*samplepb.Account) log.Printf("current balance: %v", account.GetAccountBalance()) // send another command to credit the balance @@ -75,7 +76,9 @@ func main() { AccountId: entityID, Balance: 250, } - account, _, _ = entity.SendCommand(ctx, command) + + reply, _, _ = engine.SendCommand(ctx, entityID, command, time.Minute) + account = reply.(*samplepb.Account) log.Printf("current balance: %v", account.GetAccountBalance()) // capture ctrl+c @@ -86,7 +89,7 @@ func main() { // disconnect the event store _ = eventStore.Disconnect(ctx) // stop the actor system - _ = e.Stop(ctx) + _ = engine.Stop(ctx) os.Exit(0) } @@ -96,7 +99,7 @@ type AccountBehavior struct { } // make sure that AccountBehavior is a true persistence behavior -var _ ego.EntityBehavior[*samplepb.Account] = &AccountBehavior{} +var _ ego.EntityBehavior = &AccountBehavior{} // NewAccountBehavior creates an instance of AccountBehavior func NewAccountBehavior(id string) *AccountBehavior { @@ -109,12 +112,12 @@ func (a *AccountBehavior) ID() string { } // InitialState returns the initial state -func (a *AccountBehavior) InitialState() *samplepb.Account { - return new(samplepb.Account) +func (a *AccountBehavior) InitialState() ego.State { + return ego.State(new(samplepb.Account)) } // HandleCommand handles every command that is sent to the persistent behavior -func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, _ *samplepb.Account) (events []ego.Event, err error) { +func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, _ ego.State) (events []ego.Event, err error) { switch cmd := command.(type) { case *samplepb.CreateAccount: // TODO in production grid app validate the command using the prior state @@ -140,7 +143,7 @@ func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, } // HandleEvent handles every event emitted -func (a *AccountBehavior) HandleEvent(_ context.Context, event ego.Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { +func (a *AccountBehavior) HandleEvent(_ context.Context, event ego.Event, priorState ego.State) (state ego.State, err error) { switch evt := event.(type) { case *samplepb.AccountCreated: return &samplepb.Account{ @@ -149,7 +152,8 @@ func (a *AccountBehavior) HandleEvent(_ context.Context, event ego.Event, priorS }, nil case *samplepb.AccountCredited: - bal := priorState.GetAccountBalance() + evt.GetAccountBalance() + account := priorState.(*samplepb.Account) + bal := account.GetAccountBalance() + evt.GetAccountBalance() return &samplepb.Account{ AccountId: evt.GetAccountId(), AccountBalance: bal, diff --git a/example/pbs/sample/pb/v1/sample.pb.go b/example/pbs/sample/pb/v1/sample.pb.go index 7921454..f1c0a70 100644 --- a/example/pbs/sample/pb/v1/sample.pb.go +++ b/example/pbs/sample/pb/v1/sample.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v2.31.0 +// protoc-gen-go v1.31.0 // protoc (unknown) -// source: sample/pb/v2/sample.proto +// source: sample/pb/v1/sample.proto package samplepb @@ -451,13 +451,13 @@ func file_sample_pb_v1_sample_proto_rawDescGZIP() []byte { var file_sample_pb_v1_sample_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_sample_pb_v1_sample_proto_goTypes = []interface{}{ - (*Ping)(nil), // 0: sample.v2.Ping - (*Pong)(nil), // 1: sample.v2.Pong - (*Account)(nil), // 2: sample.v2.Account - (*CreateAccount)(nil), // 3: sample.v2.CreateAccount - (*CreditAccount)(nil), // 4: sample.v2.CreditAccount - (*AccountCreated)(nil), // 5: sample.v2.AccountCreated - (*AccountCredited)(nil), // 6: sample.v2.AccountCredited + (*Ping)(nil), // 0: sample.v1.Ping + (*Pong)(nil), // 1: sample.v1.Pong + (*Account)(nil), // 2: sample.v1.Account + (*CreateAccount)(nil), // 3: sample.v1.CreateAccount + (*CreditAccount)(nil), // 4: sample.v1.CreditAccount + (*AccountCreated)(nil), // 5: sample.v1.AccountCreated + (*AccountCredited)(nil), // 6: sample.v1.AccountCredited } var file_sample_pb_v1_sample_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type diff --git a/go.mod b/go.mod index 5c51d27..724c69c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/tochemey/ego/v2 +module github.com/tochemey/ego/v3 go 1.22.0 @@ -10,11 +10,11 @@ require ( github.com/hashicorp/go-memdb v1.3.4 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 - github.com/tochemey/goakt/v2 v2.2.2 + github.com/tochemey/goakt/v2 v2.3.1 github.com/tochemey/gopack v0.0.0-20240303193017-58b82904de1b github.com/travisjeffery/go-dynaport v1.0.0 - go.opentelemetry.io/otel v1.27.0 - go.opentelemetry.io/otel/trace v1.27.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/atomic v1.11.0 go.uber.org/goleak v1.3.0 golang.org/x/sync v0.7.0 @@ -88,7 +88,7 @@ require ( github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/mod v0.18.0 // indirect diff --git a/go.sum b/go.sum index 3f1dbe9..6c5530a 100644 --- a/go.sum +++ b/go.sum @@ -231,8 +231,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt/v2 v2.5.7 h1:j5lH1fUXCnJnY8SsQeB/a/z9Azgu2bYIDvtPVNdxe2c= github.com/nats-io/jwt/v2 v2.5.7/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A= -github.com/nats-io/nats-server/v2 v2.10.16 h1:2jXaiydp5oB/nAx/Ytf9fdCi9QN6ItIc9eehX8kwVV0= -github.com/nats-io/nats-server/v2 v2.10.16/go.mod h1:Pksi38H2+6xLe1vQx0/EA4bzetM0NqyIHcIbmgXSkIU= +github.com/nats-io/nats-server/v2 v2.10.17 h1:PTVObNBD3TZSNUDgzFb1qQsQX4mOgFmOuG9vhT+KBUY= +github.com/nats-io/nats-server/v2 v2.10.17/go.mod h1:5OUyc4zg42s/p2i92zbbqXvUNsbF0ivdTLKshVMn2YQ= github.com/nats-io/nats.go v1.36.0 h1:suEUPuWzTSse/XhESwqLxXGuj8vGRuPRoG7MoRN/qyU= github.com/nats-io/nats.go v1.36.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= @@ -314,8 +314,8 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/redcon v1.6.2 h1:5qfvrrybgtO85jnhSravmkZyC0D+7WstbfCs3MmPhow= github.com/tidwall/redcon v1.6.2/go.mod h1:p5Wbsgeyi2VSTBWOcA5vRXrOb9arFTcU2+ZzFjqV75Y= -github.com/tochemey/goakt/v2 v2.2.2 h1:sbNLp1tzdbrN8j00ukuq8bVkvSg1eEw+tG44pEwIiHY= -github.com/tochemey/goakt/v2 v2.2.2/go.mod h1:++f4bMsmaybNAcc5tUu/WYaEGEdrHiK37FnGusWeSMY= +github.com/tochemey/goakt/v2 v2.3.1 h1:BZOLDvnV0ToAlFZHstqNNXVw+dbSG2FaUf4OL8gtw8U= +github.com/tochemey/goakt/v2 v2.3.1/go.mod h1:YsKrJoegoqBrhGMHBQgzThZTzLp/B68ZYm/mnPzDDWU= github.com/tochemey/gopack v0.0.0-20240303193017-58b82904de1b h1:OsgVtcoRL6V8ismMIwG9XSfFG73oC9U6XWgTECoTit0= github.com/tochemey/gopack v0.0.0-20240303193017-58b82904de1b/go.mod h1:EeuLasIUo0sW+3lk5yTi4xkjknXZOZ4B3tUX5pvMDQI= github.com/travisjeffery/go-dynaport v1.0.0 h1:m/qqf5AHgB96CMMSworIPyo1i7NZueRsnwdzdCJ8Ajw= @@ -332,16 +332,16 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= diff --git a/helper_test.go b/helper_test.go index abb6f52..4324f97 100644 --- a/helper_test.go +++ b/helper_test.go @@ -30,7 +30,7 @@ import ( "github.com/pkg/errors" "google.golang.org/protobuf/types/known/emptypb" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) // AccountEntityBehavior implement EntityBehavior @@ -39,7 +39,7 @@ type AccountEntityBehavior struct { } // make sure that testAccountBehavior is a true persistence behavior -var _ EntityBehavior[*testpb.Account] = &AccountEntityBehavior{} +var _ EntityBehavior = (*AccountEntityBehavior)(nil) // NewAccountEntityBehavior creates an instance of AccountEntityBehavior func NewAccountEntityBehavior(id string) *AccountEntityBehavior { @@ -49,11 +49,11 @@ func (t *AccountEntityBehavior) ID() string { return t.id } -func (t *AccountEntityBehavior) InitialState() *testpb.Account { +func (t *AccountEntityBehavior) InitialState() State { return new(testpb.Account) } -func (t *AccountEntityBehavior) HandleCommand(_ context.Context, command Command, _ *testpb.Account) (events []Event, err error) { +func (t *AccountEntityBehavior) HandleCommand(_ context.Context, command Command, _ State) (events []Event, err error) { switch cmd := command.(type) { case *testpb.CreateAccount: // TODO in production grid app validate the command using the prior state @@ -87,7 +87,7 @@ func (t *AccountEntityBehavior) HandleCommand(_ context.Context, command Command } } -func (t *AccountEntityBehavior) HandleEvent(_ context.Context, event Event, priorState *testpb.Account) (state *testpb.Account, err error) { +func (t *AccountEntityBehavior) HandleEvent(_ context.Context, event Event, priorState State) (state State, err error) { switch evt := event.(type) { case *testpb.AccountCreated: return &testpb.Account{ @@ -96,7 +96,9 @@ func (t *AccountEntityBehavior) HandleEvent(_ context.Context, event Event, prio }, nil case *testpb.AccountCredited: - bal := priorState.GetAccountBalance() + evt.GetAccountBalance() + // we can safely cast the prior state to Account + account := priorState.(*testpb.Account) + bal := account.GetAccountBalance() + evt.GetAccountBalance() return &testpb.Account{ AccountId: evt.GetAccountId(), AccountBalance: bal, diff --git a/offsetstore/iface.go b/offsetstore/iface.go index 5917ae2..bcc01e2 100644 --- a/offsetstore/iface.go +++ b/offsetstore/iface.go @@ -27,7 +27,7 @@ package offsetstore import ( "context" - "github.com/tochemey/ego/v2/egopb" + "github.com/tochemey/ego/v3/egopb" ) // OffsetStore defines the contract needed to persist offsets diff --git a/offsetstore/memory/memory.go b/offsetstore/memory/memory.go index 81414ff..c2adb6b 100644 --- a/offsetstore/memory/memory.go +++ b/offsetstore/memory/memory.go @@ -34,9 +34,9 @@ import ( "github.com/pkg/errors" "go.uber.org/atomic" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/internal/telemetry" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/internal/telemetry" + "github.com/tochemey/ego/v3/offsetstore" ) // OffsetStore implements the offset store interface diff --git a/offsetstore/memory/memory_test.go b/offsetstore/memory/memory_test.go index b1fad8f..3550f44 100644 --- a/offsetstore/memory/memory_test.go +++ b/offsetstore/memory/memory_test.go @@ -33,8 +33,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/offsetstore" ) func TestOffsetStore(t *testing.T) { diff --git a/offsetstore/postgres/postgres.go b/offsetstore/postgres/postgres.go index 3cac605..6ce1a2b 100644 --- a/offsetstore/postgres/postgres.go +++ b/offsetstore/postgres/postgres.go @@ -36,9 +36,9 @@ import ( "github.com/tochemey/gopack/postgres" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/internal/telemetry" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/internal/telemetry" + "github.com/tochemey/ego/v3/offsetstore" ) var ( diff --git a/offsetstore/postgres/postgres_test.go b/offsetstore/postgres/postgres_test.go index 254f846..56dd4c7 100644 --- a/offsetstore/postgres/postgres_test.go +++ b/offsetstore/postgres/postgres_test.go @@ -35,8 +35,8 @@ import ( "github.com/tochemey/gopack/postgres" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/offsetstore" ) func TestPostgresOffsetStore(t *testing.T) { diff --git a/projection/actor.go b/projection/actor.go index 323a4ea..a9ae9ce 100644 --- a/projection/actor.go +++ b/projection/actor.go @@ -32,8 +32,8 @@ import ( "github.com/tochemey/goakt/v2/actors" "github.com/tochemey/goakt/v2/goaktpb" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/offsetstore" ) // Start is used to start the projection diff --git a/projection/actor_test.go b/projection/actor_test.go index 3a48f3e..4d24a1c 100644 --- a/projection/actor_test.go +++ b/projection/actor_test.go @@ -39,10 +39,10 @@ import ( "github.com/tochemey/goakt/v2/actors" "github.com/tochemey/goakt/v2/log" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore/memory" - memoffsetstore "github.com/tochemey/ego/v2/offsetstore/memory" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore/memory" + memoffsetstore "github.com/tochemey/ego/v3/offsetstore/memory" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) func TestActor(t *testing.T) { diff --git a/projection/runner.go b/projection/runner.go index 9832ea0..744d165 100644 --- a/projection/runner.go +++ b/projection/runner.go @@ -37,10 +37,10 @@ import ( "github.com/tochemey/goakt/v2/log" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore" - "github.com/tochemey/ego/v2/internal/telemetry" - "github.com/tochemey/ego/v2/offsetstore" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore" + "github.com/tochemey/ego/v3/internal/telemetry" + "github.com/tochemey/ego/v3/offsetstore" ) // runner defines the projection runner diff --git a/projection/runner_test.go b/projection/runner_test.go index 9e39e28..7d180e6 100644 --- a/projection/runner_test.go +++ b/projection/runner_test.go @@ -40,10 +40,10 @@ import ( "github.com/tochemey/goakt/v2/log" - "github.com/tochemey/ego/v2/egopb" - "github.com/tochemey/ego/v2/eventstore/memory" - memoffsetstore "github.com/tochemey/ego/v2/offsetstore/memory" - testpb "github.com/tochemey/ego/v2/test/data/pb/v1" + "github.com/tochemey/ego/v3/egopb" + "github.com/tochemey/ego/v3/eventstore/memory" + memoffsetstore "github.com/tochemey/ego/v3/offsetstore/memory" + testpb "github.com/tochemey/ego/v3/test/data/pb/v3" ) func TestProjection(t *testing.T) { diff --git a/protos/ego/v2/ego.proto b/protos/ego/v3/ego.proto similarity index 97% rename from protos/ego/v2/ego.proto rename to protos/ego/v3/ego.proto index 16df8af..9a5671c 100644 --- a/protos/ego/v2/ego.proto +++ b/protos/ego/v3/ego.proto @@ -4,7 +4,7 @@ package ego.v1; import "google/protobuf/any.proto"; -option go_package = "github.com/tochemey/ego/v2;egopb"; +option go_package = "github.com/tochemey/ego/v3;egopb"; // Event defines the event that needs to be persisted onto the events store message Event { diff --git a/protos/test/pb/v2/test.proto b/protos/test/pb/v3/test.proto similarity index 87% rename from protos/test/pb/v2/test.proto rename to protos/test/pb/v3/test.proto index d596a6f..73083be 100644 --- a/protos/test/pb/v2/test.proto +++ b/protos/test/pb/v3/test.proto @@ -1,8 +1,8 @@ syntax = "proto3"; -package tests.v1; +package tests.v3; -option go_package = "github.com/tochemey/ego/tests/v2;testpb"; +option go_package = "github.com/tochemey/ego/tests/v3;testpb"; message TestReply {} message TestPanic {} diff --git a/readme.md b/readme.md index ec27aea..c58b1b6 100644 --- a/readme.md +++ b/readme.md @@ -32,7 +32,7 @@ To define an Aggregate Root, one needs to: 1. the state of the aggregate root using google protocol buffers message 2. the various commands that will be handled by the aggregate root 3. the various events that are result of the command handlers and that will be handled by the aggregate root to return the new state of the aggregate root -2. implements the [`EntityBehavior[T State]`](./behavior.go) interface where T is the generated golang struct of the prior defined aggregate root state. +2. implements the [`EntityBehavior`](./behavior.go) interface. #### Events Stream @@ -75,135 +75,145 @@ go get github.com/tochemey/ego package main import ( - "context" - "errors" - "log" - "os" - "os/signal" - "syscall" - - "github.com/google/uuid" - "github.com/tochemey/ego" - "github.com/tochemey/ego/eventstore/memory" - samplepb "github.com/tochemey/ego/example/pbs/sample/pb/v2" - "google.golang.org/protobuf/proto" + "context" + "errors" + "log" + "os" + "os/signal" + "syscall" + "time" + + "github.com/google/uuid" + "google.golang.org/protobuf/proto" + + "github.com/tochemey/ego/v3" + "github.com/tochemey/ego/v3/eventstore/memory" + samplepb "github.com/tochemey/ego/v3/example/pbs/sample/pb/v1" ) func main() { - // create the go context - ctx := context.Background() - // create the event store - eventStore := memory.NewEventsStore() - // create the ego engine - e := ego.NewEngine("Sample", eventStore) - // start ego engine - _ = e.Start(ctx) - // create a persistence id - entityID := uuid.NewString() - // create an entity behavior with a given id - behavior := NewAccountBehavior(entityID) - // create an entity - entity, _ := ego.NewEntity[*samplepb.Account](ctx, behavior, e) - - // send some commands to the pid - var command proto.Message - // create an account - command = &samplepb.CreateAccount{ - AccountId: entityID, - AccountBalance: 500.00, - } - // send the command to the entity. Please don't ignore the error in production grid code - account, _, _ := entity.SendCommand(ctx, command) - - log.Printf("current balance: %v", account.GetAccountBalance()) - - // send another command to credit the balance - command = &samplepb.CreditAccount{ - AccountId: entityID, - Balance: 250, - } - account, _, _ = entity.SendCommand(ctx, command) - log.Printf("current balance: %v", account.GetAccountBalance()) - - // capture ctrl+c - interruptSignal := make(chan os.Signal, 1) - signal.Notify(interruptSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - <-interruptSignal - - // stop the ego engine - _ = e.Stop(ctx) - os.Exit(0) + // create the go context + ctx := context.Background() + // create the event store + eventStore := memory.NewEventsStore() + // connect the event store + _ = eventStore.Connect(ctx) + // create the ego engine + engine := ego.NewEngine("Sample", eventStore) + // start ego engine + _ = engine.Start(ctx) + // create a persistence id + entityID := uuid.NewString() + // create an entity behavior with a given id + behavior := NewAccountBehavior(entityID) + // create an entity + _ = engine.Entity(ctx, behavior) + + // send some commands to the pid + var command proto.Message + // create an account + command = &samplepb.CreateAccount{ + AccountId: entityID, + AccountBalance: 500.00, + } + // send the command to the actor. Please don't ignore the error in production grid code + reply, _, _ := engine.SendCommand(ctx, entityID, command, time.Minute) + account := reply.(*samplepb.Account) + log.Printf("current balance: %v", account.GetAccountBalance()) + + // send another command to credit the balance + command = &samplepb.CreditAccount{ + AccountId: entityID, + Balance: 250, + } + + reply, _, _ = engine.SendCommand(ctx, entityID, command, time.Minute) + account = reply.(*samplepb.Account) + log.Printf("current balance: %v", account.GetAccountBalance()) + + // capture ctrl+c + interruptSignal := make(chan os.Signal, 1) + signal.Notify(interruptSignal, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + <-interruptSignal + + // disconnect the event store + _ = eventStore.Disconnect(ctx) + // stop the actor system + _ = engine.Stop(ctx) + os.Exit(0) } // AccountBehavior implements EntityBehavior type AccountBehavior struct { - id string + id string } // make sure that AccountBehavior is a true persistence behavior -var _ ego.EntityBehavior[*samplepb.Account] = &AccountBehavior{} +var _ ego.EntityBehavior = (*AccountBehavior)(nil) // NewAccountBehavior creates an instance of AccountBehavior func NewAccountBehavior(id string) *AccountBehavior { - return &AccountBehavior{id: id} + return &AccountBehavior{id: id} } // ID returns the id func (a *AccountBehavior) ID() string { - return a.id + return a.id } // InitialState returns the initial state -func (a *AccountBehavior) InitialState() *samplepb.Account { - return new(samplepb.Account) +func (a *AccountBehavior) InitialState() ego.State { + return ego.State(new(samplepb.Account)) } // HandleCommand handles every command that is sent to the persistent behavior -func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, _ *samplepb.Account) (events []ego.Event, err error) { - switch cmd := command.(type) { - case *samplepb.CreateAccount: - // TODO in production grid app validate the command using the prior state - return []ego.Event{ - &samplepb.AccountCreated{ - AccountId: cmd.GetAccountId(), - AccountBalance: cmd.GetAccountBalance(), - }, - }, nil - - case *samplepb.CreditAccount: - // TODO in production grid app validate the command using the prior state - return []ego.Event{ - &samplepb.AccountCredited{ - AccountId: cmd.GetAccountId(), - AccountBalance: cmd.GetBalance(), - }, - }, nil - - default: - return nil, errors.New("unhandled command") - } +func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, _ ego.State) (events []ego.Event, err error) { + switch cmd := command.(type) { + case *samplepb.CreateAccount: + // TODO in production grid app validate the command using the prior state + return []ego.Event{ + &samplepb.AccountCreated{ + AccountId: cmd.GetAccountId(), + AccountBalance: cmd.GetAccountBalance(), + }, + }, nil + + case *samplepb.CreditAccount: + // TODO in production grid app validate the command using the prior state + return []ego.Event{ + &samplepb.AccountCredited{ + AccountId: cmd.GetAccountId(), + AccountBalance: cmd.GetBalance(), + }, + }, nil + + default: + return nil, errors.New("unhandled command") + } } // HandleEvent handles every event emitted -func (a *AccountBehavior) HandleEvent(_ context.Context, event ego.Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { - switch evt := event.(type) { - case *samplepb.AccountCreated: - return &samplepb.Account{ - AccountId: evt.GetAccountId(), - AccountBalance: evt.GetAccountBalance(), - }, nil - - case *samplepb.AccountCredited: - bal := priorState.GetAccountBalance() + evt.GetAccountBalance() - return &samplepb.Account{ - AccountId: evt.GetAccountId(), - AccountBalance: bal, - }, nil - - default: - return nil, errors.New("unhandled event") - } +func (a *AccountBehavior) HandleEvent(_ context.Context, event ego.Event, priorState ego.State) (state ego.State, err error) { + switch evt := event.(type) { + case *samplepb.AccountCreated: + return &samplepb.Account{ + AccountId: evt.GetAccountId(), + AccountBalance: evt.GetAccountBalance(), + }, nil + + case *samplepb.AccountCredited: + account := priorState.(*samplepb.Account) + bal := account.GetAccountBalance() + evt.GetAccountBalance() + return &samplepb.Account{ + AccountId: evt.GetAccountId(), + AccountBalance: bal, + }, nil + + default: + return nil, errors.New("unhandled event") + } } + ``` diff --git a/test/data/pb/v1/test.pb.go b/test/data/pb/v3/test.pb.go similarity index 79% rename from test/data/pb/v1/test.pb.go rename to test/data/pb/v3/test.pb.go index ba3d2e4..70adbd6 100644 --- a/test/data/pb/v1/test.pb.go +++ b/test/data/pb/v3/test.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v2.31.0 +// protoc-gen-go v1.31.0 // protoc (unknown) -// source: test/pb/v2/test.proto +// source: test/pb/v3/test.proto package testpb @@ -29,7 +29,7 @@ type TestReply struct { func (x *TestReply) Reset() { *x = TestReply{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[0] + mi := &file_test_pb_v3_test_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -42,7 +42,7 @@ func (x *TestReply) String() string { func (*TestReply) ProtoMessage() {} func (x *TestReply) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[0] + mi := &file_test_pb_v3_test_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -55,7 +55,7 @@ func (x *TestReply) ProtoReflect() protoreflect.Message { // Deprecated: Use TestReply.ProtoReflect.Descriptor instead. func (*TestReply) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{0} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{0} } type TestPanic struct { @@ -67,7 +67,7 @@ type TestPanic struct { func (x *TestPanic) Reset() { *x = TestPanic{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[1] + mi := &file_test_pb_v3_test_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -80,7 +80,7 @@ func (x *TestPanic) String() string { func (*TestPanic) ProtoMessage() {} func (x *TestPanic) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[1] + mi := &file_test_pb_v3_test_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -93,7 +93,7 @@ func (x *TestPanic) ProtoReflect() protoreflect.Message { // Deprecated: Use TestPanic.ProtoReflect.Descriptor instead. func (*TestPanic) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{1} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{1} } type TestTimeout struct { @@ -105,7 +105,7 @@ type TestTimeout struct { func (x *TestTimeout) Reset() { *x = TestTimeout{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[2] + mi := &file_test_pb_v3_test_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -118,7 +118,7 @@ func (x *TestTimeout) String() string { func (*TestTimeout) ProtoMessage() {} func (x *TestTimeout) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[2] + mi := &file_test_pb_v3_test_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -131,7 +131,7 @@ func (x *TestTimeout) ProtoReflect() protoreflect.Message { // Deprecated: Use TestTimeout.ProtoReflect.Descriptor instead. func (*TestTimeout) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{2} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{2} } type Reply struct { @@ -145,7 +145,7 @@ type Reply struct { func (x *Reply) Reset() { *x = Reply{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[3] + mi := &file_test_pb_v3_test_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -158,7 +158,7 @@ func (x *Reply) String() string { func (*Reply) ProtoMessage() {} func (x *Reply) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[3] + mi := &file_test_pb_v3_test_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -171,7 +171,7 @@ func (x *Reply) ProtoReflect() protoreflect.Message { // Deprecated: Use Reply.ProtoReflect.Descriptor instead. func (*Reply) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{3} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{3} } func (x *Reply) GetContent() string { @@ -190,7 +190,7 @@ type TestSend struct { func (x *TestSend) Reset() { *x = TestSend{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[4] + mi := &file_test_pb_v3_test_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -203,7 +203,7 @@ func (x *TestSend) String() string { func (*TestSend) ProtoMessage() {} func (x *TestSend) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[4] + mi := &file_test_pb_v3_test_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -216,7 +216,7 @@ func (x *TestSend) ProtoReflect() protoreflect.Message { // Deprecated: Use TestSend.ProtoReflect.Descriptor instead. func (*TestSend) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{4} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{4} } type Account struct { @@ -231,7 +231,7 @@ type Account struct { func (x *Account) Reset() { *x = Account{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[5] + mi := &file_test_pb_v3_test_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -244,7 +244,7 @@ func (x *Account) String() string { func (*Account) ProtoMessage() {} func (x *Account) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[5] + mi := &file_test_pb_v3_test_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -257,7 +257,7 @@ func (x *Account) ProtoReflect() protoreflect.Message { // Deprecated: Use Account.ProtoReflect.Descriptor instead. func (*Account) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{5} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{5} } func (x *Account) GetAccountId() string { @@ -285,7 +285,7 @@ type CreateAccount struct { func (x *CreateAccount) Reset() { *x = CreateAccount{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[6] + mi := &file_test_pb_v3_test_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -298,7 +298,7 @@ func (x *CreateAccount) String() string { func (*CreateAccount) ProtoMessage() {} func (x *CreateAccount) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[6] + mi := &file_test_pb_v3_test_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -311,7 +311,7 @@ func (x *CreateAccount) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAccount.ProtoReflect.Descriptor instead. func (*CreateAccount) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{6} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{6} } func (x *CreateAccount) GetAccountBalance() float64 { @@ -333,7 +333,7 @@ type CreditAccount struct { func (x *CreditAccount) Reset() { *x = CreditAccount{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[7] + mi := &file_test_pb_v3_test_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -346,7 +346,7 @@ func (x *CreditAccount) String() string { func (*CreditAccount) ProtoMessage() {} func (x *CreditAccount) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[7] + mi := &file_test_pb_v3_test_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -359,7 +359,7 @@ func (x *CreditAccount) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditAccount.ProtoReflect.Descriptor instead. func (*CreditAccount) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{7} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{7} } func (x *CreditAccount) GetAccountId() string { @@ -388,7 +388,7 @@ type AccountCreated struct { func (x *AccountCreated) Reset() { *x = AccountCreated{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[8] + mi := &file_test_pb_v3_test_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -401,7 +401,7 @@ func (x *AccountCreated) String() string { func (*AccountCreated) ProtoMessage() {} func (x *AccountCreated) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[8] + mi := &file_test_pb_v3_test_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -414,7 +414,7 @@ func (x *AccountCreated) ProtoReflect() protoreflect.Message { // Deprecated: Use AccountCreated.ProtoReflect.Descriptor instead. func (*AccountCreated) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{8} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{8} } func (x *AccountCreated) GetAccountId() string { @@ -443,7 +443,7 @@ type AccountCredited struct { func (x *AccountCredited) Reset() { *x = AccountCredited{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[9] + mi := &file_test_pb_v3_test_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -456,7 +456,7 @@ func (x *AccountCredited) String() string { func (*AccountCredited) ProtoMessage() {} func (x *AccountCredited) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[9] + mi := &file_test_pb_v3_test_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -469,7 +469,7 @@ func (x *AccountCredited) ProtoReflect() protoreflect.Message { // Deprecated: Use AccountCredited.ProtoReflect.Descriptor instead. func (*AccountCredited) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{9} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{9} } func (x *AccountCredited) GetAccountId() string { @@ -495,7 +495,7 @@ type TestNoEvent struct { func (x *TestNoEvent) Reset() { *x = TestNoEvent{} if protoimpl.UnsafeEnabled { - mi := &file_test_pb_v1_test_proto_msgTypes[10] + mi := &file_test_pb_v3_test_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -508,7 +508,7 @@ func (x *TestNoEvent) String() string { func (*TestNoEvent) ProtoMessage() {} func (x *TestNoEvent) ProtoReflect() protoreflect.Message { - mi := &file_test_pb_v1_test_proto_msgTypes[10] + mi := &file_test_pb_v3_test_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -521,15 +521,15 @@ func (x *TestNoEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use TestNoEvent.ProtoReflect.Descriptor instead. func (*TestNoEvent) Descriptor() ([]byte, []int) { - return file_test_pb_v1_test_proto_rawDescGZIP(), []int{10} + return file_test_pb_v3_test_proto_rawDescGZIP(), []int{10} } -var File_test_pb_v1_test_proto protoreflect.FileDescriptor +var File_test_pb_v3_test_proto protoreflect.FileDescriptor -var file_test_pb_v1_test_proto_rawDesc = []byte{ - 0x0a, 0x15, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x65, 0x73, +var file_test_pb_v3_test_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x33, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x74, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x76, - 0x31, 0x22, 0x0b, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x0b, + 0x33, 0x22, 0x0b, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x0b, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x22, 0x0d, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x21, 0x0a, 0x05, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, @@ -561,44 +561,44 @@ var file_test_pb_v1_test_proto_rawDesc = []byte{ 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x0d, 0x0a, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x85, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x65, 0x73, - 0x74, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x74, 0x73, 0x2e, 0x76, 0x33, 0x42, 0x09, 0x54, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x65, 0x67, 0x6f, 0x2f, 0x74, 0x65, - 0x73, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, - 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x54, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x08, 0x54, 0x65, 0x73, 0x74, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x54, 0x65, 0x73, 0x74, - 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x09, 0x54, 0x65, 0x73, 0x74, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x73, 0x74, 0x73, 0x2f, 0x76, 0x33, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, + 0x54, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x54, 0x65, 0x73, 0x74, 0x73, 0x2e, 0x56, 0x33, 0xca, 0x02, + 0x08, 0x54, 0x65, 0x73, 0x74, 0x73, 0x5c, 0x56, 0x33, 0xe2, 0x02, 0x14, 0x54, 0x65, 0x73, 0x74, + 0x73, 0x5c, 0x56, 0x33, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x09, 0x54, 0x65, 0x73, 0x74, 0x73, 0x3a, 0x3a, 0x56, 0x33, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_test_pb_v1_test_proto_rawDescOnce sync.Once - file_test_pb_v1_test_proto_rawDescData = file_test_pb_v1_test_proto_rawDesc + file_test_pb_v3_test_proto_rawDescOnce sync.Once + file_test_pb_v3_test_proto_rawDescData = file_test_pb_v3_test_proto_rawDesc ) -func file_test_pb_v1_test_proto_rawDescGZIP() []byte { - file_test_pb_v1_test_proto_rawDescOnce.Do(func() { - file_test_pb_v1_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_pb_v1_test_proto_rawDescData) +func file_test_pb_v3_test_proto_rawDescGZIP() []byte { + file_test_pb_v3_test_proto_rawDescOnce.Do(func() { + file_test_pb_v3_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_pb_v3_test_proto_rawDescData) }) - return file_test_pb_v1_test_proto_rawDescData -} - -var file_test_pb_v1_test_proto_msgTypes = make([]protoimpl.MessageInfo, 11) -var file_test_pb_v1_test_proto_goTypes = []interface{}{ - (*TestReply)(nil), // 0: tests.v2.TestReply - (*TestPanic)(nil), // 1: tests.v2.TestPanic - (*TestTimeout)(nil), // 2: tests.v2.TestTimeout - (*Reply)(nil), // 3: tests.v2.Reply - (*TestSend)(nil), // 4: tests.v2.TestSend - (*Account)(nil), // 5: tests.v2.Account - (*CreateAccount)(nil), // 6: tests.v2.CreateAccount - (*CreditAccount)(nil), // 7: tests.v2.CreditAccount - (*AccountCreated)(nil), // 8: tests.v2.AccountCreated - (*AccountCredited)(nil), // 9: tests.v2.AccountCredited - (*TestNoEvent)(nil), // 10: tests.v2.TestNoEvent -} -var file_test_pb_v1_test_proto_depIdxs = []int32{ + return file_test_pb_v3_test_proto_rawDescData +} + +var file_test_pb_v3_test_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_test_pb_v3_test_proto_goTypes = []interface{}{ + (*TestReply)(nil), // 0: tests.v3.TestReply + (*TestPanic)(nil), // 1: tests.v3.TestPanic + (*TestTimeout)(nil), // 2: tests.v3.TestTimeout + (*Reply)(nil), // 3: tests.v3.Reply + (*TestSend)(nil), // 4: tests.v3.TestSend + (*Account)(nil), // 5: tests.v3.Account + (*CreateAccount)(nil), // 6: tests.v3.CreateAccount + (*CreditAccount)(nil), // 7: tests.v3.CreditAccount + (*AccountCreated)(nil), // 8: tests.v3.AccountCreated + (*AccountCredited)(nil), // 9: tests.v3.AccountCredited + (*TestNoEvent)(nil), // 10: tests.v3.TestNoEvent +} +var file_test_pb_v3_test_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name @@ -606,13 +606,13 @@ var file_test_pb_v1_test_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for field type_name } -func init() { file_test_pb_v1_test_proto_init() } -func file_test_pb_v1_test_proto_init() { - if File_test_pb_v1_test_proto != nil { +func init() { file_test_pb_v3_test_proto_init() } +func file_test_pb_v3_test_proto_init() { + if File_test_pb_v3_test_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_test_pb_v1_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestReply); i { case 0: return &v.state @@ -624,7 +624,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestPanic); i { case 0: return &v.state @@ -636,7 +636,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestTimeout); i { case 0: return &v.state @@ -648,7 +648,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Reply); i { case 0: return &v.state @@ -660,7 +660,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestSend); i { case 0: return &v.state @@ -672,7 +672,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Account); i { case 0: return &v.state @@ -684,7 +684,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateAccount); i { case 0: return &v.state @@ -696,7 +696,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreditAccount); i { case 0: return &v.state @@ -708,7 +708,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AccountCreated); i { case 0: return &v.state @@ -720,7 +720,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AccountCredited); i { case 0: return &v.state @@ -732,7 +732,7 @@ func file_test_pb_v1_test_proto_init() { return nil } } - file_test_pb_v1_test_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_test_pb_v3_test_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*TestNoEvent); i { case 0: return &v.state @@ -749,18 +749,18 @@ func file_test_pb_v1_test_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_test_pb_v1_test_proto_rawDesc, + RawDescriptor: file_test_pb_v3_test_proto_rawDesc, NumEnums: 0, NumMessages: 11, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_test_pb_v1_test_proto_goTypes, - DependencyIndexes: file_test_pb_v1_test_proto_depIdxs, - MessageInfos: file_test_pb_v1_test_proto_msgTypes, + GoTypes: file_test_pb_v3_test_proto_goTypes, + DependencyIndexes: file_test_pb_v3_test_proto_depIdxs, + MessageInfos: file_test_pb_v3_test_proto_msgTypes, }.Build() - File_test_pb_v1_test_proto = out.File - file_test_pb_v1_test_proto_rawDesc = nil - file_test_pb_v1_test_proto_goTypes = nil - file_test_pb_v1_test_proto_depIdxs = nil + File_test_pb_v3_test_proto = out.File + file_test_pb_v3_test_proto_rawDesc = nil + file_test_pb_v3_test_proto_goTypes = nil + file_test_pb_v3_test_proto_depIdxs = nil }