postgresql & migrations
This commit is contained in:
parent
ae096d4820
commit
7f6cd8e557
15 changed files with 254 additions and 27 deletions
|
|
@ -8,8 +8,9 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
Logger Logger `yaml:"logger"`
|
||||
Providers struct {
|
||||
Logger Logger `yaml:"logger"`
|
||||
Postgresql Postgresql `yaml:"postgresql"`
|
||||
Providers struct {
|
||||
Bybit Bybit `yaml:"bybit"`
|
||||
} `yaml:"providers"`
|
||||
}
|
||||
|
|
@ -24,6 +25,13 @@ type Bybit struct {
|
|||
BaseURL string `yaml:"base_url" env-default:"https://api.bybit.com"` // bybit api url
|
||||
}
|
||||
|
||||
type Postgresql struct {
|
||||
Address string `yaml:"address" env-required:"true"`
|
||||
User string `yaml:"user" env-required:"true"`
|
||||
Password string `yaml:"password" env-required:"true"`
|
||||
DBName string `yaml:"db_name" env-required:"true"`
|
||||
}
|
||||
|
||||
// MustLoad returns config or panic.
|
||||
func MustLoad() *Config {
|
||||
configPath := os.Getenv("CONFIG_PATH")
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"crypto_alert_bot/internal/config"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/config"
|
||||
|
||||
prettyLogger "github.com/charmbracelet/log"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@ package bybit
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto_alert_bot/internal/config"
|
||||
"crypto_alert_bot/internal/entities"
|
||||
"crypto_alert_bot/internal/provider"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/config"
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/entities"
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/provider"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ package provider
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto_alert_bot/internal/entities"
|
||||
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/entities"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
|
|
|
|||
1
internal/repository/postgresql/alert.go
Normal file
1
internal/repository/postgresql/alert.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package postgresql
|
||||
1
internal/repository/postgresql/instrument.go
Normal file
1
internal/repository/postgresql/instrument.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package postgresql
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
drop table if exists alert;
|
||||
drop table if exists instrument;
|
||||
drop table if exists currency;
|
||||
drop table if exists users;
|
||||
32
internal/repository/postgresql/migrations/000001_init.up.sql
Normal file
32
internal/repository/postgresql/migrations/000001_init.up.sql
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
create table if not exists users (
|
||||
id uuid primary key not null default gen_random_uuid(),
|
||||
telegram_id bigint not null UNIQUE
|
||||
);
|
||||
|
||||
create table if not exists currency (
|
||||
id serial primary key not null,
|
||||
symbol text not null UNIQUE
|
||||
-- decimals integer not null
|
||||
);
|
||||
|
||||
create table if not exists instrument (
|
||||
id uuid primary key not null default gen_random_uuid(),
|
||||
base_currency_id integer references currency(id) not null,
|
||||
quoted_currency_id integer references currency(id) not null,
|
||||
CHECK (base_currency_id <> quoted_currency_id),
|
||||
UNIQUE (base_currency_id, quoted_currency_id)
|
||||
);
|
||||
|
||||
create table if not exists alert (
|
||||
id uuid primary key not null default gen_random_uuid(),
|
||||
instrument_id uuid references instrument(id) not null,
|
||||
price text not null,
|
||||
active bool not null default true
|
||||
);
|
||||
|
||||
insert into currency(symbol) values ('USDT'), ('BTC'), ('ETH'), ('SOL');
|
||||
|
||||
insert into instrument (base_currency_id, quoted_currency_id) values
|
||||
((select id from currency where symbol = 'BTC'), (select id from currency where symbol = 'USDT')),
|
||||
((select id from currency where symbol = 'ETH'), (select id from currency where symbol = 'USDT')),
|
||||
((select id from currency where symbol = 'SOL'), (select id from currency where symbol = 'USDT'));
|
||||
8
internal/repository/postgresql/migrations/embed.go
Normal file
8
internal/repository/postgresql/migrations/embed.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"embed"
|
||||
)
|
||||
|
||||
//go:embed *.sql
|
||||
var Folder embed.FS
|
||||
76
internal/repository/postgresql/postgresql.go
Normal file
76
internal/repository/postgresql/postgresql.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package postgresql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/config"
|
||||
"gitea.computernetthings.ru/yash/crypto_alert_bot/internal/repository/postgresql/migrations"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
pgx "github.com/golang-migrate/migrate/v4/database/pgx/v5"
|
||||
"github.com/golang-migrate/migrate/v4/source/iofs"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
)
|
||||
|
||||
type Postgresql struct {
|
||||
db *pgxpool.Pool
|
||||
}
|
||||
|
||||
func New(ctx context.Context, log *slog.Logger, cfg *config.Postgresql) (*Postgresql, error) {
|
||||
pool, err := pgxpool.New(ctx, fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", cfg.User, cfg.Password, cfg.Address, cfg.DBName))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to postgres: %w", err)
|
||||
}
|
||||
|
||||
if err = pool.Ping(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// apply migrations automatically
|
||||
if err = applyMigrations(cfg, log); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply migrations: %w", err)
|
||||
}
|
||||
|
||||
return &Postgresql{db: pool}, nil
|
||||
}
|
||||
|
||||
func applyMigrations(cfg *config.Postgresql, log *slog.Logger) error {
|
||||
dsn := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", cfg.User, cfg.Password, cfg.Address, cfg.DBName)
|
||||
|
||||
sqlDB, err := sql.Open("pgx", dsn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open sql db for migrations: %w", err)
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
|
||||
driver, err := pgx.WithInstance(sqlDB, &pgx.Config{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create pgx driver: %w", err)
|
||||
}
|
||||
|
||||
d, err := iofs.New(migrations.Folder, ".")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create iofs source: %w", err)
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithInstance("iofs", d, "postgres", driver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create postgresql db migration: %w", err)
|
||||
}
|
||||
|
||||
if err := m.Up(); err != nil {
|
||||
if errors.Is(err, migrate.ErrNoChange) {
|
||||
log.Info("no migrations to process")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
log.Info("migrations processed")
|
||||
return nil
|
||||
}
|
||||
1
internal/repository/postgresql/user.go
Normal file
1
internal/repository/postgresql/user.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package postgresql
|
||||
Loading…
Add table
Add a link
Reference in a new issue