100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"cryptoHermes/internal/entity"
|
|
)
|
|
|
|
const coinglassSource = "coinglass"
|
|
|
|
type CoinglassLiqHeatMapRepo struct {
|
|
pool pgxPool
|
|
}
|
|
|
|
func NewCoinglassLiqHeatMapRepo(pool *pgxpool.Pool) *CoinglassLiqHeatMapRepo {
|
|
return &CoinglassLiqHeatMapRepo{pool: pool}
|
|
}
|
|
|
|
const cgLiqHeatMapUpsertSQL = `
|
|
INSERT INTO coinglass_liq_heatmap (
|
|
source, symbol, interval, timestamp,
|
|
price_min, price_max, raw_grid,
|
|
updated_at
|
|
) VALUES (
|
|
$1, $2, $3, $4,
|
|
NULLIF($5, '')::NUMERIC, NULLIF($6, '')::NUMERIC, $7::JSONB,
|
|
now()
|
|
)
|
|
ON CONFLICT (source, symbol, interval, timestamp) DO UPDATE SET
|
|
price_min = EXCLUDED.price_min,
|
|
price_max = EXCLUDED.price_max,
|
|
raw_grid = EXCLUDED.raw_grid,
|
|
updated_at = now()
|
|
`
|
|
|
|
func (r *CoinglassLiqHeatMapRepo) UpsertMany(ctx context.Context, items []entity.CGLiqHeatMap) error {
|
|
if len(items) == 0 {
|
|
return nil
|
|
}
|
|
tx, err := r.pool.Begin(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("begin: %w", err)
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
|
|
for _, item := range items {
|
|
if item.Symbol == "" || item.Interval == "" || item.Timestamp == 0 || !json.Valid(item.RawGrid) {
|
|
continue
|
|
}
|
|
if _, err := tx.Exec(ctx, cgLiqHeatMapUpsertSQL,
|
|
coinglassSource, item.Symbol, item.Interval, item.Timestamp,
|
|
item.PriceMin, item.PriceMax, string(item.RawGrid),
|
|
); err != nil {
|
|
return fmt.Errorf("upsert coinglass liq heatmap %s/%s@%d: %w", item.Symbol, item.Interval, item.Timestamp, err)
|
|
}
|
|
}
|
|
return tx.Commit(ctx)
|
|
}
|
|
|
|
const cgLiqHeatMapFindSQL = `
|
|
SELECT symbol, interval, timestamp,
|
|
COALESCE(price_min::text, ''), COALESCE(price_max::text, ''), raw_grid::text
|
|
FROM coinglass_liq_heatmap
|
|
WHERE source = $1 AND symbol = $2 AND interval = $3
|
|
ORDER BY timestamp DESC
|
|
LIMIT $4
|
|
`
|
|
|
|
func (r *CoinglassLiqHeatMapRepo) FindRecent(ctx context.Context, symbol, interval string, limit int) ([]entity.CGLiqHeatMap, error) {
|
|
if limit <= 0 {
|
|
limit = 288
|
|
}
|
|
rows, err := r.pool.Query(ctx, cgLiqHeatMapFindSQL, coinglassSource, symbol, interval, limit)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
out := make([]entity.CGLiqHeatMap, 0, limit)
|
|
for rows.Next() {
|
|
var (
|
|
item entity.CGLiqHeatMap
|
|
raw string
|
|
)
|
|
if err := rows.Scan(&item.Symbol, &item.Interval, &item.Timestamp, &item.PriceMin, &item.PriceMax, &raw); err != nil {
|
|
return nil, fmt.Errorf("scan: %w", err)
|
|
}
|
|
item.RawGrid = json.RawMessage(raw)
|
|
out = append(out, item)
|
|
}
|
|
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()
|
|
}
|