ergon_cron (ergon v0.5.0)

View Source

Scheduling SQL with pg_cron, guarded so the same code runs where it is absent.

pg_cron can be CREATE EXTENSION'd in exactly one database per cluster, named by cron.database_name in postgresql.conf. The development database here has it, the test database deliberately does not, and host clusters vary. Every helper is therefore a guarded no-op when the extension is missing, which is what lets one migration run unchanged against both.

Idempotent through cron.schedule's upsert-by-name, so scheduling the same job twice updates it in place rather than creating a duplicate. That is exactly the contract a re-runnable migration needs, and it is why priv/migrations/cron/ scripts are class always.

On one cron job per thing

ergon_migration:partitioned_table_sql/2 schedules one weekly job per partitioned table, and that is fine at any table count.

Worth stating because Phase 5 went the other way for pgmq, consolidating a per-queue tick into one. The difference is not the number of jobs, it is what they do: a per-second tick that calls pg_notify is a notifying transaction per queue per second, and every one of those takes the global notification-queue lock at commit. A weekly job that creates partitions takes no such lock and runs thousands of times less often. Do not consolidate this one by analogy.

Summary

Functions

Schedule SQL on the cron Spec, named Name.

The statement schedule/3 runs, as literal SQL, for embedding in a migration.

Every currently scheduled job name and its schedule.

Unschedule the job named Name. A no-op if it or pg_cron is absent.

The statement unschedule/1 runs, as literal SQL.

Types

db_error()

-type db_error() ::
          empty_result | would_create_cycle |
          {job_not_found, ergon_job:job_id()} |
          {pgo_error, map()} |
          term().

Functions

schedule(Name, Spec, SQL)

-spec schedule(binary(), binary(), iodata()) -> ok | {error, db_error()}.

Schedule SQL on the cron Spec, named Name.

Spec is standard five-field cron syntax, or one of pg_cron's extensions such as @weekly or 1 second. A no-op where pg_cron is not installed.

schedule_sql(Name, Spec, SQL)

-spec schedule_sql(binary(), binary(), iodata()) -> iodata().

The statement schedule/3 runs, as literal SQL, for embedding in a migration.

scheduled()

-spec scheduled() -> {ok, [{binary(), binary()}]} | {error, db_error()}.

Every currently scheduled job name and its schedule.

unschedule(Name)

-spec unschedule(binary()) -> ok | {error, db_error()}.

Unschedule the job named Name. A no-op if it or pg_cron is absent.

unschedule_sql(Name)

-spec unschedule_sql(binary()) -> iodata().

The statement unschedule/1 runs, as literal SQL.