package postgres import ( "context" "database/sql" "fmt" "github.com/jackc/pgx/v5/pgxpool" "cryptoHermes/internal/entity" ) type FundingRepo struct { pool pgxPool } func NewFundingRepo(pool *pgxpool.Pool) *FundingRepo { return &FundingRepo{pool: pool} } const fundingUpsertSQL = ` INSERT INTO funding_rates (source, symbol, funding_time, funding_rate, mark_price) VALUES ($1, $2, $3, $4, NULLIF($5, '')::NUMERIC) ON CONFLICT (source, symbol, funding_time) DO UPDATE SET funding_rate = EXCLUDED.funding_rate, mark_price = EXCLUDED.mark_price ` func (r *FundingRepo) UpsertMany(ctx context.Context, items []entity.FundingRate) error { if len(items) == 0 { return nil } tx, err := r.pool.Begin(ctx) if err != nil { return err } defer tx.Rollback(ctx) for _, f := range items { if f.FundingRate == "" || f.FundingTime == 0 { continue } if _, err := tx.Exec(ctx, fundingUpsertSQL, f.Source, f.Symbol, f.FundingTime, f.FundingRate, f.MarkPrice, ); err != nil { return fmt.Errorf("upsert funding %s@%d: %w", f.Symbol, f.FundingTime, err) } } return tx.Commit(ctx) } const fundingFindSQL = ` SELECT source, symbol, funding_time, funding_rate::text, COALESCE(mark_price::text, '') FROM funding_rates WHERE symbol = $1 ORDER BY funding_time DESC LIMIT $2 ` func (r *FundingRepo) FindRecent(ctx context.Context, symbol string, limit int) ([]entity.FundingRate, error) { if limit <= 0 { limit = 100 } rows, err := r.pool.Query(ctx, fundingFindSQL, symbol, limit) if err != nil { return nil, err } defer rows.Close() out := make([]entity.FundingRate, 0, limit) for rows.Next() { var f entity.FundingRate var mark sql.NullString if err := rows.Scan(&f.Source, &f.Symbol, &f.FundingTime, &f.FundingRate, &mark); err != nil { return nil, err } if mark.Valid { f.MarkPrice = mark.String } out = append(out, f) } for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 { out[i], out[j] = out[j], out[i] } return out, rows.Err() }