diff --git a/internal/api/v1/controllers_transactions_create.go b/internal/api/v1/controllers_transactions_create.go index 6b0c2dde9..5ec0b7540 100644 --- a/internal/api/v1/controllers_transactions_create.go +++ b/internal/api/v1/controllers_transactions_create.go @@ -102,7 +102,7 @@ func createTransaction(w http.ResponseWriter, r *http.Request) { } return } - api.Ok(w, []any{mapTransactionToV1(*res)}) + api.Ok(w, []any{mapTransactionToV1(res.Transaction)}) return } @@ -138,5 +138,5 @@ func createTransaction(w http.ResponseWriter, r *http.Request) { return } - api.Ok(w, []any{mapTransactionToV1(*res)}) + api.Ok(w, []any{mapTransactionToV1(res.Transaction)}) } diff --git a/internal/api/v1/controllers_transactions_create_test.go b/internal/api/v1/controllers_transactions_create_test.go index 8e27b3359..18f0a3f77 100644 --- a/internal/api/v1/controllers_transactions_create_test.go +++ b/internal/api/v1/controllers_transactions_create_test.go @@ -13,7 +13,6 @@ import ( "github.com/formancehq/go-libs/api" "github.com/formancehq/go-libs/auth" - "github.com/formancehq/go-libs/pointer" ledger "github.com/formancehq/ledger/internal" ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger" "github.com/stretchr/testify/require" @@ -228,9 +227,11 @@ func TestTransactionsCreate(t *testing.T) { ledgerController.EXPECT(). CreateTransaction(gomock.Any(), ledgercontroller.Parameters[ledgercontroller.RunScript]{ DryRun: tc.expectedPreview, - Input: testCase.expectedRunScript, + Input: testCase.expectedRunScript, }). - Return(pointer.For(expectedTx), nil) + Return(&ledgercontroller.CreateTransactionResult{ + Transaction: expectedTx, + }, nil) } router := NewRouter(systemController, auth.NewNoAuth(), "develop", testing.Verbose()) diff --git a/internal/api/v1/controllers_transactions_revert.go b/internal/api/v1/controllers_transactions_revert.go index aa7348596..fed02dd33 100644 --- a/internal/api/v1/controllers_transactions_revert.go +++ b/internal/api/v1/controllers_transactions_revert.go @@ -21,7 +21,7 @@ func revertTransaction(w http.ResponseWriter, r *http.Request) { return } - tx, err := l.RevertTransaction( + ret, err := l.RevertTransaction( r.Context(), getCommandParameters(r, ledgercontroller.RevertTransaction{ Force: api.QueryParamBool(r, "disableChecks"), @@ -43,5 +43,5 @@ func revertTransaction(w http.ResponseWriter, r *http.Request) { return } - api.Created(w, mapTransactionToV1(*tx)) + api.Created(w, mapTransactionToV1(ret.ReversedTransaction)) } diff --git a/internal/api/v1/controllers_transactions_revert_test.go b/internal/api/v1/controllers_transactions_revert_test.go index b6c525b05..23b178100 100644 --- a/internal/api/v1/controllers_transactions_revert_test.go +++ b/internal/api/v1/controllers_transactions_revert_test.go @@ -76,7 +76,9 @@ func TestTransactionsRevert(t *testing.T) { Force: tc.expectForce, }, }). - Return(pointer.For(tc.returnTx), tc.returnErr) + Return(pointer.For(ledgercontroller.RevertTransactionResult{ + ReversedTransaction: tc.returnTx, + }), tc.returnErr) router := NewRouter(systemController, auth.NewNoAuth(), "develop", testing.Verbose()) diff --git a/internal/api/v2/controllers_bulk.go b/internal/api/v2/controllers_bulk.go index a97f311b7..925b62cb5 100644 --- a/internal/api/v2/controllers_bulk.go +++ b/internal/api/v2/controllers_bulk.go @@ -86,7 +86,7 @@ func ProcessBulk(ctx context.Context, l ledgercontroller.Controller, bulk Bulk, } rs := req.ToRunScript(false) - tx, err := l.CreateTransaction(ctx, ledgercontroller.Parameters[ledgercontroller.RunScript]{ + createTransactionResult, err := l.CreateTransaction(ctx, ledgercontroller.Parameters[ledgercontroller.RunScript]{ DryRun: false, IdempotencyKey: element.IdempotencyKey, Input: *rs, @@ -115,7 +115,7 @@ func ProcessBulk(ctx context.Context, l ledgercontroller.Controller, bulk Bulk, } } else { ret = append(ret, Result{ - Data: tx, + Data: createTransactionResult.Transaction, ResponseType: element.Action, }) } @@ -187,7 +187,7 @@ func ProcessBulk(ctx context.Context, l ledgercontroller.Controller, bulk Bulk, return nil, errorsInBulk, fmt.Errorf("error parsing element %d: %s", i, err) } - tx, err := l.RevertTransaction(ctx, ledgercontroller.Parameters[ledgercontroller.RevertTransaction]{ + revertTransactionResult, err := l.RevertTransaction(ctx, ledgercontroller.Parameters[ledgercontroller.RevertTransaction]{ DryRun: false, IdempotencyKey: element.IdempotencyKey, Input: ledgercontroller.RevertTransaction{ @@ -210,7 +210,7 @@ func ProcessBulk(ctx context.Context, l ledgercontroller.Controller, bulk Bulk, } } else { ret = append(ret, Result{ - Data: tx, + Data: revertTransactionResult.ReversedTransaction, ResponseType: element.Action, }) } diff --git a/internal/api/v2/controllers_bulk_test.go b/internal/api/v2/controllers_bulk_test.go index 1f63fc92b..cd1f4ef39 100644 --- a/internal/api/v2/controllers_bulk_test.go +++ b/internal/api/v2/controllers_bulk_test.go @@ -67,11 +67,13 @@ func TestBulk(t *testing.T) { Timestamp: now, }, false), }). - Return(&ledger.Transaction{ - TransactionData: ledger.TransactionData{ - Postings: postings, - Metadata: metadata.Metadata{}, - Timestamp: now, + Return(&ledgercontroller.CreateTransactionResult{ + Transaction: ledger.Transaction{ + TransactionData: ledger.TransactionData{ + Postings: postings, + Metadata: metadata.Metadata{}, + Timestamp: now, + }, }, }, nil) }, @@ -164,7 +166,7 @@ func TestBulk(t *testing.T) { TransactionID: 1, }, }). - Return(&ledger.Transaction{}, nil) + Return(&ledgercontroller.RevertTransactionResult{}, nil) }, expectResults: []Result{{ Data: map[string]any{ diff --git a/internal/api/v2/controllers_transactions_create.go b/internal/api/v2/controllers_transactions_create.go index a036f6168..c6d98be15 100644 --- a/internal/api/v2/controllers_transactions_create.go +++ b/internal/api/v2/controllers_transactions_create.go @@ -51,5 +51,5 @@ func createTransaction(w http.ResponseWriter, r *http.Request) { return } - api.Ok(w, res) + api.Ok(w, res.Transaction) } diff --git a/internal/api/v2/controllers_transactions_create_test.go b/internal/api/v2/controllers_transactions_create_test.go index 906c16da3..be74cc462 100644 --- a/internal/api/v2/controllers_transactions_create_test.go +++ b/internal/api/v2/controllers_transactions_create_test.go @@ -12,7 +12,6 @@ import ( "github.com/formancehq/go-libs/api" "github.com/formancehq/go-libs/auth" - "github.com/formancehq/go-libs/pointer" ledger "github.com/formancehq/ledger/internal" ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger" "github.com/pkg/errors" @@ -408,11 +407,13 @@ func TestTransactionCreate(t *testing.T) { expect := ledgerController.EXPECT(). CreateTransaction(gomock.Any(), ledgercontroller.Parameters[ledgercontroller.RunScript]{ DryRun: tc.expectedDryRun, - Input: testCase.expectedRunScript, + Input: testCase.expectedRunScript, }) if tc.returnError == nil { - expect.Return(pointer.For(expectedTx), nil) + expect.Return(&ledgercontroller.CreateTransactionResult{ + Transaction: expectedTx, + }, nil) } else { expect.Return(nil, tc.returnError) } diff --git a/internal/api/v2/controllers_transactions_revert.go b/internal/api/v2/controllers_transactions_revert.go index 36c7185c8..e08c3bbb7 100644 --- a/internal/api/v2/controllers_transactions_revert.go +++ b/internal/api/v2/controllers_transactions_revert.go @@ -21,7 +21,7 @@ func revertTransaction(w http.ResponseWriter, r *http.Request) { return } - tx, err := l.RevertTransaction( + ret, err := l.RevertTransaction( r.Context(), getCommandParameters(r, ledgercontroller.RevertTransaction{ Force: api.QueryParamBool(r, "force"), @@ -43,5 +43,5 @@ func revertTransaction(w http.ResponseWriter, r *http.Request) { return } - api.Created(w, tx) + api.Created(w, ret.ReversedTransaction) } diff --git a/internal/api/v2/controllers_transactions_revert_test.go b/internal/api/v2/controllers_transactions_revert_test.go index 9adbdd343..2b9a21e6f 100644 --- a/internal/api/v2/controllers_transactions_revert_test.go +++ b/internal/api/v2/controllers_transactions_revert_test.go @@ -9,7 +9,6 @@ import ( "github.com/formancehq/go-libs/api" "github.com/formancehq/go-libs/auth" - "github.com/formancehq/go-libs/pointer" ledger "github.com/formancehq/ledger/internal" ledgercontroller "github.com/formancehq/ledger/internal/controller/ledger" "github.com/stretchr/testify/require" @@ -76,7 +75,9 @@ func TestTransactionsRevert(t *testing.T) { Force: tc.expectForce, }, }). - Return(pointer.For(tc.returnTx), tc.returnErr) + Return(&ledgercontroller.RevertTransactionResult{ + ReversedTransaction: tc.returnTx, + }, tc.returnErr) router := NewRouter(systemController, auth.NewNoAuth(), "develop", testing.Verbose()) diff --git a/internal/controller/ledger/controller.go b/internal/controller/ledger/controller.go index 25d745ed4..61c0a2a15 100644 --- a/internal/controller/ledger/controller.go +++ b/internal/controller/ledger/controller.go @@ -2,6 +2,8 @@ package ledger import ( "context" + "github.com/formancehq/go-libs/metadata" + "github.com/formancehq/ledger/internal/machine/vm" "github.com/formancehq/go-libs/bun/bunpaginate" "github.com/formancehq/go-libs/migrations" @@ -35,7 +37,7 @@ type Controller interface { // * ErrTransactionReferenceConflict // * ErrIdempotencyKeyConflict // * ErrInsufficientFunds - CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*ledger.Transaction, error) + CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*CreateTransactionResult, error) // RevertTransaction allow to revert a transaction. // It can return following errors: // * ErrInsufficientFunds @@ -43,7 +45,7 @@ type Controller interface { // * ErrNotFound // Parameter force indicate we want to force revert the transaction even if the accounts does not have funds // Parameter atEffectiveDate indicate we want to set the timestamp of the newly created transaction on the timestamp of the reverted transaction - RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*ledger.Transaction, error) + RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*RevertTransactionResult, error) // SaveTransactionMetadata allow to add metadata to an existing transaction // It can return following errors: // * ErrNotFound @@ -67,3 +69,43 @@ type Controller interface { // Export allow to export the logs of a ledger Export(ctx context.Context, w ExportWriter) error } + +type RunScript = vm.RunScript +type Script = vm.Script +type ScriptV1 = vm.ScriptV1 + +type CreateTransactionResult struct { + Transaction ledger.Transaction + AccountMetadata ledger.AccountMetadata +} + +type RevertTransaction struct { + Force bool + AtEffectiveDate bool + TransactionID int +} + +type RevertTransactionResult struct { + RevertedTransaction ledger.Transaction + ReversedTransaction ledger.Transaction +} + +type SaveTransactionMetadata struct { + TransactionID int + Metadata metadata.Metadata +} + +type SaveAccountMetadata struct { + Address string + Metadata metadata.Metadata +} + +type DeleteTransactionMetadata struct { + TransactionID int + Key string +} + +type DeleteAccountMetadata struct { + Address string + Key string +} \ No newline at end of file diff --git a/internal/controller/ledger/controller_default.go b/internal/controller/ledger/controller_default.go index 95cbf1454..4c4cdc088 100644 --- a/internal/controller/ledger/controller_default.go +++ b/internal/controller/ledger/controller_default.go @@ -28,7 +28,6 @@ import ( type DefaultController struct { store Store - listener Listener machineFactory MachineFactory ledger ledger.Ledger } @@ -36,12 +35,10 @@ type DefaultController struct { func NewDefaultController( ledger ledger.Ledger, store Store, - listener Listener, machineFactory MachineFactory, ) *DefaultController { ret := &DefaultController{ store: store, - listener: listener, ledger: ledger, machineFactory: machineFactory, } @@ -208,7 +205,7 @@ func (ctrl *DefaultController) GetVolumesWithBalances(ctx context.Context, q Get return ctrl.store.GetVolumesWithBalances(ctx, q) } -func (ctrl *DefaultController) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*ledger.Transaction, error) { +func (ctrl *DefaultController) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*CreateTransactionResult, error) { logger := logging.FromContext(ctx).WithField("req", uuid.NewString()[:8]) ctx = logging.ContextWithLogger(ctx, logger) @@ -273,12 +270,13 @@ func (ctrl *DefaultController) CreateTransaction(ctx context.Context, parameters transaction := log.Data.(ledger.NewTransactionLogPayload).Transaction accountMetadata := log.Data.(ledger.NewTransactionLogPayload).AccountMetadata - ctrl.listener.CommittedTransactions(ctx, ctrl.ledger.Name, transaction, accountMetadata) - - return &transaction, nil + return &CreateTransactionResult{ + Transaction: transaction, + AccountMetadata: accountMetadata, + }, nil } -func (ctrl *DefaultController) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*ledger.Transaction, error) { +func (ctrl *DefaultController) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*RevertTransactionResult, error) { var originalTransaction *ledger.Transaction log, err := forgeLog(ctx, ctrl.store, parameters, func(ctx context.Context, sqlTX TX, input RevertTransaction) (*ledger.Log, error) { @@ -343,16 +341,10 @@ func (ctrl *DefaultController) RevertTransaction(ctx context.Context, parameters return nil, err } - if ctrl.listener != nil { - ctrl.listener.RevertedTransaction( - ctx, - ctrl.ledger.Name, - *originalTransaction, - log.Data.(ledger.RevertedTransactionLogPayload).RevertTransaction, - ) - } - - return pointer.For(log.Data.(ledger.RevertedTransactionLogPayload).RevertTransaction), nil + return &RevertTransactionResult{ + RevertedTransaction: *originalTransaction, + ReversedTransaction: log.Data.(ledger.RevertedTransactionLogPayload).RevertTransaction, + }, nil } func (ctrl *DefaultController) SaveTransactionMetadata(ctx context.Context, parameters Parameters[SaveTransactionMetadata]) error { @@ -367,16 +359,6 @@ func (ctrl *DefaultController) SaveTransactionMetadata(ctx context.Context, para return err } - if ctrl.listener != nil { - ctrl.listener.SavedMetadata( - ctx, - ctrl.ledger.Name, - ledger.MetaTargetTypeTransaction, - fmt.Sprint(parameters.Input.TransactionID), - parameters.Input.Metadata, - ) - } - return nil } @@ -395,21 +377,8 @@ func (ctrl *DefaultController) SaveAccountMetadata(ctx context.Context, paramete return pointer.For(ledger.NewSetMetadataOnAccountLog(input.Address, input.Metadata)), nil }) - if err != nil { - return err - } - if ctrl.listener != nil { - ctrl.listener.SavedMetadata( - ctx, - ctrl.ledger.Name, - ledger.MetaTargetTypeAccount, - parameters.Input.Address, - parameters.Input.Metadata, - ) - } - - return nil + return err } func (ctrl *DefaultController) DeleteTransactionMetadata(ctx context.Context, parameters Parameters[DeleteTransactionMetadata]) error { @@ -425,49 +394,20 @@ func (ctrl *DefaultController) DeleteTransactionMetadata(ctx context.Context, pa return pointer.For(ledger.NewDeleteTransactionMetadataLog(input.TransactionID, input.Key)), nil }) - if err != nil { - return err - } - // todo: events should not be sent in dry run! - if ctrl.listener != nil { - ctrl.listener.DeletedMetadata( - ctx, - ctrl.ledger.Name, - ledger.MetaTargetTypeTransaction, - fmt.Sprint(parameters.Input.TransactionID), - parameters.Input.Key, - ) - } - - return nil + return err } func (ctrl *DefaultController) DeleteAccountMetadata(ctx context.Context, parameters Parameters[DeleteAccountMetadata]) error { - if err := tracing.SkipResult(tracing.Trace(ctx, "DeleteAccountMetadata", func(ctx context.Context) (*ledger.Log, error) { - return forgeLog(ctx, ctrl.store, parameters, func(ctx context.Context, sqlTX TX, input DeleteAccountMetadata) (*ledger.Log, error) { - err := sqlTX.DeleteAccountMetadata(ctx, input.Address, input.Key) - if err != nil { - return nil, err - } - - return pointer.For(ledger.NewDeleteAccountMetadataLog(input.Address, input.Key)), nil - }) - })); err != nil { - return err - } - - if ctrl.listener != nil { - ctrl.listener.DeletedMetadata( - ctx, - ctrl.ledger.Name, - ledger.MetaTargetTypeAccount, - parameters.Input.Address, - parameters.Input.Key, - ) - } + _, err := forgeLog(ctx, ctrl.store, parameters, func(ctx context.Context, sqlTX TX, input DeleteAccountMetadata) (*ledger.Log, error) { + err := sqlTX.DeleteAccountMetadata(ctx, input.Address, input.Key) + if err != nil { + return nil, err + } - return nil + return pointer.For(ledger.NewDeleteAccountMetadataLog(input.Address, input.Key)), nil + }) + return err } var _ Controller = (*DefaultController)(nil) diff --git a/internal/controller/ledger/controller_default_test.go b/internal/controller/ledger/controller_default_test.go index fcc03a00b..b603b70d3 100644 --- a/internal/controller/ledger/controller_default_test.go +++ b/internal/controller/ledger/controller_default_test.go @@ -24,10 +24,9 @@ func TestCreateTransaction(t *testing.T) { store := NewMockStore(ctrl) machine := NewMockMachine(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) sqlTX := NewMockTX(ctrl) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) runScript := RunScript{} @@ -61,9 +60,6 @@ func TestCreateTransaction(t *testing.T) { return x }) - listener.EXPECT(). - CommittedTransactions(gomock.Any(), "", gomock.Any(), ledger.AccountMetadata{}) - _, err := l.CreateTransaction(context.Background(), Parameters[RunScript]{ Input: runScript, }) @@ -76,10 +72,9 @@ func TestRevertTransaction(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) sqlTX := NewMockTX(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) store.EXPECT(). WithTX(gomock.Any(), nil, gomock.Any()). @@ -102,11 +97,7 @@ func TestRevertTransaction(t *testing.T) { sqlTX.EXPECT(). CommitTransaction(gomock.Any(), gomock.Any()). - DoAndReturn(func(ctx context.Context, newTx *ledger.Transaction) error { - listener.EXPECT(). - RevertedTransaction(gomock.Any(), "", txToRevert, *newTx) - return nil - }) + Return(nil) sqlTX.EXPECT(). InsertLog(gomock.Any(), gomock.Cond(func(x any) bool { @@ -128,10 +119,9 @@ func TestSaveTransactionMetadata(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) sqlTX := NewMockTX(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) store.EXPECT(). WithTX(gomock.Any(), nil, gomock.Any()). @@ -153,9 +143,6 @@ func TestSaveTransactionMetadata(t *testing.T) { })). Return(nil) - listener.EXPECT(). - SavedMetadata(gomock.Any(), "", ledger.MetaTargetTypeTransaction, "1", m) - err := l.SaveTransactionMetadata(ctx, Parameters[SaveTransactionMetadata]{ Input: SaveTransactionMetadata{ Metadata: m, @@ -171,10 +158,9 @@ func TestDeleteTransactionMetadata(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) sqlTX := NewMockTX(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) store.EXPECT(). WithTX(gomock.Any(), nil, gomock.Any()). @@ -193,9 +179,6 @@ func TestDeleteTransactionMetadata(t *testing.T) { })). Return(nil) - listener.EXPECT(). - DeletedMetadata(gomock.Any(), "", ledger.MetaTargetTypeTransaction, "1", "foo") - err := l.DeleteTransactionMetadata(ctx, Parameters[DeleteTransactionMetadata]{ Input: DeleteTransactionMetadata{ TransactionID: 1, @@ -210,7 +193,6 @@ func TestListTransactions(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() cursor := &bunpaginate.Cursor[ledger.Transaction]{} @@ -219,7 +201,7 @@ func TestListTransactions(t *testing.T) { ListTransactions(gomock.Any(), query). Return(cursor, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.ListTransactions(ctx, query) require.NoError(t, err) require.Equal(t, cursor, ret) @@ -230,13 +212,12 @@ func TestCountAccounts(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() query := NewListAccountsQuery(NewPaginatedQueryOptions[PITFilterWithVolumes](PITFilterWithVolumes{})) store.EXPECT().CountAccounts(gomock.Any(), query).Return(1, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) count, err := l.CountAccounts(ctx, query) require.NoError(t, err) require.Equal(t, 1, count) @@ -247,7 +228,6 @@ func TestGetTransaction(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() tx := ledger.Transaction{} @@ -256,7 +236,7 @@ func TestGetTransaction(t *testing.T) { GetTransaction(gomock.Any(), query). Return(&tx, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.GetTransaction(ctx, query) require.NoError(t, err) require.Equal(t, tx, *ret) @@ -267,7 +247,6 @@ func TestGetAccount(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() account := ledger.Account{} @@ -276,7 +255,7 @@ func TestGetAccount(t *testing.T) { GetAccount(gomock.Any(), query). Return(&account, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.GetAccount(ctx, query) require.NoError(t, err) require.Equal(t, account, *ret) @@ -287,13 +266,12 @@ func TestCountTransactions(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() query := NewListTransactionsQuery(NewPaginatedQueryOptions[PITFilterWithVolumes](PITFilterWithVolumes{})) store.EXPECT().CountTransactions(gomock.Any(), query).Return(1, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) count, err := l.CountTransactions(ctx, query) require.NoError(t, err) require.Equal(t, 1, count) @@ -304,7 +282,6 @@ func TestListAccounts(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() cursor := &bunpaginate.Cursor[ledger.Account]{} @@ -313,7 +290,7 @@ func TestListAccounts(t *testing.T) { ListAccounts(gomock.Any(), query). Return(cursor, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.ListAccounts(ctx, query) require.NoError(t, err) require.Equal(t, cursor, ret) @@ -324,7 +301,6 @@ func TestGetAggregatedBalances(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() balancesByAssets := ledger.BalancesByAssets{} @@ -333,7 +309,7 @@ func TestGetAggregatedBalances(t *testing.T) { GetAggregatedBalances(gomock.Any(), query). Return(balancesByAssets, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.GetAggregatedBalances(ctx, query) require.NoError(t, err) require.Equal(t, balancesByAssets, ret) @@ -344,7 +320,6 @@ func TestListLogs(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() cursor := &bunpaginate.Cursor[ledger.Log]{} @@ -353,7 +328,7 @@ func TestListLogs(t *testing.T) { ListLogs(gomock.Any(), query). Return(cursor, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.ListLogs(ctx, query) require.NoError(t, err) require.Equal(t, cursor, ret) @@ -364,7 +339,6 @@ func TestGetVolumesWithBalances(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() balancesByAssets := &bunpaginate.Cursor[ledger.VolumesWithBalanceByAssetByAccount]{} @@ -373,7 +347,7 @@ func TestGetVolumesWithBalances(t *testing.T) { GetVolumesWithBalances(gomock.Any(), query). Return(balancesByAssets, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.GetVolumesWithBalances(ctx, query) require.NoError(t, err) require.Equal(t, balancesByAssets, ret) @@ -384,7 +358,6 @@ func TestGetMigrationsInfo(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() migrationsInfo := make([]migrations.Info, 0) @@ -392,7 +365,7 @@ func TestGetMigrationsInfo(t *testing.T) { GetMigrationsInfo(gomock.Any()). Return(migrationsInfo, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.GetMigrationsInfo(ctx) require.NoError(t, err) require.Equal(t, migrationsInfo, ret) @@ -403,14 +376,13 @@ func TestIsDatabaseUpToDate(t *testing.T) { store := NewMockStore(ctrl) machineFactory := NewMockMachineFactory(ctrl) - listener := NewMockListener(ctrl) ctx := logging.TestingContext() store.EXPECT(). IsUpToDate(gomock.Any()). Return(true, nil) - l := NewDefaultController(ledger.Ledger{}, store, listener, machineFactory) + l := NewDefaultController(ledger.Ledger{}, store, machineFactory) ret, err := l.IsDatabaseUpToDate(ctx) require.NoError(t, err) require.True(t, ret) diff --git a/internal/controller/ledger/controller_generated.go b/internal/controller/ledger/controller_generated.go index a17ca83d0..136967c57 100644 --- a/internal/controller/ledger/controller_generated.go +++ b/internal/controller/ledger/controller_generated.go @@ -73,10 +73,10 @@ func (mr *MockControllerMockRecorder) CountTransactions(ctx, query any) *gomock. } // CreateTransaction mocks base method. -func (m *MockController) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*ledger.Transaction, error) { +func (m *MockController) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*CreateTransactionResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CreateTransaction", ctx, parameters) - ret0, _ := ret[0].(*ledger.Transaction) + ret0, _ := ret[0].(*CreateTransactionResult) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -294,10 +294,10 @@ func (mr *MockControllerMockRecorder) ListTransactions(ctx, query any) *gomock.C } // RevertTransaction mocks base method. -func (m *MockController) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*ledger.Transaction, error) { +func (m *MockController) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*RevertTransactionResult, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "RevertTransaction", ctx, parameters) - ret0, _ := ret[0].(*ledger.Transaction) + ret0, _ := ret[0].(*RevertTransactionResult) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/internal/controller/ledger/controller_with_events.go b/internal/controller/ledger/controller_with_events.go new file mode 100644 index 000000000..24944752e --- /dev/null +++ b/internal/controller/ledger/controller_with_events.go @@ -0,0 +1,124 @@ +package ledger + +import ( + "context" + "fmt" + ledger "github.com/formancehq/ledger/internal" +) + +type ControllerWithEvents struct { + Controller + ledger ledger.Ledger + listener Listener +} + +func NewControllerWithEvents(ledger ledger.Ledger, underlying Controller, listener Listener) *ControllerWithEvents { + ret := &ControllerWithEvents{ + Controller: underlying, + ledger: ledger, + listener: listener, + } + return ret +} +func (ctrl *ControllerWithEvents) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*CreateTransactionResult, error) { + ret, err := ctrl.Controller.CreateTransaction(ctx, parameters) + if err != nil { + return nil, err + } + if !parameters.DryRun { + ctrl.listener.CommittedTransactions(ctx, ctrl.ledger.Name, ret.Transaction, ret.AccountMetadata) + } + + return ret, nil +} + +func (ctrl *ControllerWithEvents) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*RevertTransactionResult, error) { + ret, err := ctrl.Controller.RevertTransaction(ctx, parameters) + if err != nil { + return nil, err + } + if !parameters.DryRun { + ctrl.listener.RevertedTransaction( + ctx, + ctrl.ledger.Name, + ret.RevertedTransaction, + ret.RevertedTransaction, + ) + } + + return ret, nil +} + +func (ctrl *ControllerWithEvents) SaveTransactionMetadata(ctx context.Context, parameters Parameters[SaveTransactionMetadata]) error { + err := ctrl.Controller.SaveTransactionMetadata(ctx, parameters) + if err != nil { + return err + } + if !parameters.DryRun { + ctrl.listener.SavedMetadata( + ctx, + ctrl.ledger.Name, + ledger.MetaTargetTypeTransaction, + fmt.Sprint(parameters.Input.TransactionID), + parameters.Input.Metadata, + ) + } + + return nil +} + +func (ctrl *ControllerWithEvents) SaveAccountMetadata(ctx context.Context, parameters Parameters[SaveAccountMetadata]) error { + err := ctrl.Controller.SaveAccountMetadata(ctx, parameters) + if err != nil { + return err + } + if !parameters.DryRun { + ctrl.listener.SavedMetadata( + ctx, + ctrl.ledger.Name, + ledger.MetaTargetTypeAccount, + parameters.Input.Address, + parameters.Input.Metadata, + ) + } + + return nil +} + +func (ctrl *ControllerWithEvents) DeleteTransactionMetadata(ctx context.Context, parameters Parameters[DeleteTransactionMetadata]) error { + err := ctrl.Controller.DeleteTransactionMetadata(ctx, parameters) + if err != nil { + return err + } + if !parameters.DryRun { + ctrl.listener.DeletedMetadata( + ctx, + ctrl.ledger.Name, + ledger.MetaTargetTypeTransaction, + fmt.Sprint(parameters.Input.TransactionID), + parameters.Input.Key, + ) + } + + return nil +} + +func (ctrl *ControllerWithEvents) DeleteAccountMetadata(ctx context.Context, parameters Parameters[DeleteAccountMetadata]) error { + err := ctrl.Controller.DeleteAccountMetadata(ctx, parameters) + if err != nil { + return err + } + if !parameters.DryRun { + ctrl.listener.DeletedMetadata( + ctx, + ctrl.ledger.Name, + ledger.MetaTargetTypeAccount, + parameters.Input.Address, + parameters.Input.Key, + ) + } + + return nil +} + +var _ Controller = (*ControllerWithEvents)(nil) diff --git a/internal/controller/ledger/controller_with_traces.go b/internal/controller/ledger/controller_with_traces.go index 9a2a0528b..75d29c93f 100644 --- a/internal/controller/ledger/controller_with_traces.go +++ b/internal/controller/ledger/controller_with_traces.go @@ -95,14 +95,14 @@ func (ctrl *ControllerWithTraces) GetVolumesWithBalances(ctx context.Context, q }) } -func (ctrl *ControllerWithTraces) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*ledger.Transaction, error) { - return tracing.Trace(ctx, "CreateTransaction", func(ctx context.Context) (*ledger.Transaction, error) { +func (ctrl *ControllerWithTraces) CreateTransaction(ctx context.Context, parameters Parameters[RunScript]) (*CreateTransactionResult, error) { + return tracing.Trace(ctx, "CreateTransaction", func(ctx context.Context) (*CreateTransactionResult, error) { return ctrl.underlying.CreateTransaction(ctx, parameters) }) } -func (ctrl *ControllerWithTraces) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*ledger.Transaction, error) { - return tracing.Trace(ctx, "RevertTransaction", func(ctx context.Context) (*ledger.Transaction, error) { +func (ctrl *ControllerWithTraces) RevertTransaction(ctx context.Context, parameters Parameters[RevertTransaction]) (*RevertTransactionResult, error) { + return tracing.Trace(ctx, "RevertTransaction", func(ctx context.Context) (*RevertTransactionResult, error) { return ctrl.underlying.RevertTransaction(ctx, parameters) }) } diff --git a/internal/controller/ledger/inputs.go b/internal/controller/ledger/inputs.go deleted file mode 100644 index 7f2d8de03..000000000 --- a/internal/controller/ledger/inputs.go +++ /dev/null @@ -1,37 +0,0 @@ -package ledger - -import ( - "github.com/formancehq/ledger/internal/machine/vm" - - "github.com/formancehq/go-libs/metadata" -) - -type RunScript = vm.RunScript -type Script = vm.Script -type ScriptV1 = vm.ScriptV1 - -type RevertTransaction struct { - Force bool - AtEffectiveDate bool - TransactionID int -} - -type SaveTransactionMetadata struct { - TransactionID int - Metadata metadata.Metadata -} - -type SaveAccountMetadata struct { - Address string - Metadata metadata.Metadata -} - -type DeleteTransactionMetadata struct { - TransactionID int - Key string -} - -type DeleteAccountMetadata struct { - Address string - Key string -} diff --git a/internal/controller/ledger/stats_test.go b/internal/controller/ledger/stats_test.go index f82fcf353..43ac90bb8 100644 --- a/internal/controller/ledger/stats_test.go +++ b/internal/controller/ledger/stats_test.go @@ -27,7 +27,6 @@ func TestStats(t *testing.T) { ledgerController := NewDefaultController( ledger.MustNewWithDefault("foo"), store, - NewMockListener(ctrl), machineFactory, ) stats, err := ledgerController.GetStats(ctx) diff --git a/internal/controller/system/controller.go b/internal/controller/system/controller.go index 8ab25d133..543d44e6b 100644 --- a/internal/controller/system/controller.go +++ b/internal/controller/system/controller.go @@ -32,31 +32,35 @@ type DefaultController struct { registry *ledgercontroller.StateRegistry } -func (c *DefaultController) GetLedgerController(ctx context.Context, name string) (ledgercontroller.Controller, error) { +func (ctrl *DefaultController) GetLedgerController(ctx context.Context, name string) (ledgercontroller.Controller, error) { return tracing.Trace(ctx, "GetLedgerController", func(ctx context.Context) (ledgercontroller.Controller, error) { - store, l, err := c.store.OpenLedger(ctx, name) + store, l, err := ctrl.store.OpenLedger(ctx, name) if err != nil { return nil, err } - var ctrl ledgercontroller.Controller = ledgercontroller.NewDefaultController( + var ledgerController ledgercontroller.Controller = ledgercontroller.NewDefaultController( *l, store, - c.listener, - ledgercontroller.NewDefaultMachineFactory(c.compiler), + ledgercontroller.NewDefaultMachineFactory(ctrl.compiler), ) - // add cache regarding database state - ctrl = ledgercontroller.NewControllerWithCache(*l, ctrl, c.registry) + // Add cache regarding database state + ledgerController = ledgercontroller.NewControllerWithCache(*l, ledgerController, ctrl.registry) - // add traces - ctrl = ledgercontroller.NewControllerWithTraces(ctrl) + // Add traces + ledgerController = ledgercontroller.NewControllerWithTraces(ledgerController) - return ctrl, nil + // Add events listener + if ctrl.listener != nil { + ledgerController = ledgercontroller.NewControllerWithEvents(*l, ledgerController, ctrl.listener) + } + + return ledgerController, nil }) } -func (c *DefaultController) CreateLedger(ctx context.Context, name string, configuration ledger.Configuration) error { +func (ctrl *DefaultController) CreateLedger(ctx context.Context, name string, configuration ledger.Configuration) error { return tracing.SkipResult(tracing.Trace(ctx, "CreateLedger", tracing.NoResult(func(ctx context.Context) error { configuration.SetDefaults() l, err := ledger.New(name, configuration) @@ -64,31 +68,31 @@ func (c *DefaultController) CreateLedger(ctx context.Context, name string, confi return err } - return c.store.CreateLedger(ctx, l) + return ctrl.store.CreateLedger(ctx, l) }))) } -func (c *DefaultController) GetLedger(ctx context.Context, name string) (*ledger.Ledger, error) { +func (ctrl *DefaultController) GetLedger(ctx context.Context, name string) (*ledger.Ledger, error) { return tracing.Trace(ctx, "GetLedger", func(ctx context.Context) (*ledger.Ledger, error) { - return c.store.GetLedger(ctx, name) + return ctrl.store.GetLedger(ctx, name) }) } -func (c *DefaultController) ListLedgers(ctx context.Context, query ledgercontroller.ListLedgersQuery) (*bunpaginate.Cursor[ledger.Ledger], error) { +func (ctrl *DefaultController) ListLedgers(ctx context.Context, query ledgercontroller.ListLedgersQuery) (*bunpaginate.Cursor[ledger.Ledger], error) { return tracing.Trace(ctx, "ListLedgers", func(ctx context.Context) (*bunpaginate.Cursor[ledger.Ledger], error) { - return c.store.ListLedgers(ctx, query) + return ctrl.store.ListLedgers(ctx, query) }) } -func (c *DefaultController) UpdateLedgerMetadata(ctx context.Context, name string, m map[string]string) error { +func (ctrl *DefaultController) UpdateLedgerMetadata(ctx context.Context, name string, m map[string]string) error { return tracing.SkipResult(tracing.Trace(ctx, "UpdateLedgerMetadata", tracing.NoResult(func(ctx context.Context) error { - return c.store.UpdateLedgerMetadata(ctx, name, m) + return ctrl.store.UpdateLedgerMetadata(ctx, name, m) }))) } -func (c *DefaultController) DeleteLedgerMetadata(ctx context.Context, param string, key string) error { +func (ctrl *DefaultController) DeleteLedgerMetadata(ctx context.Context, param string, key string) error { return tracing.SkipResult(tracing.Trace(ctx, "DeleteLedgerMetadata", tracing.NoResult(func(ctx context.Context) error { - return c.store.DeleteLedgerMetadata(ctx, param, key) + return ctrl.store.DeleteLedgerMetadata(ctx, param, key) }))) } diff --git a/test/performance/env_core_test.go b/test/performance/env_core_test.go index e09e9a940..f29572b36 100644 --- a/test/performance/env_core_test.go +++ b/test/performance/env_core_test.go @@ -44,7 +44,7 @@ func (e *CoreEnv) Executor() TransactionExecutor { return nil, err } - return ret, nil + return &ret.Transaction, nil }) } @@ -84,7 +84,7 @@ func (f *CoreEnvFactory) Create(ctx context.Context, b *testing.B, l ledger.Ledg ) return &CoreEnv{ - writer: ledgercontroller.NewDefaultController(l, ledgerStore, nil, machineFactory), + writer: ledgercontroller.NewDefaultController(l, ledgerStore, machineFactory), bunDB: bunDB, pgDatabase: pgDatabase, }