70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/xerr"
|
|
)
|
|
|
|
type transactionRow struct {
|
|
TransactionID string
|
|
MetadataJSON string
|
|
}
|
|
|
|
func (r *Repository) lookupTransaction(ctx context.Context, tx *sql.Tx, commandID string, requestHash string, bizType string) (transactionRow, bool, error) {
|
|
return r.lookupTransactionWithConflictCode(ctx, tx, commandID, requestHash, bizType, xerr.LedgerConflict)
|
|
}
|
|
|
|
func (r *Repository) lookupTransactionWithConflictCode(ctx context.Context, tx *sql.Tx, commandID string, requestHash string, bizType string, conflictCode xerr.Code) (transactionRow, bool, error) {
|
|
row := tx.QueryRowContext(ctx,
|
|
`SELECT transaction_id, request_hash, biz_type, COALESCE(CAST(metadata_json AS CHAR), '{}')
|
|
FROM wallet_transactions
|
|
WHERE app_code = ? AND command_id = ?
|
|
FOR UPDATE`,
|
|
appcode.FromContext(ctx),
|
|
commandID,
|
|
)
|
|
|
|
var txRow transactionRow
|
|
var storedHash string
|
|
var storedBizType string
|
|
if err := row.Scan(&txRow.TransactionID, &storedHash, &storedBizType, &txRow.MetadataJSON); err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return transactionRow{}, false, nil
|
|
}
|
|
return transactionRow{}, false, err
|
|
}
|
|
if storedHash != requestHash || storedBizType != bizType {
|
|
|
|
return transactionRow{}, true, xerr.New(conflictCode, "wallet command idempotency conflict")
|
|
}
|
|
return txRow, true, nil
|
|
}
|
|
|
|
func (r *Repository) insertTransaction(ctx context.Context, tx *sql.Tx, transactionID string, commandID string, bizType string, requestHash string, externalRef string, metadata any, nowMs int64) error {
|
|
metadataJSON, err := json.Marshal(metadata)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = tx.ExecContext(ctx,
|
|
`INSERT INTO wallet_transactions (
|
|
app_code, transaction_id, command_id, biz_type, status, request_hash, external_ref, metadata_json, created_at_ms, updated_at_ms
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
appcode.FromContext(ctx),
|
|
transactionID,
|
|
commandID,
|
|
bizType,
|
|
transactionStatusSucceeded,
|
|
requestHash,
|
|
externalRef,
|
|
string(metadataJSON),
|
|
nowMs,
|
|
nowMs,
|
|
)
|
|
return err
|
|
}
|