diff options
-rw-r--r-- | cmd/start.go | 8 | ||||
-rw-r--r-- | internal/crons/main.go | 88 | ||||
-rw-r--r-- | internal/database/migrations/001_init.down.sql | 2 | ||||
-rw-r--r-- | internal/database/migrations/001_init.up.sql | 6 | ||||
-rw-r--r-- | internal/database/migrations/002_defaults.down.sql | 5 | ||||
-rw-r--r-- | internal/database/migrations/002_defaults.up.sql | 11 | ||||
-rw-r--r-- | internal/database/repos/defaults.go | 25 | ||||
-rw-r--r-- | internal/database/repos/main.go | 1 | ||||
-rw-r--r-- | internal/handlers/main.go | 6 | ||||
-rw-r--r-- | internal/server/main.go | 7 |
10 files changed, 146 insertions, 13 deletions
diff --git a/cmd/start.go b/cmd/start.go index fa00786..f6a2267 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -2,8 +2,11 @@ package cmd import ( "apjournal/config" + "apjournal/internal/crons" + "apjournal/internal/database/repos" database "apjournal/internal/database/sql" "apjournal/internal/server" + "context" "os" "log/slog" @@ -34,7 +37,10 @@ var startCmd = &cobra.Command{ log.Error("failed to connect to db", "error", err) return } - srv := server.NewServer(cfg, log, db.Conn) + repo := repos.NewProvider(db.Conn) + srv := server.NewServer(cfg, log, repo) + cron := crons.NewCron(context.Background(), repo) + cron.StartCronJobs() // listen for new messages srv.Listen() }, diff --git a/internal/crons/main.go b/internal/crons/main.go new file mode 100644 index 0000000..9655522 --- /dev/null +++ b/internal/crons/main.go @@ -0,0 +1,88 @@ +package crons + +import ( + "apjournal/internal/database/repos" + "context" + "os" + "strconv" + "time" + + "log/slog" +) + +var ( + log = slog.New(slog.NewJSONHandler(os.Stdout, + &slog.HandlerOptions{Level: slog.LevelDebug})) +) + +const ( + CheckBurnTimeKey = "check_burn_time_key" +) + +type Cron struct { + ctx context.Context + repo repos.FullRepo +} + +func NewCron( + ctx context.Context, repo repos.FullRepo, +) *Cron { + return &Cron{ + ctx: ctx, + repo: repo, + } +} + +func (c *Cron) UpdateDefaultsFloat64(defaults map[string]float64) (map[string]float64, error) { + dm, err := c.repo.DBGetDefaultsMap() + if err != nil { + return defaults, err + } + for k, _ := range defaults { + sosValue, ok := dm[k] + if ok { + value, err := strconv.ParseFloat(sosValue, 64) + if err != nil { + // log err + continue + } + defaults[k] = value + } + } + return defaults, nil +} + +func (c *Cron) StartCronJobs() { + // check system_options for time + defaults := map[string]float64{ + CheckBurnTimeKey: 5.0, + } + defaults, err := c.UpdateDefaultsFloat64(defaults) + if err != nil { + panic(err) + } + go c.BurnTicker( + time.Minute * time.Duration(defaults[CheckBurnTimeKey])) +} + +func (c *Cron) BurnTicker(interval time.Duration) { + funcname := "BurnTicker" + ticker := time.NewTicker(interval) + for { + select { + case <-c.ctx.Done(): + log.Info("cron stopped by ctx.Done", "func", funcname) + return + case <-ticker.C: + c.BurnTimeUpdate() + } + } +} + +func (c *Cron) BurnTimeUpdate() { + // funcname := "BurnTimeUpdate" + // get all user scores + // if burn time < now + // halv the score + // move the burn time to 24h from now (using same hours, minutes, seconds) +} diff --git a/internal/database/migrations/001_init.down.sql b/internal/database/migrations/001_init.down.sql index 1b8680f..41cc5c9 100644 --- a/internal/database/migrations/001_init.down.sql +++ b/internal/database/migrations/001_init.down.sql @@ -1,4 +1,4 @@ -BEGIN; +BEGIN TRANSACTION; DROP SCHEMA public CASCADE; CREATE SCHEMA public; COMMIT; diff --git a/internal/database/migrations/001_init.up.sql b/internal/database/migrations/001_init.up.sql index f7e41c1..141a045 100644 --- a/internal/database/migrations/001_init.up.sql +++ b/internal/database/migrations/001_init.up.sql @@ -1,5 +1,5 @@ -BEGIN; -CREATE TABLE user_score ( +BEGIN TRANSACTION; +CREATE TABLE IF NOT EXISTS user_score ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, @@ -8,7 +8,7 @@ CREATE TABLE user_score ( created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); -CREATE TABLE action ( +CREATE TABLE IF NOT EXISTS action( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, magnitude SMALLINT NOT NULL DEFAULT 1, diff --git a/internal/database/migrations/002_defaults.down.sql b/internal/database/migrations/002_defaults.down.sql new file mode 100644 index 0000000..3e38fa2 --- /dev/null +++ b/internal/database/migrations/002_defaults.down.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +DROP TABLE defaults; + +COMMIT; diff --git a/internal/database/migrations/002_defaults.up.sql b/internal/database/migrations/002_defaults.up.sql new file mode 100644 index 0000000..4bf42b7 --- /dev/null +++ b/internal/database/migrations/002_defaults.up.sql @@ -0,0 +1,11 @@ +BEGIN TRANSACTION; + +CREATE TABLE IF NOT EXISTS defaults ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + key TEXT UNIQUE NOT NULL, + value TEXT NOT NULL, + description TEXT NOT NULL DEFAULT '', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +COMMIT; diff --git a/internal/database/repos/defaults.go b/internal/database/repos/defaults.go new file mode 100644 index 0000000..e0b5e52 --- /dev/null +++ b/internal/database/repos/defaults.go @@ -0,0 +1,25 @@ +package repos + +type DefaultsRepo interface { + DBGetDefaultsMap() (map[string]string, error) +} + +func (p *Provider) DBGetDefaultsMap() (map[string]string, error) { + rows, err := p.db.Queryx(`SELECT key, value + FROM defaults; + `) + if err != nil { + return nil, err + } + res := make(map[string]string) + for rows.Next() { + keyval, err := rows.SliceScan() + if err != nil { + return nil, err + } + key := keyval[0].(string) + value := keyval[1].(string) + res[key] = value + } + return res, nil +} diff --git a/internal/database/repos/main.go b/internal/database/repos/main.go index 25eeec4..72860dd 100644 --- a/internal/database/repos/main.go +++ b/internal/database/repos/main.go @@ -7,6 +7,7 @@ import ( type FullRepo interface { ActionRepo UserScoreRepo + DefaultsRepo } type Provider struct { diff --git a/internal/handlers/main.go b/internal/handlers/main.go index 3bb194c..5546d9a 100644 --- a/internal/handlers/main.go +++ b/internal/handlers/main.go @@ -11,8 +11,6 @@ import ( "os" "strconv" "time" - - "github.com/jmoiron/sqlx" ) var defUS = models.UserScore{} @@ -27,7 +25,7 @@ type Handlers struct { // NewHandlers constructor func NewHandlers( - cfg config.Config, l *slog.Logger, conn *sqlx.DB, + cfg config.Config, l *slog.Logger, repo repos.FullRepo, ) *Handlers { if l == nil { l = slog.New(slog.NewJSONHandler(os.Stdout, nil)) @@ -35,7 +33,7 @@ func NewHandlers( h := &Handlers{ cfg: cfg, log: l, - repo: repos.NewProvider(conn), + repo: repo, mc: cache.MemCache, } return h diff --git a/internal/server/main.go b/internal/server/main.go index 95d0369..1ab6cc2 100644 --- a/internal/server/main.go +++ b/internal/server/main.go @@ -2,6 +2,7 @@ package server import ( "apjournal/config" + "apjournal/internal/database/repos" "apjournal/internal/handlers" "context" @@ -9,8 +10,6 @@ import ( "os" "os/signal" "syscall" - - "github.com/jmoiron/sqlx" ) // Server interface @@ -41,9 +40,9 @@ func (srv *server) stopOnSignal(close context.CancelFunc) { os.Exit(0) } -func NewServer(cfg config.Config, log *slog.Logger, conn *sqlx.DB) Server { +func NewServer(cfg config.Config, log *slog.Logger, repo repos.FullRepo) Server { ctx, close := context.WithCancel(context.Background()) - actions := handlers.NewHandlers(cfg, log, conn) + actions := handlers.NewHandlers(cfg, log, repo) return &server{ config: cfg, actions: actions, |