2023-01-05 12:45:09 +01:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2023-03-08 15:30:40 +01:00
|
|
|
"os"
|
|
|
|
"time"
|
2023-01-05 12:45:09 +01:00
|
|
|
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
2023-03-08 15:30:40 +01:00
|
|
|
"github.com/jackc/tern/v2/migrate"
|
2023-01-05 12:45:09 +01:00
|
|
|
"github.com/knadh/goyesql/v2"
|
|
|
|
"github.com/zerodha/logf"
|
|
|
|
)
|
|
|
|
|
2023-03-08 15:30:40 +01:00
|
|
|
const (
|
|
|
|
schemaTable = "schema_version"
|
|
|
|
)
|
2023-01-05 12:45:09 +01:00
|
|
|
|
2023-03-08 15:30:40 +01:00
|
|
|
type (
|
|
|
|
queries struct {
|
|
|
|
CommitBlock string `query:"commit-block"`
|
|
|
|
GetMissingBlocks string `query:"get-missing-blocks"`
|
|
|
|
GetSearchBounds string `query:"get-search-bounds"`
|
|
|
|
InitSyncerMeta string `query:"init-syncer-meta"`
|
|
|
|
SetSearchLowerBound string `query:"set-search-lower-bound"`
|
|
|
|
}
|
|
|
|
|
|
|
|
PostgresStoreOpts struct {
|
|
|
|
DSN string
|
|
|
|
MigrationsFolderPath string
|
|
|
|
InitialLowerBound uint64
|
|
|
|
Logg logf.Logger
|
|
|
|
Queries goyesql.Queries
|
|
|
|
}
|
|
|
|
)
|
2023-01-05 12:45:09 +01:00
|
|
|
|
|
|
|
type PostgresStore struct {
|
|
|
|
logg logf.Logger
|
|
|
|
pool *pgxpool.Pool
|
|
|
|
queries queries
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewPostgresStore(o PostgresStoreOpts) (Store[pgx.Rows], error) {
|
|
|
|
postgresStore := &PostgresStore{
|
|
|
|
logg: o.Logg,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := goyesql.ScanToStruct(&postgresStore.queries, o.Queries, nil); err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to scan queries %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
parsedConfig, err := pgxpool.ParseConfig(o.DSN)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-03-08 15:30:40 +01:00
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
dbPool, err := pgxpool.NewWithConfig(ctx, parsedConfig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, err := dbPool.Acquire(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer conn.Release()
|
|
|
|
|
|
|
|
migrator, err := migrate.NewMigrator(ctx, conn.Conn(), schemaTable)
|
2023-01-05 12:45:09 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-03-08 15:30:40 +01:00
|
|
|
if err := migrator.LoadMigrations(os.DirFS(o.MigrationsFolderPath)); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := migrator.Migrate(ctx); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = dbPool.Exec(ctx, postgresStore.queries.InitSyncerMeta, o.InitialLowerBound)
|
2023-01-05 12:45:09 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
postgresStore.pool = dbPool
|
|
|
|
|
|
|
|
return postgresStore, nil
|
|
|
|
}
|
|
|
|
|
2023-01-11 09:13:59 +01:00
|
|
|
func (s *PostgresStore) GetSearchBounds(ctx context.Context, batchSize uint64, headCursor uint64, headBlockLag uint64) (uint64, uint64, error) {
|
2023-01-05 12:45:09 +01:00
|
|
|
var (
|
|
|
|
lowerBound uint64
|
|
|
|
upperBound uint64
|
|
|
|
)
|
|
|
|
|
|
|
|
if err := s.pool.QueryRow(
|
2023-01-11 09:13:59 +01:00
|
|
|
ctx,
|
2023-01-05 12:45:09 +01:00
|
|
|
s.queries.GetSearchBounds,
|
|
|
|
batchSize,
|
|
|
|
headCursor,
|
|
|
|
headBlockLag,
|
|
|
|
).Scan(&lowerBound, &upperBound); err != nil {
|
|
|
|
s.logg.Error("pgx error", "error", err)
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return lowerBound, upperBound, nil
|
|
|
|
}
|
|
|
|
|
2023-01-11 09:13:59 +01:00
|
|
|
func (s *PostgresStore) GetMissingBlocks(ctx context.Context, lowerBound uint64, upperBound uint64) (pgx.Rows, error) {
|
|
|
|
rows, err := s.pool.Query(ctx, s.queries.GetMissingBlocks, lowerBound, upperBound)
|
2023-01-05 12:45:09 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return rows, nil
|
|
|
|
}
|
|
|
|
|
2023-01-11 09:13:59 +01:00
|
|
|
func (s *PostgresStore) SetSearchLowerBound(ctx context.Context, newLowerBound uint64) error {
|
|
|
|
_, err := s.pool.Exec(ctx, s.queries.SetSearchLowerBound, newLowerBound)
|
2023-01-05 12:45:09 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-01-11 09:13:59 +01:00
|
|
|
func (s *PostgresStore) CommitBlock(ctx context.Context, block uint64) error {
|
|
|
|
_, err := s.pool.Exec(ctx, s.queries.CommitBlock, block)
|
2023-01-05 12:45:09 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|