From 474c53823a657b598a972847393b8c154209d527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Tigerstr=C3=B6m?= Date: Tue, 18 Feb 2025 12:02:01 +0100 Subject: [PATCH 1/2] accounts+db: Add sql db `CreditAccount` query This commit adds a separate `CreditAccount` query to the sql db, to incentivize not setting the balance directly, but rather instead increase and decrease the balance by a specific amount. We also update the sql store to use the new query function, instead of setting the balance directly. --- accounts/store_sql.go | 16 +++++----------- db/sqlc/accounts.sql.go | 19 +++++++++++++++++++ db/sqlc/querier.go | 1 + db/sqlc/queries/accounts.sql | 6 ++++++ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/accounts/store_sql.go b/accounts/store_sql.go index 830f16587..0bfc1b923 100644 --- a/accounts/store_sql.go +++ b/accounts/store_sql.go @@ -34,6 +34,7 @@ const ( //nolint:lll type SQLQueries interface { AddAccountInvoice(ctx context.Context, arg sqlc.AddAccountInvoiceParams) error + CreditAccount(ctx context.Context, arg sqlc.CreditAccountParams) (int64, error) DeleteAccount(ctx context.Context, id int64) error DeleteAccountPayment(ctx context.Context, arg sqlc.DeleteAccountPaymentParams) error GetAccount(ctx context.Context, id int64) (sqlc.Account, error) @@ -394,17 +395,10 @@ func (s *SQLStore) CreditAccount(ctx context.Context, alias AccountID, return err } - acct, err := db.GetAccount(ctx, id) - if err != nil { - return err - } - - newBalance := acct.CurrentBalanceMsat + int64(amount) - - _, err = db.UpdateAccountBalance( - ctx, sqlc.UpdateAccountBalanceParams{ - ID: id, - CurrentBalanceMsat: newBalance, + _, err = db.CreditAccount( + ctx, sqlc.CreditAccountParams{ + ID: id, + Amount: int64(amount), }, ) if err != nil { diff --git a/db/sqlc/accounts.sql.go b/db/sqlc/accounts.sql.go index 4deefdb88..562932cfd 100644 --- a/db/sqlc/accounts.sql.go +++ b/db/sqlc/accounts.sql.go @@ -26,6 +26,25 @@ func (q *Queries) AddAccountInvoice(ctx context.Context, arg AddAccountInvoicePa return err } +const creditAccount = `-- name: CreditAccount :one +UPDATE accounts +SET current_balance_msat = current_balance_msat + $2 +WHERE id = $1 +RETURNING id +` + +type CreditAccountParams struct { + ID int64 + Amount int64 +} + +func (q *Queries) CreditAccount(ctx context.Context, arg CreditAccountParams) (int64, error) { + row := q.db.QueryRowContext(ctx, creditAccount, arg.ID, arg.Amount) + var id int64 + err := row.Scan(&id) + return id, err +} + const deleteAccount = `-- name: DeleteAccount :exec DELETE FROM accounts WHERE id = $1 diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 76355ed6f..331eb3568 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -11,6 +11,7 @@ import ( type Querier interface { AddAccountInvoice(ctx context.Context, arg AddAccountInvoiceParams) error + CreditAccount(ctx context.Context, arg CreditAccountParams) (int64, error) DeleteAccount(ctx context.Context, id int64) error DeleteAccountPayment(ctx context.Context, arg DeleteAccountPaymentParams) error DeleteSessionsWithState(ctx context.Context, state int16) error diff --git a/db/sqlc/queries/accounts.sql b/db/sqlc/queries/accounts.sql index 637a49727..c745ef14b 100644 --- a/db/sqlc/queries/accounts.sql +++ b/db/sqlc/queries/accounts.sql @@ -9,6 +9,12 @@ SET current_balance_msat = $1 WHERE id = $2 RETURNING id; +-- name: CreditAccount :one +UPDATE accounts +SET current_balance_msat = current_balance_msat + sqlc.arg(amount) +WHERE id = $1 +RETURNING id; + -- name: UpdateAccountExpiry :one UPDATE accounts SET expiration = $1 From 46bc3c006c1136f706c174a774087b784c3d42bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Tigerstr=C3=B6m?= Date: Tue, 18 Mar 2025 09:23:59 +0000 Subject: [PATCH 2/2] accounts+db: Add sql db `DebitAccount` query This commit adds a separate `DebitAccount` query to the sql db, to incentivize not setting the balance directly, but rather instead increase and decrease the balance by a specific amount. We also update the sql store to use the new query function, instead of setting the balance directly. --- accounts/store_sql.go | 26 +++++++++----------------- db/sqlc/accounts.sql.go | 20 ++++++++++++++++++++ db/sqlc/querier.go | 1 + db/sqlc/queries/accounts.sql | 7 +++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/accounts/store_sql.go b/accounts/store_sql.go index 0bfc1b923..4febdde62 100644 --- a/accounts/store_sql.go +++ b/accounts/store_sql.go @@ -35,6 +35,7 @@ const ( type SQLQueries interface { AddAccountInvoice(ctx context.Context, arg sqlc.AddAccountInvoiceParams) error CreditAccount(ctx context.Context, arg sqlc.CreditAccountParams) (int64, error) + DebitAccount(ctx context.Context, arg sqlc.DebitAccountParams) (int64, error) DeleteAccount(ctx context.Context, id int64) error DeleteAccountPayment(ctx context.Context, arg sqlc.DeleteAccountPaymentParams) error GetAccount(ctx context.Context, id int64) (sqlc.Account, error) @@ -423,26 +424,17 @@ func (s *SQLStore) DebitAccount(ctx context.Context, alias AccountID, return err } - acct, err := db.GetAccount(ctx, id) - if err != nil { - return err - } - - if acct.CurrentBalanceMsat-int64(amount) < 0 { + id, err = db.DebitAccount( + ctx, sqlc.DebitAccountParams{ + ID: id, + Amount: int64(amount), + }, + ) + if errors.Is(err, sql.ErrNoRows) { return fmt.Errorf("cannot debit %v from the account "+ "balance, as the resulting balance would be "+ "below 0", int64(amount/1000)) - } - - newBalance := acct.CurrentBalanceMsat - int64(amount) - - _, err = db.UpdateAccountBalance( - ctx, sqlc.UpdateAccountBalanceParams{ - ID: id, - CurrentBalanceMsat: newBalance, - }, - ) - if err != nil { + } else if err != nil { return err } diff --git a/db/sqlc/accounts.sql.go b/db/sqlc/accounts.sql.go index 562932cfd..1b991a183 100644 --- a/db/sqlc/accounts.sql.go +++ b/db/sqlc/accounts.sql.go @@ -45,6 +45,26 @@ func (q *Queries) CreditAccount(ctx context.Context, arg CreditAccountParams) (i return id, err } +const debitAccount = `-- name: DebitAccount :one +UPDATE accounts +SET current_balance_msat = current_balance_msat - $2 +WHERE id = $1 +AND current_balance_msat >= $2 +RETURNING id +` + +type DebitAccountParams struct { + ID int64 + Amount int64 +} + +func (q *Queries) DebitAccount(ctx context.Context, arg DebitAccountParams) (int64, error) { + row := q.db.QueryRowContext(ctx, debitAccount, arg.ID, arg.Amount) + var id int64 + err := row.Scan(&id) + return id, err +} + const deleteAccount = `-- name: DeleteAccount :exec DELETE FROM accounts WHERE id = $1 diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 331eb3568..7fad274aa 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -12,6 +12,7 @@ import ( type Querier interface { AddAccountInvoice(ctx context.Context, arg AddAccountInvoiceParams) error CreditAccount(ctx context.Context, arg CreditAccountParams) (int64, error) + DebitAccount(ctx context.Context, arg DebitAccountParams) (int64, error) DeleteAccount(ctx context.Context, id int64) error DeleteAccountPayment(ctx context.Context, arg DeleteAccountPaymentParams) error DeleteSessionsWithState(ctx context.Context, state int16) error diff --git a/db/sqlc/queries/accounts.sql b/db/sqlc/queries/accounts.sql index c745ef14b..1512a430b 100644 --- a/db/sqlc/queries/accounts.sql +++ b/db/sqlc/queries/accounts.sql @@ -15,6 +15,13 @@ SET current_balance_msat = current_balance_msat + sqlc.arg(amount) WHERE id = $1 RETURNING id; +-- name: DebitAccount :one +UPDATE accounts +SET current_balance_msat = current_balance_msat - sqlc.arg(amount) +WHERE id = $1 +AND current_balance_msat >= sqlc.arg(amount) +RETURNING id; + -- name: UpdateAccountExpiry :one UPDATE accounts SET expiration = $1