Skip to content

Solution/priyank patel#104

Open
priiyank-xd wants to merge 3 commits into
Robustrade:mainfrom
priiyank-xd:solution/priyank-patel
Open

Solution/priyank patel#104
priiyank-xd wants to merge 3 commits into
Robustrade:mainfrom
priiyank-xd:solution/priyank-patel

Conversation

@priiyank-xd

@priiyank-xd priiyank-xd commented Jul 2, 2026

Copy link
Copy Markdown

.

Copilot AI review requested due to automatic review settings July 2, 2026 13:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a minimal wallet-to-wallet transfer service (POST /transfers) backed by Postgres, focusing on idempotency, double-entry ledger writes, and concurrency safety via row locks. The PR also adds migrations/seed data, local dev tooling (docker-compose + Makefile), and integration-style tests for handler/service/domain validation.

Changes:

  • Added Postgres schema + seed migrations for wallets/transfers/ledger/idempotency records.
  • Implemented handler/service/repository/domain layers for creating transfers with idempotency + ledger entries and concurrency locking.
  • Added integration tests and local development tooling/docs to run the service and validate behavior.

Reviewed changes

Copilot reviewed 28 out of 30 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
TEST_CASES.md Test plan documenting expected validation/idempotency/ledger/concurrency behaviors.
PR_DESCRIPTION.md Solution write-up covering schema, idempotency, concurrency, and run/test instructions.
migrations/000001_init_schema.up.sql Creates core tables/constraints/indexes for wallets, transfers, ledger entries, idempotency records.
migrations/000001_init_schema.down.sql Drops tables in dependency-safe order.
migrations/000002_seed_wallets.up.sql Seeds wallet-alice and wallet-bob balances.
migrations/000002_seed_wallets.down.sql Removes seeded wallets.
Makefile Adds db-up/down/logs and migration helper targets.
internal/testutil/db.go Test DB helper for pooling, advisory lock, reset, and assertions helpers.
internal/service/transfer_service.go Core transfer workflow: validate, idempotency lookup, tx, wallet locks, status/ledger/balance updates.
internal/service/transfer_service_test.go Service-level integration tests for validation, ledger, idempotency, and concurrency behavior.
internal/repository/wallet_repository.go Wallet lock + balance update SQL methods.
internal/repository/transfer_repository.go Transfer/idempotency/ledger persistence methods.
internal/repository/transaction.go Transaction wrapper helper (WithTx).
internal/repository/repository.go Repository struct + constructor.
internal/repository/errors.go Repository error constants.
internal/handler/transfer_handler.go HTTP endpoint wiring + request decode + response/status mapping.
internal/handler/transfer_handler_test.go Handler integration tests covering success and key error paths.
internal/domain/wallet.go Wallet domain model.
internal/domain/transfer.go Transfer models + request validation.
internal/domain/transfer_test.go Unit tests for request validation rules.
internal/domain/status.go Transfer status enum.
internal/domain/ledger.go Ledger entry model + entry type enum.
internal/domain/errors.go Domain error definitions.
internal/config/config.go Runtime config loading for DB URL and HTTP port.
go.mod Defines module and Go/toolchain version + dependencies.
go.sum Dependency checksums.
docker-compose.yml Local Postgres + migrate service for running migrations.
cmd/server/main.go Service wiring + HTTP server + graceful shutdown.
.gitignore Expanded ignore patterns for local dev artifacts and tooling.
.env.example Example environment variables for local runs.

Comment thread go.mod
@@ -0,0 +1,16 @@
module github.com/priiyank-xd/wallet-transfer-service

go 1.25.0
Comment thread PR_DESCRIPTION.md

Requirements:
- Docker
- Go 1.25+
return s.processTransfer(ctx, req)
}

func (s *TransferService) checkIdemPotencyRecord(ctx context.Context, key string) (domain.TransferResponse, int, bool, error) {
return resp, http.StatusBadRequest, err
}

stored, status, ok, err := s.checkIdemPotencyRecord(ctx, req.IdempotencyKey)
}

func (s *TransferService) loadStoredResponse(ctx context.Context, key string) (domain.TransferResponse, int, error) {
if resp, status, ok, err := s.checkIdemPotencyRecord(ctx, key); err != nil {
Comment thread internal/testutil/db.go
Comment on lines +64 to +69
if _, err := pool.Exec(ctx,
`UPDATE wallets SET balance = $1, updated_at = NOW() WHERE id = $2`,
AliceSeedBalance, WalletAlice,
); err != nil {
t.Fatalf("reset alice balance: %v", err)
}
Comment thread internal/testutil/db.go
Comment on lines +70 to +75
if _, err := pool.Exec(ctx,
`UPDATE wallets SET balance = $1, updated_at = NOW() WHERE id = $2`,
BobSeedBalance, WalletBob,
); err != nil {
t.Fatalf("reset bob balance: %v", err)
}
Comment thread internal/testutil/db.go
Comment on lines +81 to +87
_, err := pool.Exec(context.Background(),
`UPDATE wallets SET balance = $2, updated_at = NOW() WHERE id = $1`,
walletID, balance,
)
if err != nil {
t.Fatalf("set wallet balance: %v", err)
}
Comment on lines +36 to +41
func (r *Repository) UpdateBalance(ctx context.Context, tx pgx.Tx, walletID string, delta int64) error {
query := `UPDATE wallets SET balance = balance + $2, updated_at = NOW() WHERE id = $1`

_, err := tx.Exec(ctx, query, walletID, delta)
return err
}
Comment on lines +45 to +52
func (r *Repository) FindIdempotencyRecord(ctx context.Context, key string) ([]byte, int, error) {
query := `SELECT response_body, http_status FROM idempotency_records WHERE idempotency_key = $1`

var body []byte
var status int

err := r.pool.QueryRow(ctx, query, key).Scan(&body, &status)
if errors.Is(err, pgx.ErrNoRows) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants