Documentation
¶
Overview ¶
Package sqlstore keeps CronWatch's jobs, runs and state in the app's own database through database/sql: SQLite, Postgres or MySQL (and MariaDB). The app brings its driver and its *sql.DB; this package imports none, so the cronwatch module needs no driver at all.
db, _ := sql.Open("sqlite", "file:data/app.db") // modernc.org/sqlite
db, _ := sql.Open("pgx", os.Getenv("DATABASE_URL")) // github.com/jackc/pgx/v5/stdlib
db, _ := sql.Open("mysql", "app:pw@tcp(db:3306)/app") // github.com/go-sql-driver/mysql
store, err := sqlstore.New(db, sqlstore.Postgres)
cw, err := cronwatch.New(cronwatch.WithStore(store))
The tables are the SDK's (stores/sql.ts): the same names, columns and statements, and the SDK's JSON in the JSON columns byte for byte, so a Go process shares a database with a Node, Ruby, Python or PHP one.
Index ¶
- Constants
- type Dialect
- type Option
- type Store
- func (s *Store) Close() error
- func (s *Store) CompareAndSetState(ctx context.Context, st cronwatch.JobState, expected int64) (bool, error)
- func (s *Store) DeleteJob(ctx context.Context, name string) error
- func (s *Store) DeleteRunIf(ctx context.Context, id, job string, status cronwatch.RunStatus) (bool, error)
- func (s *Store) Dialect() Dialect
- func (s *Store) GetJob(ctx context.Context, name string) (*cronwatch.StoredJob, error)
- func (s *Store) GetRun(ctx context.Context, id string) (*cronwatch.Run, error)
- func (s *Store) GetState(ctx context.Context, job string) (*cronwatch.JobState, error)
- func (s *Store) Init(ctx context.Context) error
- func (s *Store) InsertRun(ctx context.Context, r cronwatch.Run) error
- func (s *Store) LastRun(ctx context.Context, job string) (*cronwatch.Run, error)
- func (s *Store) ListJobs(ctx context.Context) ([]cronwatch.StoredJob, error)
- func (s *Store) ListRuns(ctx context.Context, job string, limit int) ([]cronwatch.Run, error)
- func (s *Store) Prune(ctx context.Context, before int64) (int, error)
- func (s *Store) RunningRuns(ctx context.Context) ([]cronwatch.Run, error)
- func (s *Store) SetState(ctx context.Context, st cronwatch.JobState) error
- func (s *Store) TablePrefix() string
- func (s *Store) UpdateRun(ctx context.Context, r cronwatch.Run) error
- func (s *Store) UpdateRunIf(ctx context.Context, r cronwatch.Run, from []cronwatch.RunStatus) (bool, error)
- func (s *Store) UpsertJob(ctx context.Context, def cronwatch.Definition, now int64) error
Constants ¶
const DefaultPrefix = "cronwatch_"
DefaultPrefix starts every table name unless Prefix says otherwise.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a cronwatch.Store over a *sql.DB. Safe for use by many goroutines at once.
On SQLite it holds one connection of the pool (the SDK's store has one connection too): an in-memory database is one per connection, and one writer at a time is what SQLite allows anyway. That connection is put in WAL mode (with the SDK's retry of a busy database while switching), with busy_timeout 5000 and synchronous NORMAL. On Postgres and MySQL it uses the pool, each statement on its own (autocommit), so its writes never join a transaction the app has open. So a pool limited to one connection (db.SetMaxOpenConns(1)) leaves the app none on SQLite, and waits on an app's open transaction on the others: give it room for the store too.
The tests are in the sqltest module beside this package (SQLite, Postgres, MySQL and MariaDB, and a file shared with the SDK in Node), kept apart so the drivers never become the cronwatch module's requirements.
func (*Store) Close ¶
Close gives SQLite's connection back to the pool. The *sql.DB is the app's, and stays open.
func (*Store) CompareAndSetState ¶
func (*Store) DeleteRunIf ¶
func (s *Store) DeleteRunIf(ctx context.Context, id, job string, status cronwatch.RunStatus) (bool, error)
DeleteRunIf deletes a run only while it is of job and in status, in one statement, and says whether it did. A DELETE counts the rows it matched on every dialect, MySQL included.
func (*Store) Init ¶
Init makes the tables. On Postgres many processes starting at once would race CREATE TABLE IF NOT EXISTS, which Postgres can reject with a unique violation on pg_type, so they take turns under an advisory lock per prefix. MySQL commits CREATE TABLE at once, so call Init when nothing is open (it runs at the client's first use).
func (*Store) RunningRuns ¶
func (*Store) TablePrefix ¶
TablePrefix is the prefix of the store's tables.