diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b7f6bb..fc241f7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,8 +34,9 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN}} - - name: Download latest earthly - run: "sudo /bin/sh -c 'wget https://github.com/earthly/earthly/releases/download/v0.7.1/earthly-linux-amd64 -O /usr/local/bin/earthly && chmod +x /usr/local/bin/earthly'" + - uses: earthly/actions/setup-earthly@v1 + with: + version: v0.7.19 - name: Earthly version run: earthly --version - name: Run Linter and Tests diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index b16b4cc..3baf49c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -38,8 +38,9 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN}} - - name: Download latest earthly - run: "sudo /bin/sh -c 'wget https://github.com/earthly/earthly/releases/download/v0.7.1/earthly-linux-amd64 -O /usr/local/bin/earthly && chmod +x /usr/local/bin/earthly'" + - uses: earthly/actions/setup-earthly@v1 + with: + version: v0.7.19 - name: Earthly version run: earthly --version - name: Run Linter and Tests diff --git a/entity/behavior.go b/actor.go similarity index 68% rename from entity/behavior.go rename to actor.go index e79c9b0..4be1f96 100644 --- a/entity/behavior.go +++ b/actor.go @@ -1,4 +1,4 @@ -package entity +package ego import ( "context" @@ -12,40 +12,13 @@ import ( "github.com/tochemey/ego/internal/telemetry" "github.com/tochemey/goakt/actors" "go.uber.org/atomic" - "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/timestamppb" ) -type Command proto.Message -type Event proto.Message -type State proto.Message - -// Behavior defines an event sourced behavior when modeling a CQRS Behavior. -type Behavior[T State] 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 - // 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. - // They encode the business rules of your event sourced actor and act as a guardian of the event sourced actor consistency. - // The command eventSourcedHandler must first validate that the incoming command can be applied to the current model state. - // Any decision should be solely based on the data passed in the commands and the state of the Behavior. - // In case of successful validation, one or more events expressing the mutations are persisted. - // Once the events are persisted, they are applied to the state producing a new valid state. - HandleCommand(ctx context.Context, command Command, priorState T) (event 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) -} - -// Entity is an event sourced based actor -type Entity[T State] struct { - Behavior[T] +// actor is an event sourced based actor +type actor[T State] struct { + EntityBehavior[T] // specifies the events store eventsStore eventstore.EventsStore // specifies the current state @@ -57,22 +30,22 @@ type Entity[T State] struct { } // enforce compilation error -var _ actors.Actor = &Entity[State]{} +var _ actors.Actor = &actor[State]{} -// New creates an instance of Entity provided the eventSourcedHandler and the events store -func New[T State](behavior Behavior[T], eventsStore eventstore.EventsStore) *Entity[T] { +// newActor creates an instance of actor provided the eventSourcedHandler and the events store +func newActor[T State](behavior EntityBehavior[T], eventsStore eventstore.EventsStore) *actor[T] { // create an instance of entity and return it - return &Entity[T]{ - eventsStore: eventsStore, - Behavior: behavior, - eventsCounter: atomic.NewUint64(0), - mu: sync.RWMutex{}, + return &actor[T]{ + eventsStore: eventsStore, + EntityBehavior: behavior, + eventsCounter: atomic.NewUint64(0), + mu: sync.RWMutex{}, } } // PreStart pre-starts the actor // At this stage we connect to the various stores -func (entity *Entity[T]) PreStart(ctx context.Context) error { +func (entity *actor[T]) PreStart(ctx context.Context) error { // add a span context //ctx, span := telemetry.SpanContext(ctx, "PreStart") //defer span.End() @@ -99,7 +72,7 @@ func (entity *Entity[T]) PreStart(ctx context.Context) error { } // Receive processes any message dropped into the actor mailbox. -func (entity *Entity[T]) Receive(ctx actors.ReceiveContext) { +func (entity *actor[T]) Receive(ctx actors.ReceiveContext) { // add a span context _, span := telemetry.SpanContext(ctx.Context(), "Receive") defer span.End() @@ -119,7 +92,7 @@ func (entity *Entity[T]) Receive(ctx actors.ReceiveContext) { } // PostStop prepares the actor to gracefully shutdown -func (entity *Entity[T]) PostStop(ctx context.Context) error { +func (entity *actor[T]) PostStop(ctx context.Context) error { // add a span context ctx, span := telemetry.SpanContext(ctx, "PostStop") defer span.End() @@ -138,7 +111,7 @@ func (entity *Entity[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 *Entity[T]) recoverFromSnapshot(ctx context.Context) error { +func (entity *actor[T]) recoverFromSnapshot(ctx context.Context) error { // add a span context ctx, span := telemetry.SpanContext(ctx, "RecoverFromSnapshot") defer span.End() @@ -168,7 +141,7 @@ func (entity *Entity[T]) recoverFromSnapshot(ctx context.Context) error { } // sendErrorReply sends an error as a reply message -func (entity *Entity[T]) sendErrorReply(ctx actors.ReceiveContext, err error) { +func (entity *actor[T]) sendErrorReply(ctx actors.ReceiveContext, err error) { // create a new error reply reply := &egopb.CommandReply{ Reply: &egopb.CommandReply_ErrorReply{ @@ -182,7 +155,7 @@ func (entity *Entity[T]) sendErrorReply(ctx actors.ReceiveContext, err error) { } // getStateAndReply returns the current state of the entity -func (entity *Entity[T]) getStateAndReply(ctx actors.ReceiveContext) { +func (entity *actor[T]) getStateAndReply(ctx actors.ReceiveContext) { // let us fetch the latest journal latestEvent, err := entity.eventsStore.GetLatestEvent(ctx.Context(), entity.ID()) // handle the error @@ -209,7 +182,7 @@ func (entity *Entity[T]) getStateAndReply(ctx actors.ReceiveContext) { } // processCommandAndReply processes the incoming command -func (entity *Entity[T]) processCommandAndReply(ctx actors.ReceiveContext, command Command) { +func (entity *actor[T]) processCommandAndReply(ctx actors.ReceiveContext, command Command) { // set the go context goCtx := ctx.Context() // pass the received command to the command handler @@ -256,7 +229,7 @@ func (entity *Entity[T]) processCommandAndReply(ctx actors.ReceiveContext, comma sequenceNumber := entity.eventsCounter.Load() timestamp := timestamppb.Now() entity.lastCommandTime = timestamp.AsTime() - shardNumber := ctx.Self().ActorSystem().GetPartition(goCtx, entity.ID()) + shardNumber := ctx.Self().ActorSystem().GetPartition(entity.ID()) // create the event envelope := &egopb.Event{ diff --git a/entity/behavior_test.go b/actor_test.go similarity index 95% rename from entity/behavior_test.go rename to actor_test.go index 522f5a9..19078cd 100644 --- a/entity/behavior_test.go +++ b/actor_test.go @@ -1,4 +1,4 @@ -package entity +package ego import ( "context" @@ -19,7 +19,7 @@ import ( "google.golang.org/protobuf/proto" ) -func TestAccountAggregate(t *testing.T) { +func TestActor(t *testing.T) { t.Run("with state reply", func(t *testing.T) { defer goleak.VerifyNone(t) ctx := context.TODO() @@ -43,9 +43,9 @@ func TestAccountAggregate(t *testing.T) { behavior := NewAccountEntityBehavior(persistenceID) // create the persistence actor using the behavior previously created - actor := New[*testpb.Account](behavior, eventStore) + actor := newActor[*testpb.Account](behavior, eventStore) // spawn the actor - pid := actorSystem.Spawn(ctx, behavior.ID(), actor) + pid, _ := actorSystem.Spawn(ctx, behavior.ID(), actor) require.NotNil(t, pid) var command proto.Message @@ -129,9 +129,9 @@ func TestAccountAggregate(t *testing.T) { behavior := NewAccountEntityBehavior(persistenceID) // create the persistence actor using the behavior previously created - persistentActor := New[*testpb.Account](behavior, eventStore) + persistentActor := newActor[*testpb.Account](behavior, eventStore) // spawn the actor - pid := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) + pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NotNil(t, pid) var command proto.Message @@ -204,9 +204,9 @@ func TestAccountAggregate(t *testing.T) { behavior := NewAccountEntityBehavior(persistenceID) // create the persistence actor using the behavior previously created - persistentActor := New[*testpb.Account](behavior, eventStore) + persistentActor := newActor[*testpb.Account](behavior, eventStore) // spawn the actor - pid := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) + pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NotNil(t, pid) command := &testpb.TestSend{} @@ -271,9 +271,9 @@ func TestAccountAggregate(t *testing.T) { behavior := NewAccountEntityBehavior(persistenceID) // create the persistence actor using the behavior previously created - persistentActor := New[*testpb.Account](behavior, eventStore) + persistentActor := newActor[*testpb.Account](behavior, eventStore) // spawn the actor - pid := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) + pid, _ := actorSystem.Spawn(ctx, behavior.ID(), persistentActor) require.NotNil(t, pid) var command proto.Message diff --git a/behavior.go b/behavior.go new file mode 100644 index 0000000..1a204f0 --- /dev/null +++ b/behavior.go @@ -0,0 +1,33 @@ +package ego + +import ( + "context" + + "google.golang.org/protobuf/proto" +) + +type Command proto.Message +type Event proto.Message +type State proto.Message + +// EntityBehavior defines an event sourced behavior when modeling a CQRS EntityBehavior. +type EntityBehavior[T State] 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 + // 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. + // They encode the business rules of your event sourced actor and act as a guardian of the event sourced actor consistency. + // The command eventSourcedHandler must first validate that the incoming command can be applied to the current model state. + // Any decision should be solely based on the data passed in the commands and the state of the Behavior. + // In case of successful validation, one or more events expressing the mutations are persisted. + // Once the events are persisted, they are applied to the state producing a new valid state. + HandleCommand(ctx context.Context, command Command, priorState T) (event 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) +} diff --git a/ego.go b/ego.go deleted file mode 100644 index c68d8f6..0000000 --- a/ego.go +++ /dev/null @@ -1,169 +0,0 @@ -package ego - -import ( - "context" - "time" - - "github.com/pkg/errors" - "github.com/tochemey/ego/egopb" - "github.com/tochemey/ego/entity" - "github.com/tochemey/ego/eventstore" - "github.com/tochemey/goakt/actors" - "github.com/tochemey/goakt/discovery" - "github.com/tochemey/goakt/log" - "github.com/tochemey/goakt/telemetry" - "go.uber.org/atomic" -) - -// Ego represents the engine that empowers the various entities -type Ego struct { - name string // name is the application name - eventsStore eventstore.EventsStore // eventsStore is the events store - enableCluster *atomic.Bool // enableCluster enable/disable cluster mode - actorSystem actors.ActorSystem // actorSystem is the underlying actor system - logger log.Logger // logger is the logging engine to use - discoveryProvider discovery.Provider // discoveryProvider is the discovery provider for clustering - discoveryConfig discovery.Config // discoveryConfig is the discovery provider config for clustering - telemetry *telemetry.Telemetry // telemetry is the observability engine - partitionsCount uint64 // partitionsCount specifies the number of partitions -} - -// New creates an instance of Ego -func New(name string, eventsStore eventstore.EventsStore, opts ...Option) *Ego { - // create an instance of ego - e := &Ego{ - name: name, - eventsStore: eventsStore, - enableCluster: atomic.NewBool(false), - logger: log.DefaultLogger, - telemetry: telemetry.New(), - } - // apply the various options - for _, opt := range opts { - opt.Apply(e) - } - return e -} - -// Start starts the ego engine -func (x *Ego) Start(ctx context.Context) error { - // create a variable to hold the options - opts := []actors.Option{ - actors.WithLogger(x.logger), - actors.WithPassivationDisabled(), - actors.WithActorInitMaxRetries(1), - actors.WithReplyTimeout(5 * time.Second), - actors.WithTelemetry(x.telemetry), - actors.WithSupervisorStrategy(actors.StopDirective), - } - // set the remaining options - if x.enableCluster.Load() { - opts = append(opts, actors.WithClustering( - discovery.NewServiceDiscovery(x.discoveryProvider, x.discoveryConfig), - x.partitionsCount)) - } - - var err error - // create the actor system that will empower the entities - x.actorSystem, err = actors.NewActorSystem(x.name, opts...) - // handle the error - if err != nil { - // log the error - x.logger.Error(errors.Wrap(err, "failed to create the ego actor system")) - return err - } - // start the actor system - return x.actorSystem.Start(ctx) -} - -// Stop stops the ego engine -func (x *Ego) Stop(ctx context.Context) error { - return x.actorSystem.Stop(ctx) -} - -// 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 *Ego) SendCommand(ctx context.Context, command entity.Command, entityID string) (entity.State, error) { - // first check whether we are running in cluster mode or not - if x.enableCluster.Load() { - // grab the remote address of the actor - addr, err := x.actorSystem.RemoteActor(ctx, entityID) - // handle the error - if err != nil { - x.logger.Error(errors.Wrap(err, "failed to remotely locate actor address")) - return nil, err - } - // send a remote message to the actor - reply, err := actors.RemoteAsk(ctx, addr, command) - // handle the error - if err != nil { - // create a custom error - e := errors.Wrapf(err, "failed to send command to entity=(%s)", entityID) - // log the error - x.logger.Error(e) - return nil, e - } - // let us unmarshall the reply - commandReply := new(egopb.CommandReply) - // parse the reply and return the error when there is one - if err = reply.UnmarshalTo(commandReply); err != nil { - return nil, err - } - - // parse the command reply and return the appropriate responses - return parseCommandReply(commandReply) - } - // locate the given actor - pid, err := x.actorSystem.LocalActor(ctx, entityID) - // handle the error - if err != nil { - // create a custom error - e := errors.Wrap(err, "failed to locally locate actor address") - // log the error - x.logger.Error(e) - return nil, e - } - // send the command to the actor - reply, err := actors.Ask(ctx, pid, command, time.Second) - // handle the error - if err != nil { - x.logger.Error(err) - return nil, err - } - - // cast the reply to a command reply because that is the expected return type - commandReply, ok := reply.(*egopb.CommandReply) - // when casting is successful - if ok { - // parse the command reply and return the appropriate responses - return parseCommandReply(commandReply) - } - // casting failed - return nil, errors.New("failed to parse command reply") -} - -// parseCommandReply parses the command reply -func parseCommandReply(reply *egopb.CommandReply) (entity.State, error) { - var ( - state entity.State - err error - ) - // parse the command reply - switch r := reply.GetReply().(type) { - case *egopb.CommandReply_StateReply: - state, err = r.StateReply.GetState().UnmarshalNew() - case *egopb.CommandReply_NoReply: - // nothing to be done here - case *egopb.CommandReply_ErrorReply: - err = errors.New(r.ErrorReply.GetMessage()) - } - return state, err -} - -// NewEntity creates an entity and return the entity reference -func NewEntity[T entity.State](ctx context.Context, e *Ego, entityBehavior entity.Behavior[T]) actors.PID { - // create the entity - return e.actorSystem.Spawn(ctx, entityBehavior.ID(), entity.New(entityBehavior, e.eventsStore)) -} diff --git a/egopb/ego.pb.go b/egopb/ego.pb.go index f0b7f7f..ba8ebeb 100644 --- a/egopb/ego.pb.go +++ b/egopb/ego.pb.go @@ -21,71 +21,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// ProjectionRecoveryStrategy is used to recover from unhandled exceptions without causing the projection to fail -type ProjectionRecoveryStrategy int32 - -const ( - // States that if the first attempt to invoke the handler fails it will immediately give up and fail the projection - ProjectionRecoveryStrategy_FAIL ProjectionRecoveryStrategy = 0 - // States that if he first attempts to invoke the handler fails it will retry invoking the handler with the - // same envelope this number of `retries` with the `delay` between each attempt. It will give up - // and fail the projection if all attempts fail. For this to work as expected one need to define the `retries` and `delay` - // settings in the projection configuration. - ProjectionRecoveryStrategy_RETRY_AND_FAIL ProjectionRecoveryStrategy = 1 - // States that if the first attempt to invoke the handler fails it will immediately give up, discard the envelope and - // continue with next. This will commit the offset assuming the event has been successfully processed. - // Use this strategy with care. - ProjectionRecoveryStrategy_SKIP ProjectionRecoveryStrategy = 2 - // States that if he first attempts to invoke the handler fails it will retry invoking the handler with the - // same envelope this number of `retries` with the `delay` between each attempt. It will give up, - // discard the element and continue with next if all attempts fail. - // For this to work as expected one need to define the `retries` and `delay` settings in the projection configuration. - ProjectionRecoveryStrategy_RETRY_AND_SKIP ProjectionRecoveryStrategy = 3 -) - -// Enum value maps for ProjectionRecoveryStrategy. -var ( - ProjectionRecoveryStrategy_name = map[int32]string{ - 0: "FAIL", - 1: "RETRY_AND_FAIL", - 2: "SKIP", - 3: "RETRY_AND_SKIP", - } - ProjectionRecoveryStrategy_value = map[string]int32{ - "FAIL": 0, - "RETRY_AND_FAIL": 1, - "SKIP": 2, - "RETRY_AND_SKIP": 3, - } -) - -func (x ProjectionRecoveryStrategy) Enum() *ProjectionRecoveryStrategy { - p := new(ProjectionRecoveryStrategy) - *p = x - return p -} - -func (x ProjectionRecoveryStrategy) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ProjectionRecoveryStrategy) Descriptor() protoreflect.EnumDescriptor { - return file_ego_v1_ego_proto_enumTypes[0].Descriptor() -} - -func (ProjectionRecoveryStrategy) Type() protoreflect.EnumType { - return &file_ego_v1_ego_proto_enumTypes[0] -} - -func (x ProjectionRecoveryStrategy) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ProjectionRecoveryStrategy.Descriptor instead. -func (ProjectionRecoveryStrategy) EnumDescriptor() ([]byte, []int) { - return file_ego_v1_ego_proto_rawDescGZIP(), []int{0} -} - // Event defines the event that needs to be persisted onto the events store type Event struct { state protoimpl.MessageState @@ -271,7 +206,7 @@ type isCommandReply_Reply interface { } type CommandReply_StateReply struct { - // actual state is wrapped with meta data + // actual state is wrapped with metadata StateReply *StateReply `protobuf:"bytes,1,opt,name=state_reply,json=stateReply,proto3,oneof"` } @@ -497,83 +432,6 @@ func (*GetStateCommand) Descriptor() ([]byte, []int) { return file_ego_v1_ego_proto_rawDescGZIP(), []int{5} } -type Offset struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Specifies the persistence unique identifier - PersistenceId string `protobuf:"bytes,1,opt,name=persistence_id,json=persistenceId,proto3" json:"persistence_id,omitempty"` - // Specifies the projection name. - ProjectionName string `protobuf:"bytes,2,opt,name=projection_name,json=projectionName,proto3" json:"projection_name,omitempty"` - // Specifies the current_offset - // The current offset should match the sequence number of the given event consumed by the - // projection - CurrentOffset uint64 `protobuf:"varint,3,opt,name=current_offset,json=currentOffset,proto3" json:"current_offset,omitempty"` - // Specifies the timestamp - Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` -} - -func (x *Offset) Reset() { - *x = Offset{} - if protoimpl.UnsafeEnabled { - mi := &file_ego_v1_ego_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Offset) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Offset) ProtoMessage() {} - -func (x *Offset) ProtoReflect() protoreflect.Message { - mi := &file_ego_v1_ego_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Offset.ProtoReflect.Descriptor instead. -func (*Offset) Descriptor() ([]byte, []int) { - return file_ego_v1_ego_proto_rawDescGZIP(), []int{6} -} - -func (x *Offset) GetPersistenceId() string { - if x != nil { - return x.PersistenceId - } - return "" -} - -func (x *Offset) GetProjectionName() string { - if x != nil { - return x.ProjectionName - } - return "" -} - -func (x *Offset) GetCurrentOffset() uint64 { - if x != nil { - return x.CurrentOffset - } - return 0 -} - -func (x *Offset) GetTimestamp() int64 { - if x != nil { - return x.Timestamp - } - return 0 -} - var File_ego_v1_ego_proto protoreflect.FileDescriptor var file_ego_v1_ego_proto_rawDesc = []byte{ @@ -624,30 +482,14 @@ var file_ego_v1_ego_proto_rawDesc = []byte{ 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x09, 0x0a, 0x07, 0x4e, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x11, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x22, 0x9d, 0x01, 0x0a, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x25, 0x0a, - 0x0e, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, - 0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x2a, 0x58, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, - 0x54, 0x52, 0x59, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x01, 0x12, 0x08, - 0x0a, 0x04, 0x53, 0x4b, 0x49, 0x50, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x45, 0x54, 0x52, - 0x59, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x10, 0x03, 0x42, 0x73, 0x0a, 0x0a, - 0x63, 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, 0x31, 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, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x64, 0x42, 0x73, 0x0a, 0x0a, 0x63, 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, 0x31, 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, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -662,26 +504,23 @@ func file_ego_v1_ego_proto_rawDescGZIP() []byte { return file_ego_v1_ego_proto_rawDescData } -var file_ego_v1_ego_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ego_v1_ego_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_ego_v1_ego_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_ego_v1_ego_proto_goTypes = []interface{}{ - (ProjectionRecoveryStrategy)(0), // 0: ego.v1.ProjectionRecoveryStrategy - (*Event)(nil), // 1: ego.v1.Event - (*CommandReply)(nil), // 2: ego.v1.CommandReply - (*StateReply)(nil), // 3: ego.v1.StateReply - (*ErrorReply)(nil), // 4: ego.v1.ErrorReply - (*NoReply)(nil), // 5: ego.v1.NoReply - (*GetStateCommand)(nil), // 6: ego.v1.GetStateCommand - (*Offset)(nil), // 7: ego.v1.Offset - (*anypb.Any)(nil), // 8: google.protobuf.Any + (*Event)(nil), // 0: ego.v1.Event + (*CommandReply)(nil), // 1: ego.v1.CommandReply + (*StateReply)(nil), // 2: ego.v1.StateReply + (*ErrorReply)(nil), // 3: ego.v1.ErrorReply + (*NoReply)(nil), // 4: ego.v1.NoReply + (*GetStateCommand)(nil), // 5: ego.v1.GetStateCommand + (*anypb.Any)(nil), // 6: google.protobuf.Any } var file_ego_v1_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 - 3, // 2: ego.v1.CommandReply.state_reply:type_name -> ego.v1.StateReply - 4, // 3: ego.v1.CommandReply.error_reply:type_name -> ego.v1.ErrorReply - 5, // 4: ego.v1.CommandReply.no_reply:type_name -> ego.v1.NoReply - 8, // 5: ego.v1.StateReply.state:type_name -> google.protobuf.Any + 6, // 0: ego.v1.Event.event:type_name -> google.protobuf.Any + 6, // 1: ego.v1.Event.resulting_state:type_name -> google.protobuf.Any + 2, // 2: ego.v1.CommandReply.state_reply:type_name -> ego.v1.StateReply + 3, // 3: ego.v1.CommandReply.error_reply:type_name -> ego.v1.ErrorReply + 4, // 4: ego.v1.CommandReply.no_reply:type_name -> ego.v1.NoReply + 6, // 5: ego.v1.StateReply.state:type_name -> google.protobuf.Any 6, // [6:6] is the sub-list for method output_type 6, // [6:6] is the sub-list for method input_type 6, // [6:6] is the sub-list for extension type_name @@ -767,18 +606,6 @@ func file_ego_v1_ego_proto_init() { return nil } } - file_ego_v1_ego_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Offset); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } file_ego_v1_ego_proto_msgTypes[1].OneofWrappers = []interface{}{ (*CommandReply_StateReply)(nil), @@ -790,14 +617,13 @@ func file_ego_v1_ego_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ego_v1_ego_proto_rawDesc, - NumEnums: 1, - NumMessages: 7, + NumEnums: 0, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, GoTypes: file_ego_v1_ego_proto_goTypes, DependencyIndexes: file_ego_v1_ego_proto_depIdxs, - EnumInfos: file_ego_v1_ego_proto_enumTypes, MessageInfos: file_ego_v1_ego_proto_msgTypes, }.Build() File_ego_v1_ego_proto = out.File diff --git a/engine.go b/engine.go new file mode 100644 index 0000000..50b30c6 --- /dev/null +++ b/engine.go @@ -0,0 +1,80 @@ +package ego + +import ( + "context" + "time" + + "github.com/pkg/errors" + "github.com/tochemey/ego/eventstore" + "github.com/tochemey/goakt/actors" + "github.com/tochemey/goakt/discovery" + "github.com/tochemey/goakt/log" + "github.com/tochemey/goakt/telemetry" + "go.uber.org/atomic" +) + +// Engine represents the engine that empowers the various entities +type Engine struct { + name string // name is the application name + eventsStore eventstore.EventsStore // eventsStore is the events store + enableCluster *atomic.Bool // enableCluster enable/disable cluster mode + actorSystem actors.ActorSystem // actorSystem is the underlying actor system + logger log.Logger // logger is the logging engine to use + discoveryProvider discovery.Provider // discoveryProvider is the discovery provider for clustering + discoveryConfig discovery.Config // discoveryConfig is the discovery provider config for clustering + telemetry *telemetry.Telemetry // telemetry is the observability engine + partitionsCount uint64 // partitionsCount specifies the number of partitions +} + +// NewEngine creates an instance of Engine +func NewEngine(name string, eventsStore eventstore.EventsStore, opts ...Option) *Engine { + // create an instance of ego + e := &Engine{ + name: name, + eventsStore: eventsStore, + enableCluster: atomic.NewBool(false), + logger: log.DefaultLogger, + telemetry: telemetry.New(), + } + // apply the various options + for _, opt := range opts { + opt.Apply(e) + } + return e +} + +// Start starts the ego engine +func (x *Engine) Start(ctx context.Context) error { + // create a variable to hold the options + opts := []actors.Option{ + actors.WithLogger(x.logger), + actors.WithPassivationDisabled(), + actors.WithActorInitMaxRetries(1), + actors.WithReplyTimeout(5 * time.Second), + actors.WithTelemetry(x.telemetry), + actors.WithSupervisorStrategy(actors.StopDirective), + } + // set the remaining options + if x.enableCluster.Load() { + opts = append(opts, actors.WithClustering( + discovery.NewServiceDiscovery(x.discoveryProvider, x.discoveryConfig), + x.partitionsCount)) + } + + var err error + // create the actor system that will empower the entities + x.actorSystem, err = actors.NewActorSystem(x.name, opts...) + // handle the error + if err != nil { + // log the error + x.logger.Error(errors.Wrap(err, "failed to create the ego actor system")) + return err + } + // start the actor system + return x.actorSystem.Start(ctx) +} + +// Stop stops the ego engine +func (x *Engine) Stop(ctx context.Context) error { + return x.actorSystem.Stop(ctx) +} diff --git a/ego_test.go b/engine_test.go similarity index 85% rename from ego_test.go rename to engine_test.go index 9951a8f..4477db9 100644 --- a/ego_test.go +++ b/engine_test.go @@ -11,7 +11,6 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tochemey/ego/entity" "github.com/tochemey/ego/eventstore/memory" samplepb "github.com/tochemey/ego/example/pbs/sample/pb/v1" "github.com/tochemey/goakt/discovery" @@ -58,7 +57,7 @@ func TestEgo(t *testing.T) { provider.EXPECT().DiscoverPeers().Return(addrs, nil) // create the ego engine - e := New("Sample", eventStore, WithCluster(provider, config, 4)) + e := NewEngine("Sample", eventStore, WithCluster(provider, config, 4)) // start ego engine err := e.Start(ctx) @@ -71,7 +70,8 @@ func TestEgo(t *testing.T) { // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - NewEntity[*samplepb.Account](ctx, e, behavior) + entity, err := NewEntity[*samplepb.Account](ctx, behavior, e) + require.NoError(t, err) // send some commands to the pid var command proto.Message // create an account @@ -84,24 +84,24 @@ 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 - reply, err := e.SendCommand(ctx, command, entityID) + resultingState, revision, err := entity.SendCommand(ctx, command) require.NoError(t, err) - resultingState := reply.(*samplepb.Account) assert.EqualValues(t, 500.00, resultingState.GetAccountBalance()) assert.Equal(t, entityID, resultingState.GetAccountId()) + assert.EqualValues(t, 1, revision) // send another command to credit the balance command = &samplepb.CreditAccount{ AccountId: entityID, Balance: 250, } - reply, err = e.SendCommand(ctx, command, entityID) + newState, revision, err := entity.SendCommand(ctx, command) require.NoError(t, err) - newState := reply.(*samplepb.Account) assert.EqualValues(t, 750.00, newState.GetAccountBalance()) assert.Equal(t, entityID, newState.GetAccountId()) + assert.EqualValues(t, 2, revision) // free resources assert.NoError(t, e.Stop(ctx)) @@ -111,7 +111,7 @@ func TestEgo(t *testing.T) { // create the event store eventStore := memory.NewEventsStore() // create the ego engine - e := New("Sample", eventStore) + e := NewEngine("Sample", eventStore) // start ego engine err := e.Start(ctx) require.NoError(t, err) @@ -120,7 +120,8 @@ func TestEgo(t *testing.T) { // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - NewEntity[*samplepb.Account](ctx, e, behavior) + entity, err := NewEntity[*samplepb.Account](ctx, behavior, e) + require.NoError(t, err) // send some commands to the pid var command proto.Message // create an account @@ -129,24 +130,24 @@ func TestEgo(t *testing.T) { AccountBalance: 500.00, } // send the command to the actor. Please don't ignore the error in production grid code - reply, err := e.SendCommand(ctx, command, entityID) + resultingState, revision, err := entity.SendCommand(ctx, command) require.NoError(t, err) - resultingState := reply.(*samplepb.Account) assert.EqualValues(t, 500.00, resultingState.GetAccountBalance()) assert.Equal(t, entityID, resultingState.GetAccountId()) + assert.EqualValues(t, 1, revision) // send another command to credit the balance command = &samplepb.CreditAccount{ AccountId: entityID, Balance: 250, } - reply, err = e.SendCommand(ctx, command, entityID) + newState, revision, err := entity.SendCommand(ctx, command) require.NoError(t, err) - newState := reply.(*samplepb.Account) assert.EqualValues(t, 750.00, newState.GetAccountBalance()) assert.Equal(t, entityID, newState.GetAccountId()) + assert.EqualValues(t, 2, revision) // free resources assert.NoError(t, e.Stop(ctx)) @@ -159,7 +160,7 @@ type AccountBehavior struct { } // make sure that AccountBehavior is a true persistence behavior -var _ entity.Behavior[*samplepb.Account] = &AccountBehavior{} +var _ EntityBehavior[*samplepb.Account] = &AccountBehavior{} // NewAccountBehavior creates an instance of AccountBehavior func NewAccountBehavior(id string) *AccountBehavior { @@ -177,7 +178,7 @@ func (a *AccountBehavior) InitialState() *samplepb.Account { } // HandleCommand handles every command that is sent to the persistent behavior -func (a *AccountBehavior) HandleCommand(_ context.Context, command entity.Command, _ *samplepb.Account) (event entity.Event, err error) { +func (a *AccountBehavior) HandleCommand(_ context.Context, command Command, _ *samplepb.Account) (event Event, err error) { switch cmd := command.(type) { case *samplepb.CreateAccount: // TODO in production grid app validate the command using the prior state @@ -199,7 +200,7 @@ func (a *AccountBehavior) HandleCommand(_ context.Context, command entity.Comman } // HandleEvent handles every event emitted -func (a *AccountBehavior) HandleEvent(_ context.Context, event entity.Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { +func (a *AccountBehavior) HandleEvent(_ context.Context, event Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { switch evt := event.(type) { case *samplepb.AccountCreated: return &samplepb.Account{ diff --git a/enitity.go b/enitity.go new file mode 100644 index 0000000..7ad02d1 --- /dev/null +++ b/enitity.go @@ -0,0 +1,87 @@ +package ego + +import ( + "context" + "fmt" + "time" + + "github.com/pkg/errors" + "github.com/tochemey/ego/egopb" + "github.com/tochemey/goakt/actors" +) + +// 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) { + // create the instance of the actor + pid, err := engine.actorSystem.Spawn(ctx, behavior.ID(), newActor(behavior, engine.eventsStore)) + // return the error in case there is one + 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 nilT T + // send the command to the actor + reply, err := actors.Ask(ctx, x.actor, command, time.Second) + // handle the error + if err != nil { + return nilT, 0, err + } + + // cast the reply to a command reply because that is the expected return type + commandReply, ok := reply.(*egopb.CommandReply) + // when casting is successful + if ok { + // parse the command reply and return the appropriate responses + return parseCommandReply[T](commandReply) + } + // casting failed + return nilT, 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 + ) + // parse the command reply + switch r := reply.GetReply().(type) { + case *egopb.CommandReply_StateReply: + // unmarshal the state + msg, err := r.StateReply.GetState().UnmarshalNew() + // return the error in case there is one + if err != nil { + return state, 0, err + } + + // unpack the state properly + 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_NoReply: + // nothing to be done here + 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/example/main.go b/example/main.go index bf38b9e..abd684c 100644 --- a/example/main.go +++ b/example/main.go @@ -10,7 +10,6 @@ import ( "github.com/google/uuid" "github.com/tochemey/ego" - "github.com/tochemey/ego/entity" "github.com/tochemey/ego/eventstore/memory" samplepb "github.com/tochemey/ego/example/pbs/sample/pb/v1" "google.golang.org/protobuf/proto" @@ -22,7 +21,7 @@ func main() { // create the event store eventStore := memory.NewEventsStore() // create the ego engine - e := ego.New("Sample", eventStore) + e := ego.NewEngine("Sample", eventStore) // start ego engine _ = e.Start(ctx) // create a persistence id @@ -30,7 +29,7 @@ func main() { // create an entity behavior with a given id behavior := NewAccountBehavior(entityID) // create an entity - ego.NewEntity[*samplepb.Account](ctx, e, behavior) + entity, _ := ego.NewEntity[*samplepb.Account](ctx, behavior, e) // send some commands to the pid var command proto.Message @@ -40,9 +39,7 @@ func main() { AccountBalance: 500.00, } // send the command to the actor. Please don't ignore the error in production grid code - reply, _ := e.SendCommand(ctx, command, entityID) - - account := reply.(*samplepb.Account) + account, _, _ := entity.SendCommand(ctx, command) log.Printf("current balance: %v", account.GetAccountBalance()) @@ -51,8 +48,7 @@ func main() { AccountId: entityID, Balance: 250, } - reply, _ = e.SendCommand(ctx, command, entityID) - account = reply.(*samplepb.Account) + account, _, _ = entity.SendCommand(ctx, command) log.Printf("current balance: %v", account.GetAccountBalance()) // capture ctrl+c @@ -71,7 +67,7 @@ type AccountBehavior struct { } // make sure that AccountBehavior is a true persistence behavior -var _ entity.Behavior[*samplepb.Account] = &AccountBehavior{} +var _ ego.EntityBehavior[*samplepb.Account] = &AccountBehavior{} // NewAccountBehavior creates an instance of AccountBehavior func NewAccountBehavior(id string) *AccountBehavior { @@ -89,7 +85,7 @@ func (a *AccountBehavior) InitialState() *samplepb.Account { } // HandleCommand handles every command that is sent to the persistent behavior -func (a *AccountBehavior) HandleCommand(_ context.Context, command entity.Command, _ *samplepb.Account) (event entity.Event, err error) { +func (a *AccountBehavior) HandleCommand(_ context.Context, command ego.Command, _ *samplepb.Account) (event ego.Event, err error) { switch cmd := command.(type) { case *samplepb.CreateAccount: // TODO in production grid app validate the command using the prior state @@ -111,7 +107,7 @@ func (a *AccountBehavior) HandleCommand(_ context.Context, command entity.Comman } // HandleEvent handles every event emitted -func (a *AccountBehavior) HandleEvent(_ context.Context, event entity.Event, priorState *samplepb.Account) (state *samplepb.Account, err error) { +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{ diff --git a/go.mod b/go.mod index b9630d2..43fee26 100644 --- a/go.mod +++ b/go.mod @@ -4,19 +4,17 @@ go 1.20 require ( github.com/Masterminds/squirrel v1.5.4 - github.com/flowchartsman/retry v1.2.0 github.com/google/uuid v1.3.1 github.com/hashicorp/go-memdb v1.3.4 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 - github.com/tochemey/goakt v0.8.0 + github.com/tochemey/goakt v1.0.0 github.com/tochemey/gopack v0.0.0-20230929225503-4618c2f87d6b github.com/travisjeffery/go-dynaport v1.0.0 go.opentelemetry.io/otel v1.19.0 go.opentelemetry.io/otel/trace v1.19.0 go.uber.org/atomic v1.11.0 go.uber.org/goleak v1.2.1 - golang.org/x/sync v0.3.0 google.golang.org/protobuf v1.31.0 ) @@ -42,7 +40,6 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/georgysavva/scany v1.2.1 // indirect github.com/georgysavva/scany/v2 v2.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -95,22 +92,21 @@ require ( golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.15.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect + golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/term v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb // indirect - google.golang.org/grpc v1.58.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.29.0-alpha.0 // indirect - k8s.io/apimachinery v0.29.0-alpha.0 // indirect - k8s.io/client-go v0.29.0-alpha.0 // indirect + k8s.io/api v0.29.0-alpha.1 // indirect + k8s.io/apimachinery v0.29.0-alpha.1 // indirect + k8s.io/client-go v0.29.0-alpha.1 // indirect k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 // indirect + k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect diff --git a/go.sum b/go.sum index 3757080..22207f5 100644 --- a/go.sum +++ b/go.sum @@ -4,7 +4,6 @@ connectrpc.com/otelconnect v0.5.0 h1:K7xQKFbgeaHx563B+IIbd1EJe856AanueIYtGEtdnH8 connectrpc.com/otelconnect v0.5.0/go.mod h1:cjBMmtJmTokg4/k/3iDjLOjfNVM4qSVfIWz/qWQ8FNw= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= @@ -15,8 +14,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/RoaringBitmap/roaring v1.2.1/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA= github.com/RoaringBitmap/roaring v1.5.0 h1:V0VCSiHjroItEYCM3guC8T83ehi5QMt3oM9EefTTOms= github.com/RoaringBitmap/roaring v1.5.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= -github.com/XSAM/otelsql v0.23.0 h1:NsJQS9YhI1+RDsFqE9mW5XIQmPmdF/qa8qQOLZN8XEA= -github.com/XSAM/otelsql v0.23.0/go.mod h1:oX4LXMsb+9lAZhvHjUS61oQP/hbcJRadWHnBKNL+LuM= github.com/XSAM/otelsql v0.25.0 h1:ji1G+O45lrmZV9pXv2jQNRzYVFIwEB0jlY0XXdgpuNk= github.com/XSAM/otelsql v0.25.0/go.mod h1:VfWJ7nRF1t74mSL36s0ksIohT4nmFH5/opajHcmXPFc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -27,7 +24,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -52,14 +48,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= -github.com/cockroachdb/cockroach-go/v2 v2.2.0/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -76,13 +67,9 @@ github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxER github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/flowchartsman/retry v1.2.0 h1:qDhlw6RNufXz6RGr+IiYimFpMMkt77SUSHY5tgFaUCU= -github.com/flowchartsman/retry v1.2.0/go.mod h1:+sfx8OgCCiAr3t5jh2Gk+T0fRTI+k52edaYxURQxY64= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/georgysavva/scany v1.2.1 h1:91PAMBpwBtDjvn46TaLQmuVhxpAG6p6sjQaU4zPHPSM= -github.com/georgysavva/scany v1.2.1/go.mod h1:vGBpL5XRLOocMFFa55pj0P04DrL3I7qKVRL49K6Eu5o= github.com/georgysavva/scany/v2 v2.0.0 h1:RGXqxDv4row7/FYoK8MRXAZXqoWF/NM+NP0q50k3DKU= github.com/georgysavva/scany/v2 v2.0.0/go.mod h1:sigOdh+0qb/+aOs3TVhehVT10p8qJL7K/Zhyz8vWo38= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -105,13 +92,10 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -143,8 +127,7 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= @@ -180,61 +163,10 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.8.0 h1:FmjZ0rOyXTr1wfWs45i4a9vjnjWUAGpMuQLD9OSs+lw= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.6.2 h1:b3pDeuhbbzBYcg5kwNmNDun4pFUD/0AAr1kLXZLeNt8= -github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.10.1 h1:/6Q3ye4myIj6AaplUm+eRcz4OhK9HAvFf4ePsG40LJY= -github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3 h1:JnPg/5Q9xVJGfjsO5CPUOjnJps1JaRUm8I9FXVCFK94= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jackc/pgx/v5 v5.0.0 h1:3UdmB3yUeTnJtZ+nDv3Mxzd4GHHvHkl9XN3oboIbOrY= +github.com/jackc/puddle/v2 v2.0.0 h1:Kwk/AlLigcnZsDssc3Zun1dk1tAtQNPaBBxBHWn0Mjc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -245,13 +177,11 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -259,26 +189,12 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.45/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= @@ -344,27 +260,17 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= @@ -388,12 +294,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 v0.8.0 h1:s5DtH4LXmFnTOLuoofMH0W273hlLfiaFSIQudOIw5m8= -github.com/tochemey/goakt v0.8.0/go.mod h1:nbd+GPq7hTxIQeHSIvrN8dyae6AkIDjydK0ZwShIVss= -github.com/tochemey/gopack v0.0.0-20230901205014-06584bf05eb5 h1:ZpUGyBPXHr7KPqJzLYqQdyTARnOVpUGy4LZx7Jgcle0= -github.com/tochemey/gopack v0.0.0-20230901205014-06584bf05eb5/go.mod h1:O8C7dX8QMSDPbIjYXma+pe5pk9tg3vo6OxpDU0cFCh8= -github.com/tochemey/gopack v0.0.0-20230919121015-798d84fb51d5 h1:fa89fVP9KSDJ229eK+ADHzZoBD5wIJ2UovCQ2sTSAZY= -github.com/tochemey/gopack v0.0.0-20230919121015-798d84fb51d5/go.mod h1:Bzocc2Z1Z5uBNkyceMkHP3sPWMfRgWrVIo4DmrXPOJk= +github.com/tochemey/goakt v1.0.0 h1:yvbEtKXGlHMBytDa3BpTLm9OjItM0tDUJfN8+Yg15d4= +github.com/tochemey/goakt v1.0.0/go.mod h1:wkWArcaOE5dI/Q8NgeZbrS38QNrHl8sf9pM3rKHPO7A= github.com/tochemey/gopack v0.0.0-20230929225503-4618c2f87d6b h1:T8eXqAgqTFYoOVkFiI5EesGgVjiQPo1R451ipkVJHKk= github.com/tochemey/gopack v0.0.0-20230929225503-4618c2f87d6b/go.mod h1:SaU2hyOF8P/WNO+cnZI4RxFe8qqbK2KcnmLjmj2rvDU= github.com/travisjeffery/go-dynaport v1.0.0 h1:m/qqf5AHgB96CMMSworIPyo1i7NZueRsnwdzdCJ8Ajw= @@ -406,59 +308,28 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= -go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= -go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= -go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= -go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 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.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -466,17 +337,14 @@ golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -498,21 +366,15 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -522,7 +384,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -534,20 +395,13 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -555,25 +409,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb h1:Isk1sSH7bovx8Rti2wZK0UZF6oraBDK74uoyLEEVFN0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= -google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= -google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= -google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -586,13 +427,10 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -608,21 +446,17 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg= -gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -k8s.io/api v0.29.0-alpha.0 h1:U+fNSD93YX8KFeYu2mOsKP+AhktiEDw6VdvQ/pQN2kU= -k8s.io/api v0.29.0-alpha.0/go.mod h1:4nKPvoLiBp8GFtH8PBBiOu6dyLq1RQ6RLJvYwohLeQg= -k8s.io/apimachinery v0.29.0-alpha.0 h1:0hjEznQCsjbYaMG5uDQhoPtc0SBE+AdN88jmuIBuJUI= -k8s.io/apimachinery v0.29.0-alpha.0/go.mod h1:xhQIsaL3hXneGluH+0pzF7kr+VYuLS/VcYJxF1xQf+g= -k8s.io/client-go v0.29.0-alpha.0 h1:PlJ1deDfJsBFw/s1Mu4mInfcpr/whkKjI/0QVzLU+hE= -k8s.io/client-go v0.29.0-alpha.0/go.mod h1:xyOOIROVCmzmrGdtA0t5PDvzZbH3HqzmJJP6L8T+cNw= +k8s.io/api v0.29.0-alpha.1 h1:2L/HVdzNvB6cEKWWzdz6ocGqUsWvxcnmzuacEhhs0Fk= +k8s.io/api v0.29.0-alpha.1/go.mod h1:eYxbep9dvaZTFXRWrbVTJWC/F3Y41J7K8xODAOnBYIg= +k8s.io/apimachinery v0.29.0-alpha.1 h1:d7cj9SSTDXLZxiAJ1g6Oib4Ya+2XTlNOePNYVuATjg4= +k8s.io/apimachinery v0.29.0-alpha.1/go.mod h1:ITRsvhyE2eLGBxgwRxs79z49RNNQh7HUqBvHCNIgEZc= +k8s.io/client-go v0.29.0-alpha.1 h1:V3iWjzFQSHcs4AOeBV3fL379SjEVfyU2KnNW0Q6ACII= +k8s.io/client-go v0.29.0-alpha.1/go.mod h1:5CnPkSLo3JBTEka4x0g46Lh06l08UnJf+1x7O+dqtEM= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 h1:CAIciCnJnSOQxPd0xvpV6JU3D4AJvnYbImPpFpO9Hnw= -k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f h1:eeEUOoGYWhOz7EyXqhlR2zHKNw2mNJ9vzJmub6YN6kk= +k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= diff --git a/entity/helper_test.go b/helper_test.go similarity index 93% rename from entity/helper_test.go rename to helper_test.go index dfb9412..703b8a1 100644 --- a/entity/helper_test.go +++ b/helper_test.go @@ -1,4 +1,4 @@ -package entity +package ego import ( "context" @@ -7,13 +7,13 @@ import ( testpb "github.com/tochemey/ego/test/data/pb/v1" ) -// AccountEntityBehavior implement Behavior +// AccountEntityBehavior implement EntityBehavior type AccountEntityBehavior struct { id string } // make sure that testAccountBehavior is a true persistence behavior -var _ Behavior[*testpb.Account] = &AccountEntityBehavior{} +var _ EntityBehavior[*testpb.Account] = &AccountEntityBehavior{} // NewAccountEntityBehavior creates an instance of AccountEntityBehavior func NewAccountEntityBehavior(id string) *AccountEntityBehavior { diff --git a/option.go b/option.go index 6761558..8f8018e 100644 --- a/option.go +++ b/option.go @@ -10,22 +10,22 @@ import ( // Option is the interface that applies a configuration option. type Option interface { // Apply sets the Option value of a config. - Apply(e *Ego) + Apply(e *Engine) } var _ Option = OptionFunc(nil) // OptionFunc implements the Option interface. -type OptionFunc func(e *Ego) +type OptionFunc func(e *Engine) -// Apply applies the options to Ego -func (f OptionFunc) Apply(e *Ego) { +// Apply applies the options to Engine +func (f OptionFunc) Apply(e *Engine) { f(e) } // WithCluster enables cluster mode func WithCluster(discoProvider discovery.Provider, config discovery.Config, partitionsCount uint64) Option { - return OptionFunc(func(e *Ego) { + return OptionFunc(func(e *Engine) { e.enableCluster = atomic.NewBool(true) e.discoveryProvider = discoProvider e.discoveryConfig = config @@ -35,14 +35,14 @@ func WithCluster(discoProvider discovery.Provider, config discovery.Config, part // WithLogger sets the logger func WithLogger(logger log.Logger) Option { - return OptionFunc(func(e *Ego) { + return OptionFunc(func(e *Engine) { e.logger = logger }) } // WithTelemetry sets the telemetry engine func WithTelemetry(telemetry *telemetry.Telemetry) Option { - return OptionFunc(func(e *Ego) { + return OptionFunc(func(e *Engine) { e.telemetry = telemetry }) } diff --git a/option_test.go b/option_test.go index aca206d..d101909 100644 --- a/option_test.go +++ b/option_test.go @@ -22,12 +22,12 @@ func TestOptions(t *testing.T) { testCases := []struct { name string option Option - expected Ego + expected Engine }{ { name: "WithCluster", option: WithCluster(discoveryProvider, config, 30), - expected: Ego{ + expected: Engine{ discoveryProvider: discoveryProvider, discoveryConfig: config, partitionsCount: 30, @@ -37,17 +37,17 @@ func TestOptions(t *testing.T) { { name: "WithLogger", option: WithLogger(logger), - expected: Ego{logger: logger}, + expected: Engine{logger: logger}, }, { name: "WithTelemetry", option: WithTelemetry(tel), - expected: Ego{telemetry: tel}, + expected: Engine{telemetry: tel}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - var e Ego + var e Engine tc.option.Apply(&e) assert.Equal(t, tc.expected, e) }) diff --git a/protos/ego/v1/ego.proto b/protos/ego/v1/ego.proto index 0d86346..9807fa6 100644 --- a/protos/ego/v1/ego.proto +++ b/protos/ego/v1/ego.proto @@ -64,36 +64,3 @@ message NoReply {} // GetStateCommand tells the Aggregate // to reply with its latest state message GetStateCommand {} - -message Offset { - // Specifies the persistence unique identifier - string persistence_id = 1; - // Specifies the projection name. - string projection_name = 2; - // Specifies the current_offset - // The current offset should match the sequence number of the given event consumed by the - // projection - uint64 current_offset = 3; - // Specifies the timestamp - int64 timestamp = 4; -} - -// ProjectionRecoveryStrategy is used to recover from unhandled exceptions without causing the projection to fail -enum ProjectionRecoveryStrategy { - // States that if the first attempt to invoke the handler fails it will immediately give up and fail the projection - FAIL = 0; - // States that if he first attempts to invoke the handler fails it will retry invoking the handler with the - // same envelope this number of `retries` with the `delay` between each attempt. It will give up - // and fail the projection if all attempts fail. For this to work as expected one need to define the `retries` and `delay` - // settings in the projection configuration. - RETRY_AND_FAIL = 1; - // States that if the first attempt to invoke the handler fails it will immediately give up, discard the envelope and - // continue with next. This will commit the offset assuming the event has been successfully processed. - // Use this strategy with care. - SKIP = 2; - // States that if he first attempts to invoke the handler fails it will retry invoking the handler with the - // same envelope this number of `retries` with the `delay` between each attempt. It will give up, - // discard the element and continue with next if all attempts fail. - // For this to work as expected one need to define the `retries` and `delay` settings in the projection configuration. - RETRY_AND_SKIP = 3; -} diff --git a/readme.md b/readme.md index bd34e52..2b1e04f 100644 --- a/readme.md +++ b/readme.md @@ -16,16 +16,7 @@ Under the hood, ego leverages [goakt](https://github.com/Tochemey/goakt) to scal They encode the business rules of your event sourced actor and act as a guardian of the Aggregate consistency. The command handler must first validate that the incoming command can be applied to the current model state. Any decision should be solely based on the data passed in the commands and the state of the Behavior. - In case of successful validation, one or more events expressing the mutations are persisted. The following replies to a given command are: - - [StateReply](protos): this message is returned when an event is the product of the command handler. The message contains: - - the entity id - - the resulting state - - the actual event to be persisted - - the sequence number - - the event timestamp - - [NoReply](protos): this message is returned when the command does not need a reply. - - [ErrorReply](protos): is used when a command processing has failed. This message contains the error message. - Once the events are persisted, they are applied to the state producing a new valid state. + In case of successful validation, one or more events expressing the mutations are persisted. Once the events are persisted, they are applied to the state producing a new valid state. - Events handler: The event handlers are used to mutate the state of the Aggregate by applying the events to it. Event handlers must be pure functions as they will be used when instantiating the Aggregate and replaying the event store. - Extensible events store