104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
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()
|
|
}
|