Skip to content

Commit

Permalink
fix(ledger): use a unique index on idempotency key and ledger (#1638)
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-nicolas committed Aug 16, 2024
1 parent 3c20f74 commit 43bced8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
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 @@ -41,6 +41,9 @@ var addIndexOnReference string
//go:embed migrations/7-add-ik-unique-index.sql
var addIKUniqueIndex string

//go:embed migrations/8-ik-ledger-unique-index.sql
var updateIKUniqueIndex string

type Bucket struct {
name string
db *bun.DB
Expand Down Expand Up @@ -200,6 +203,13 @@ func registerMigrations(migrator *migrations.Migrator, name string) {
return err
},
},
migrations.Migration{
Name: "Update unique index on IK",
UpWithContext: func(ctx context.Context, tx bun.Tx) error {
_, err := tx.ExecContext(ctx, updateIKUniqueIndex)
return err
},
},
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
drop index logs_idempotency_key;

create unique index logs_idempotency_key on logs (ledger, idempotency_key);
70 changes: 70 additions & 0 deletions tests/integration/suite/ledger-create-transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ var _ = WithModules([]*Module{modules.Search, modules.Ledger}, func() {
})
Expect(err).To(BeNil())
Expect(createLedgerResponse.StatusCode).To(Equal(http.StatusNoContent))

createLedgerResponse, err = Client().Ledger.V2CreateLedger(TestContext(), operations.V2CreateLedgerRequest{
Ledger: "test",
})
Expect(err).To(BeNil())
Expect(createLedgerResponse.StatusCode).To(Equal(http.StatusNoContent))
})
When("creating a transaction on a ledger", func() {
var (
Expand Down Expand Up @@ -286,6 +292,70 @@ var _ = WithModules([]*Module{modules.Search, modules.Ledger}, func() {
})
})

When("creating a transaction on a ledger with an idempotency key and a specific ledger", func() {
var (
err error
response *operations.V2CreateTransactionResponse
timestamp = time.Now().Add(-1 * time.Minute).Round(time.Second).UTC()
timestamp2 = time.Now().Round(time.Second).UTC()
)
BeforeEach(func() {
// Create a transaction
response, err = Client().Ledger.V2CreateTransaction(
TestContext(),
operations.V2CreateTransactionRequest{
IdempotencyKey: pointer.For("foo"),
V2PostTransaction: shared.V2PostTransaction{
Metadata: map[string]string{},
Postings: []shared.V2Posting{
{
Amount: big.NewInt(100),
Asset: "USD",
Source: "world",
Destination: "alice",
},
},
Timestamp: &timestamp,
Reference: pointer.For("foo"),
},
Ledger: "default",
},
)
})
It("should be ok", func() {
Expect(err).To(Succeed())
Expect(response.V2CreateTransactionResponse.Data.ID).To(Equal(big.NewInt(0)))
})
Then("creating a ledger transaction with same ik and different ledger", func() {
BeforeEach(func() {
response, err = Client().Ledger.V2CreateTransaction(
TestContext(),
operations.V2CreateTransactionRequest{
IdempotencyKey: pointer.For("foo"),
V2PostTransaction: shared.V2PostTransaction{
Metadata: map[string]string{},
Postings: []shared.V2Posting{
{
Amount: big.NewInt(100),
Asset: "USD",
Source: "world",
Destination: "alice",
},
},
Timestamp: &timestamp2,
Reference: pointer.For("foo2"),
},
Ledger: "test",
},
)
})
It("should not have an error", func() {
Expect(err).To(Succeed())
Expect(response.V2CreateTransactionResponse.Data.ID).To(Equal(big.NewInt(0)))
})
})
})

When("creating a transaction on a ledger with an idempotency key", func() {
var (
err error
Expand Down

0 comments on commit 43bced8

Please sign in to comment.