forked from ebhomengo/niki
ADD | general instant queries & debug sth
This commit is contained in:
parent
44bfde3c65
commit
9a219730a0
|
|
@ -32,7 +32,7 @@ func (db *DB) GetTransactionListByUserID(ctx context.Context, userID uint64, dbP
|
||||||
scanTransaction, countParams, fetchParams,
|
scanTransaction, countParams, fetchParams,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, richerror.New(op).WithErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return transactionsList, totalItemsCount, nil
|
return transactionsList, totalItemsCount, nil
|
||||||
|
|
@ -101,7 +101,7 @@ func (db *DB) GetTransactionListByUserID(ctx context.Context, userID uint64, dbP
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanTransaction(scanner postgres.Scanner) (transaction entity.Transaction, err error) {
|
func scanTransaction(scanner postgres.Scanner) (transaction entity.Transaction, err error) {
|
||||||
err = scanner.Scan(&transaction.UserID, &transaction.Currency, &transaction.Amount, &transaction.ActionType, &transaction.Timestamp, &transaction.CreatedAt)
|
err = scanner.Scan(&transaction.ID, &transaction.UserID, &transaction.Amount, &transaction.Currency, &transaction.ActionType, &transaction.Timestamp, &transaction.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,11 @@ func (db *DB) InsertTransaction(ctx context.Context, transaction entity.Transact
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
params := []any{transaction.UserID, transaction.Currency, transaction.Amount, transaction.ActionType, transaction.Timestamp}
|
params := []any{transaction.UserID, transaction.Amount, transaction.Currency, transaction.ActionType, transaction.Timestamp}
|
||||||
|
|
||||||
_, execErr := tx.StmtExecContext(newCtx, stmt, params...)
|
_, execErr := tx.StmtExecContext(newCtx, stmt, params...)
|
||||||
if execErr != nil {
|
if execErr != nil {
|
||||||
err = richerror.New(op).WithErr(execErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantInsertTransaction)
|
err = richerror.New(op).WithErr(execErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package postgres
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/domain/wallet/entity"
|
||||||
|
"git.gocasts.ir/ebhomengo/niki/pkg/database/postgres"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *DB) GetWalletByUserID(ctx context.Context, UserID uint64) (entity.Wallet, error) {
|
||||||
|
|
||||||
|
const op = richerror.Op("Wallet.repo.GetWalletByUserID")
|
||||||
|
|
||||||
|
query := `SELECT * FROM wallets WHERE user_id = $1`
|
||||||
|
|
||||||
|
/////////////// use instant query
|
||||||
|
|
||||||
|
wallet, err := postgres.InstantQueryRowContext[entity.Wallet](ctx, postgres.StatementKeyWalletGetUserWallet, query, db.conn, scanWallet, UserID)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Wallet{}, richerror.New(op).WithErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet, nil
|
||||||
|
|
||||||
|
//////////////////////normal
|
||||||
|
|
||||||
|
//stmt, stErr := db.conn.PrepareStatement(ctx, postgres.StatementKeyWalletGetUserWallet, query)
|
||||||
|
//if stErr != nil {
|
||||||
|
// return entity.Wallet{}, richerror.New(op).WithErr(stErr)
|
||||||
|
//}
|
||||||
|
//walletRow := db.conn.StmtQueryRowContext(ctx, stmt, UserID)
|
||||||
|
//
|
||||||
|
//wallet, sErr := scanWallet(walletRow)
|
||||||
|
//
|
||||||
|
//if sErr != nil {
|
||||||
|
// return entity.Wallet{}, richerror.New(op).WithErr(sErr)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//return wallet, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func scanWallet(scanner postgres.Scanner) (entity.Wallet, error) {
|
||||||
|
|
||||||
|
var wallet entity.Wallet
|
||||||
|
|
||||||
|
err := scanner.Scan(&wallet.ID, &wallet.UserID, &wallet.Balance, &wallet.Currency, &wallet.Status, &wallet.UpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return entity.Wallet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet, nil
|
||||||
|
}
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package postgres
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/domain/wallet/entity"
|
|
||||||
"git.gocasts.ir/ebhomengo/niki/pkg/database/postgres"
|
|
||||||
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (db *DB) GetWalletByUserID(ctx context.Context, UserID uint64) (entity.Wallet, error) {
|
|
||||||
const op = richerror.Op("Wallet.repo.GetWalletByUserID")
|
|
||||||
query := `SELECT * FROM wallets WHERE user_id = $1`
|
|
||||||
stmt, stErr := db.conn.PrepareStatement(ctx, postgres.StatementKeyWalletGetUserWallet, query)
|
|
||||||
if stErr != nil {
|
|
||||||
return entity.Wallet{}, richerror.New(op).WithErr(stErr)
|
|
||||||
}
|
|
||||||
walletRow := db.conn.StmtQueryRowContext(ctx, stmt, UserID)
|
|
||||||
|
|
||||||
wallet, sErr := scanWallet(walletRow)
|
|
||||||
|
|
||||||
if sErr != nil {
|
|
||||||
return entity.Wallet{}, richerror.New(op).WithErr(sErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return wallet, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanWallet(scanner postgres.Scanner) (entity.Wallet, error) {
|
|
||||||
|
|
||||||
var wallet entity.Wallet
|
|
||||||
|
|
||||||
err := scanner.Scan(&wallet.ID, &wallet.Balance, &wallet.Currency, &wallet.Status, &wallet.UpdatedAt)
|
|
||||||
if err != nil {
|
|
||||||
return entity.Wallet{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return wallet, nil
|
|
||||||
}
|
|
||||||
|
|
@ -22,11 +22,11 @@ func (s Service) CreateTransaction(ctx context.Context, request param.CreateTran
|
||||||
Timestamp: request.Timestamp,
|
Timestamp: request.Timestamp,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
err := s.repo.InsertTransaction(ctx, transaction)
|
balance, err := s.repo.InsertTransaction(ctx, transaction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return param.InsertTransactionResponse{}, richerror.New(op).WithErr(err)
|
return param.InsertTransactionResponse{}, richerror.New(op).WithErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return param.InsertTransactionResponse{}, nil
|
return param.InsertTransactionResponse{Balance: balance}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import (
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
GetTransactionListByUserID(ctx context.Context, UserID uint64, DBPagination postgres.DBPagination) ([]entity.Transaction, int64, error)
|
GetTransactionListByUserID(ctx context.Context, UserID uint64, DBPagination postgres.DBPagination) ([]entity.Transaction, int64, error)
|
||||||
GetWalletByUserID(ctx context.Context, UserID uint64) (entity.Wallet, error)
|
GetWalletByUserID(ctx context.Context, UserID uint64) (entity.Wallet, error)
|
||||||
InsertTransaction(ctx context.Context, transaction entity.Transaction) error
|
InsertTransaction(ctx context.Context, transaction entity.Transaction) (float64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ package postgres
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
_ "github.com/jackc/pgx/v5/stdlib"
|
_ "github.com/jackc/pgx/v5/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -111,3 +114,96 @@ func (db *DB) StmtExecContext(ctx context.Context, stmt *sql.Stmt, args ...any)
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////// generic query
|
||||||
|
|
||||||
|
type ScannerFunc[T any] func(scanner Scanner) (T, error)
|
||||||
|
|
||||||
|
func InstantQueryContext[T any](ctx context.Context, stmtKey statementKey, query string, conn *DB, scanner ScannerFunc[T], args ...any) ([]T, error) {
|
||||||
|
const op = richerror.Op("postgres.InstantQueryContext")
|
||||||
|
|
||||||
|
readyStmt, err := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, qErr := readyStmt.QueryContext(ctx, args...)
|
||||||
|
|
||||||
|
if qErr != nil {
|
||||||
|
return nil, richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var itemsList []T
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
|
||||||
|
item, sErr := scanner(rows)
|
||||||
|
if sErr != nil {
|
||||||
|
return nil, richerror.New(op).WithErr(sErr).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsList = append(itemsList, item)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if rErr := rows.Err(); rErr != nil {
|
||||||
|
return nil, richerror.New(op).WithErr(rErr).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemsList, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstantQueryRowContext[T any](ctx context.Context, stmtKey statementKey, query string, conn *DB, scanner ScannerFunc[T], args ...any) (item T, err error) {
|
||||||
|
const op = richerror.Op("postgres.InstantQueryRowContext")
|
||||||
|
readyStmt, sErr := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if sErr != nil {
|
||||||
|
err = richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
row := readyStmt.QueryRowContext(ctx, args...)
|
||||||
|
|
||||||
|
item, scErr := scanner(row)
|
||||||
|
if scErr != nil {
|
||||||
|
if errors.Is(scErr, sql.ErrNoRows) {
|
||||||
|
err = richerror.New(op).WithErr(scErr).WithKind(richerror.KindNotFound).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
err = richerror.New(op).WithErr(scErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if rErr := row.Err(); rErr != nil {
|
||||||
|
err = richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func InstantExecContext(ctx context.Context, stmtKey statementKey, query string, conn *DB, args ...any) (sql.Result, error) {
|
||||||
|
const op = richerror.Op("postgres.InstantExecContext")
|
||||||
|
|
||||||
|
readyStmt, err := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := readyStmt.ExecContext(ctx, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ type DBPagination struct {
|
||||||
PageSize int64
|
PageSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScannerFunc[T any] func(scanner Scanner) (T, error)
|
|
||||||
|
|
||||||
func PageNumberPagination[T any](ctx context.Context, countQuery string, fetchQuery string, conn *DB, countQueryStmt statementKey, fetchQueryStmt statementKey, op richerror.Op, scanner ScannerFunc[T], countParams []any, fetchParams []any) ([]T, int64, error) {
|
func PageNumberPagination[T any](ctx context.Context, countQuery string, fetchQuery string, conn *DB, countQueryStmt statementKey, fetchQueryStmt statementKey, op richerror.Op, scanner ScannerFunc[T], countParams []any, fetchParams []any) ([]T, int64, error) {
|
||||||
|
|
||||||
var totalCount int64
|
var totalCount int64
|
||||||
|
|
@ -78,7 +76,7 @@ func PageNumberPagination[T any](ctx context.Context, countQuery string, fetchQu
|
||||||
|
|
||||||
if qErr := queryRows.Err(); qErr != nil {
|
if qErr := queryRows.Err(); qErr != nil {
|
||||||
|
|
||||||
return nil, 0, richerror.New(op).WithErr(qErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
return nil, 0, richerror.New(op).WithErr(qErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
return itemsList, totalCount, nil
|
return itemsList, totalCount, nil
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@ package postgres
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg"
|
||||||
|
richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error"
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -176,3 +179,99 @@ func (tx *TxConn) StmtExecContext(ctx context.Context, stmt *sql.Stmt, args ...a
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////// generic query
|
||||||
|
|
||||||
|
func TXInstantQueryContext[T any](ctx context.Context, txConn *sql.Tx, stmtKey statementKey, query string, conn *DB, scanner ScannerFunc[T], args ...any) ([]T, error) {
|
||||||
|
const op = richerror.Op("postgres.TXInstantQueryContext")
|
||||||
|
|
||||||
|
stmt, err := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
txStmt := txConn.StmtContext(ctx, stmt)
|
||||||
|
|
||||||
|
rows, qErr := txStmt.QueryContext(ctx, args...)
|
||||||
|
|
||||||
|
if qErr != nil {
|
||||||
|
return nil, richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var itemsList []T
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
|
||||||
|
item, sErr := scanner(rows)
|
||||||
|
if sErr != nil {
|
||||||
|
return nil, richerror.New(op).WithErr(sErr).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsList = append(itemsList, item)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if rErr := rows.Err(); rErr != nil {
|
||||||
|
return nil, richerror.New(op).WithErr(rErr).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemsList, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TXInstantQueryRowContext[T any](ctx context.Context, txConn *sql.Tx, stmtKey statementKey, query string, conn *DB, scanner ScannerFunc[T], args ...any) (item T, err error) {
|
||||||
|
const op = richerror.Op("postgres.TXInstantQueryRowContext")
|
||||||
|
|
||||||
|
stmt, sErr := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if sErr != nil {
|
||||||
|
err = richerror.New(op).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
txStmt := txConn.StmtContext(ctx, stmt)
|
||||||
|
|
||||||
|
row := txStmt.QueryRowContext(ctx, args...)
|
||||||
|
|
||||||
|
item, scErr := scanner(row)
|
||||||
|
if scErr != nil {
|
||||||
|
if errors.Is(scErr, sql.ErrNoRows) {
|
||||||
|
err = richerror.New(op).WithErr(scErr).WithKind(richerror.KindNotFound).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
err = richerror.New(op).WithErr(scErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgCantScanQueryResult)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if rErr := row.Err(); rErr != nil {
|
||||||
|
err = richerror.New(op).WithErr(rErr).WithKind(richerror.KindUnexpected).WithMessage(errmsg.ErrorMsgFailedQuery)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TXInstantExecContext(ctx context.Context, txConn *sql.Tx, stmtKey statementKey, query string, conn *DB, args ...any) (sql.Result, error) {
|
||||||
|
const op = richerror.Op("postgres.TXInstantExecContext")
|
||||||
|
|
||||||
|
stmt, err := conn.PrepareStatement(ctx, stmtKey, query)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op)
|
||||||
|
}
|
||||||
|
txStmt := txConn.StmtContext(ctx, stmt)
|
||||||
|
|
||||||
|
result, err := txStmt.ExecContext(ctx, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, richerror.New(op)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,6 @@ const (
|
||||||
ErrorMsgInvalidBenefactorStatus = "invalid benefactor status"
|
ErrorMsgInvalidBenefactorStatus = "invalid benefactor status"
|
||||||
ErrorMsgInvalidAction = "action invalid"
|
ErrorMsgInvalidAction = "action invalid"
|
||||||
ErrorMsgCantUpsertBalance = "cant update balance" // wallet
|
ErrorMsgCantUpsertBalance = "cant update balance" // wallet
|
||||||
ErrorMsgCantGetBalance = "cant update balance" // wallet
|
|
||||||
ErrorMsgCantInsertTransaction = "cant insert transaction" // wallet
|
|
||||||
ErrorMsgFailedQuery = "query failed" // wallet
|
ErrorMsgFailedQuery = "query failed" // wallet
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue