diff --git a/aggregate/executor.go b/aggregate/executor.go new file mode 100644 index 0000000..20042ea --- /dev/null +++ b/aggregate/executor.go @@ -0,0 +1,36 @@ +package aggregate + +import ( + "context" +) + +// NewExecutor creates a new executor for the given aggregate store. +func NewExecutor[T Rooter](store *Store[T]) Executor[T] { + return func(ctx context.Context, a T, f func(ctx context.Context) error) error { + return Exec(ctx, store, a, f) + } +} + +// Executor is a helper function to load an aggregate from the store, execute a function and save the aggregate back to the store. +type Executor[T Rooter] func(ctx context.Context, a T, f func(ctx context.Context) error) error + +// Exec is a helper function to load an aggregate from the store, execute a function and save the aggregate back to the store. +func Exec[T Rooter](ctx context.Context, store *Store[T], a T, f func(ctx context.Context) error) error { + err := store.ByID(ctx, a.StringID(), a) + if err != nil { + return err + } + + err = f(ctx) + if err != nil { + return err + } + + return store.Save(ctx, a) +} + +// TODO +// always start a transaction in s.AppendEvents if one not present in the context - if yes then use it +// this way we can ensure that all events are saved in a single transaction +// and in the case of multiple aggregates we can ensure that all aggregates are saved in a single transaction +// also then client need to wrap the call to s.AppendEvents in a transaction only if they want to save multiple aggregates in a single transaction diff --git a/go.mod b/go.mod index 244a13e..b54583e 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23 require ( github.com/google/uuid v1.6.0 github.com/labstack/echo/v4 v4.12.0 + github.com/relvacode/iso8601 v1.4.0 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.33.0 github.com/testcontainers/testcontainers-go/modules/postgres v0.33.0 @@ -15,7 +16,7 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/containerd/containerd v1.7.18 // indirect @@ -56,7 +57,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/relvacode/iso8601 v1.4.0 // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect diff --git a/go.sum b/go.sum index bea234c..f404942 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +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/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=