package repository import ( "context" "fmt" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/yourorg/go-dw-platform/services/template-service/entity" ) type Filter struct { StartDate time.Time EndDate time.Time Limit int } type Repository struct { pool *pgxpool.Pool } func New(pool *pgxpool.Pool) *Repository { return &Repository{pool: pool} } func (r *Repository) ExistsByKey(ctx context.Context, naturalKey string) (bool, error) { var exists bool err := r.pool.QueryRow(ctx, `SELECT EXISTS(SELECT 1 FROM orders WHERE natural_key = $1)`, naturalKey, ).Scan(&exists) if err != nil { return false, fmt.Errorf("exists by key: %w", err) } return exists, nil } func (r *Repository) InsertBatch(ctx context.Context, entities []*entity.Order) (int64, error) { tx, err := r.pool.Begin(ctx) if err != nil { return 0, fmt.Errorf("begin tx: %w", err) } defer tx.Rollback(ctx) stmt := `INSERT INTO orders (order_id, customer_id, amount, natural_key, created_at) VALUES ($1, $2, $3, $4, $5)` batch := &pgx.Batch{} for _, e := range entities { naturalKey := fmt.Sprintf("%s_%s_%d", e.OrderID, e.CustomerID, e.CreatedAt.Unix()) batch.Queue(stmt, e.OrderID, e.CustomerID, e.Amount, naturalKey, e.CreatedAt) } results := tx.SendBatch(ctx, batch) var rowsInserted int64 for i := 0; i < len(entities); i++ { tag, err := results.Exec() if err != nil { results.Close() return 0, fmt.Errorf("exec batch: %w", err) } rowsInserted += tag.RowsAffected() } if err := results.Close(); err != nil { return 0, fmt.Errorf("close batch results: %w", err) } if err := tx.Commit(ctx); err != nil { return 0, fmt.Errorf("commit: %w", err) } return rowsInserted, nil } func (r *Repository) FindByFilters(ctx context.Context, filter *Filter) ([]*entity.Order, error) { ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() query := `SELECT order_id, customer_id, amount, created_at FROM orders WHERE created_at >= $1 AND created_at <= $2 LIMIT $3` rows, err := r.pool.Query(ctx, query, filter.StartDate, filter.EndDate, filter.Limit) if err != nil { return nil, fmt.Errorf("query: %w", err) } defer rows.Close() var orders []*entity.Order for rows.Next() { var o entity.Order if err := rows.Scan(&o.OrderID, &o.CustomerID, &o.Amount, &o.CreatedAt); err != nil { return nil, fmt.Errorf("scan: %w", err) } orders = append(orders, &o) } return orders, rows.Err() }