Created
June 18, 2022 09:00
-
-
Save illiafox/c2eb6de45f6529fb4f2537a1542f4a87 to your computer and use it in GitHub Desktop.
да
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func (s balanceStorage) ChangeBalance(ctx context.Context, userID int64, amount int64, desc string) error { | |
// acquire connection | |
c, err := s.pool.Acquire(ctx) | |
if err != nil { | |
return errors.NewInternal(err, "acquire connection") | |
} | |
defer c.Release() | |
// begin transaction | |
tx, err := c.Begin(ctx) | |
if err != nil { | |
return errors.NewInternal(err, "begin transaction") | |
} | |
defer tx.Rollback(ctx) // ignore error on rollback | |
// | |
var balance, balanceID int64 | |
// get balance | |
err = tx.QueryRow(ctx, "SELECT balance_id,balance FROM balances WHERE user_id = $1 FOR UPDATE", userID).Scan(&balanceID, &balance) | |
if err != nil { | |
if err == pgx.ErrNoRows { // no rows -> balance not found | |
if amount < 0 { // we can't create new balance with negative amount | |
return fmt.Errorf("balance with user id %d not found", userID) | |
} | |
// create new balance | |
err = tx.QueryRow(ctx, | |
"INSERT INTO balances (user_id,balance) VALUES ($1,$2) RETURNING balance_id", userID, amount, | |
).Scan(&balanceID) | |
} else { // internal error | |
return errors.NewInternal(err, "query: get balance for update") | |
} | |
} else { // if balance found | |
balance += amount | |
if balance < 0 { // check whether there is enough money to proceed change | |
return fmt.Errorf("insufficient funds: missing %.2f", float64(-balance)/100) | |
} | |
// update existing balance | |
_, err = tx.Exec(ctx, "UPDATE balances SET balance = $1 WHERE balance_id = $2", balance, balanceID) | |
if err != nil { | |
return errors.NewInternal(err, "exec: update balance") | |
} | |
// | |
} | |
// create record | |
_, err = tx.Exec(ctx, `INSERT INTO transactions (balance_id,action,description) | |
VALUES ($1,$2,$3,$4)`, balanceID, amount, desc) | |
if err != nil { | |
return errors.NewInternal(err, "exec: create record") | |
} | |
// commit transaction | |
err = tx.Commit(ctx) | |
if err != nil { | |
return errors.NewInternal(err, "commit transaction") | |
} | |
// | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment