package models import ( "database/sql" "time" ) type Schedule struct { ID int64 `db:"id" json:"id"` SyncPairID int64 `db:"sync_pair_id" json:"sync_pair_id"` CronExpr string `db:"cron_expr" json:"cron_expr"` NextRunAt *time.Time `db:"next_run_at" json:"next_run_at"` Enabled bool `db:"enabled" json:"enabled"` CreatedAt time.Time `db:"created_at" json:"created_at"` } type ScheduleRepository struct { db *sql.DB } func NewScheduleRepository(db *sql.DB) *ScheduleRepository { return &ScheduleRepository{db: db} } func (r *ScheduleRepository) Create(s *Schedule) (int64, error) { res, err := r.db.Exec(` INSERT INTO schedules (sync_pair_id, cron_expr, next_run_at, enabled) VALUES (?, ?, ?, ?)`, s.SyncPairID, s.CronExpr, s.NextRunAt, boolToInt(s.Enabled), ) if err != nil { return 0, err } return res.LastInsertId() } func (r *ScheduleRepository) GetAll() ([]Schedule, error) { rows, err := r.db.Query(` SELECT id, sync_pair_id, cron_expr, next_run_at, enabled, created_at FROM schedules ORDER BY id`) if err != nil { return nil, err } defer rows.Close() var schedules []Schedule for rows.Next() { var s Schedule var nextRun sql.NullTime if err := rows.Scan(&s.ID, &s.SyncPairID, &s.CronExpr, &nextRun, &s.Enabled, &s.CreatedAt); err != nil { return nil, err } if nextRun.Valid { s.NextRunAt = &nextRun.Time } s.Enabled = intToBool(intToInt(s.Enabled)) schedules = append(schedules, s) } return schedules, rows.Err() } func (r *ScheduleRepository) GetByID(id int64) (*Schedule, error) { var s Schedule var nextRun sql.NullTime err := r.db.QueryRow(` SELECT id, sync_pair_id, cron_expr, next_run_at, enabled, created_at FROM schedules WHERE id = ?`, id).Scan( &s.ID, &s.SyncPairID, &s.CronExpr, &nextRun, &s.Enabled, &s.CreatedAt) if err != nil { return nil, err } if nextRun.Valid { s.NextRunAt = &nextRun.Time } s.Enabled = intToBool(intToInt(s.Enabled)) return &s, nil } func (r *ScheduleRepository) Update(s *Schedule) error { _, err := r.db.Exec(` UPDATE schedules SET sync_pair_id=?, cron_expr=?, next_run_at=?, enabled=? WHERE id=?`, s.SyncPairID, s.CronExpr, s.NextRunAt, boolToInt(s.Enabled), s.ID, ) return err } func (r *ScheduleRepository) Delete(id int64) error { _, err := r.db.Exec("DELETE FROM schedules WHERE id = ?", id) return err } func (r *ScheduleRepository) GetEnabledDue(before time.Time) ([]Schedule, error) { rows, err := r.db.Query(` SELECT id, sync_pair_id, cron_expr, next_run_at, enabled, created_at FROM schedules WHERE enabled = 1 AND next_run_at IS NOT NULL AND next_run_at <= ? ORDER BY next_run_at`, before) if err != nil { return nil, err } defer rows.Close() var schedules []Schedule for rows.Next() { var s Schedule var nextRun sql.NullTime if err := rows.Scan(&s.ID, &s.SyncPairID, &s.CronExpr, &nextRun, &s.Enabled, &s.CreatedAt); err != nil { return nil, err } if nextRun.Valid { s.NextRunAt = &nextRun.Time } s.Enabled = true schedules = append(schedules, s) } return schedules, rows.Err() } func (r *ScheduleRepository) UpdateNextRun(id int64, nextRun time.Time) error { _, err := r.db.Exec("UPDATE schedules SET next_run_at = ? WHERE id = ?", nextRun, id) return err }