Skip to content

Commit

Permalink
fix: invalid state with posting A -> A (#1138)
Browse files Browse the repository at this point in the history
  • Loading branch information
gfyrag authored Jan 19, 2024
1 parent 4bd95f6 commit 1d58454
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
5 changes: 5 additions & 0 deletions components/ledger/internal/engine/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"sync"

"github.com/pkg/errors"

"github.com/formancehq/ledger/internal/storage/ledgerstore"

"github.com/ThreeDotsLabs/watermill/message"
Expand Down Expand Up @@ -79,6 +81,9 @@ func (r *Resolver) startLedgerUsingStore(ctx context.Context, name string, store
}

func (r *Resolver) GetLedger(ctx context.Context, name string) (*Ledger, error) {
if name == "" {
return nil, errors.New("empty name")
}
r.lock.RLock()
ledger, ok := r.ledgers[name]
r.lock.RUnlock()
Expand Down
10 changes: 10 additions & 0 deletions components/ledger/internal/storage/ledgerstore/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
//go:embed migrations/0-init-schema.sql
var initSchema string

//go:embed migrations/1-fix-trigger.sql
var fixTrigger string

type Bucket struct {
name string
db *bun.DB
Expand Down Expand Up @@ -127,6 +130,13 @@ func registerMigrations(migrator *migrations.Migrator, name string) {
return nil
},
},
migrations.Migration{
Name: "Fix trigger",
UpWithContext: func(ctx context.Context, tx bun.Tx) error {
_, err := tx.ExecContext(ctx, fixTrigger)
return err
},
},
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
create or replace function insert_posting(_transaction_seq bigint, _ledger varchar, _insertion_date timestamp without time zone,
_effective_date timestamp without time zone, posting jsonb, _account_metadata jsonb)
returns void
language plpgsql
as
$$
declare
_source_exists bool;
_destination_exists bool;
begin

select true from accounts where ledger = _ledger and address = posting ->> 'source' into _source_exists;
if posting ->>'source' = posting->>'destination' then
_destination_exists = true;
else
select true from accounts where ledger = _ledger and address = posting ->> 'destination' into _destination_exists;
end if;

perform upsert_account(_ledger, posting ->> 'source', _account_metadata -> (posting ->> 'source'), _insertion_date);
perform upsert_account(_ledger, posting ->> 'destination', _account_metadata -> (posting ->> 'destination'),
_insertion_date);

-- todo: sometimes the balance is known at commit time (for sources != world), we need to forward the value to populate the pre_commit_aggregated_input and output
perform insert_move(_transaction_seq, _ledger, _insertion_date, _effective_date,
posting ->> 'source', posting ->> 'asset', (posting ->> 'amount')::numeric, true,
_source_exists);
perform insert_move(_transaction_seq, _ledger, _insertion_date, _effective_date,
posting ->> 'destination', posting ->> 'asset', (posting ->> 'amount')::numeric, false,
_destination_exists);
end;
$$;
Original file line number Diff line number Diff line change
Expand Up @@ -1074,3 +1074,20 @@ func TestGetLastTransaction(t *testing.T) {
require.NoError(t, err)
require.Equal(t, *tx3, tx.Transaction)
}

func TestTransactionFromWorldToWorld(t *testing.T) {
t.Parallel()
store := newLedgerStore(t)
ctx := logging.TestingContext()

tx := ledger.NewTransaction().
WithIDUint64(0).
WithPostings(
ledger.NewPosting("world", "world", "USD", big.NewInt(100)),
)
require.NoError(t, store.InsertLogs(ctx, ledger.ChainLogs(ledger.NewTransactionLog(tx, map[string]metadata.Metadata{}))...))

account, err := store.GetAccountWithVolumes(ctx, NewGetAccountQuery("world").WithExpandVolumes())
require.NoError(t, err)
internaltesting.RequireEqual(t, big.NewInt(0), account.Volumes.Balances()["USD"])
}

0 comments on commit 1d58454

Please sign in to comment.