Packages
PostgreSQL-native background job and workflow processing, built on PostgreSQL 19 temporal tables, SQL/PGQ property graphs, pgmq durable queues, and pg_cron scheduling.
Current section
Files
Jump to
Current section
Files
rebar.config
%% == Compiler & other options ==
%% These opts are what consumers compile ergon with: rebar3 builds a hex
%% dependency using the dependency's own erl_opts, unfiltered. So anything
%% strict or noisy here lands in someone else's build, which is why
%% `warnings_as_errors`, `verbose` and `report` live in the `check` profile
%% instead. A future OTP that adds one new deprecation warning would otherwise
%% turn every downstream `rebar3 compile` into a hard failure on a release we
%% never touched.
{erl_opts, [
warn_unused_import,
warn_export_vars,
debug_info
]}.
%% OTP 28 is a floor, not a preference. The source uses strict generators
%% (`<:-`) and EEP-69 nominal types, both 28-only, on top of OTP 27's sigils,
%% `maybe`, and `json`. flake.nix pins the same version.
{minimum_otp_vsn, "28"}.
%% == Dependencies and Plugins ==
{plugins, [
{rebar3_ex_doc, "v0.3.0"},
{rebar3_nix, ".*", {git, "https://github.com/erlang-nix/rebar3_nix.git", {tag, "v0.1.1"}}},
{covertool, "v2.0.4"}
]}.
%% pgo is the runtime driver (socket-direct, built-in pool, pgo_notifications).
%% epgsql arrives transitively through migraterl and is used at boot only, by
%% ergon_migrate: migraterl's API takes an epgsql:connection(), not a pgo pool.
%% worker_pool backs the per-queue handler executors. It is not used for routing:
%% FOR UPDATE SKIP LOCKED is the dispatcher, so none of wpool's worker-selection
%% strategies apply. What it provides is a supervised, bounded set of executors
%% plus overrun_warning for handlers that run long.
%% backoff is already in the tree as a transitive dependency of pgo; naming it
%% here only promotes it to a direct one, at the version already locked. It backs
%% the LISTEN resubscribe loops in ergon_job_notifier and ergon_pgmq_consumer.
{deps, [
{pgo, "0.20.0"},
{migraterl, "0.5.0"},
{worker_pool, "6.5.3"},
{backoff, "1.1.6"}
]}.
{ex_doc, [
{source_url, <<"https://github.com/byzantine-systems/ergon">>},
{main, "readme"},
%% Both source files are named README.md, so pin their output names rather
%% than letting ExDoc disambiguate them as readme-1.html/readme-2.html.
{extras, [
{"README.md", #{filename => "readme", title => "Overview"}},
{"examples/README.md", #{filename => "examples", title => "Examples"}},
"examples/getting-started.md",
"examples/migrations.md",
"examples/operations.md",
"examples/pgmq.md",
"examples/scheduling.md",
"examples/unique-jobs.md",
"examples/workflows.md"
]},
%% This empty seed is load-bearing, not leftover. rebar3_ex_doc applies
%% `with_mermaid` with
%% lists:keyreplace(before_closing_body_tag, 1, Opts, {Key, New})
%% and keyreplace/4 returns the list *unchanged* when the key is absent, so
%% `with_mermaid` on its own is a silent no-op: no script tag is emitted and
%% nothing warns. Declaring the key here gives keyreplace something to hit.
%% The fold keysorts its options first, and before_closing_body_tag sorts
%% ahead of with_mermaid, so the seed is always in place by the time the
%% mermaid clause runs; the merge then concatenates the injected script onto
%% this empty string. Delete the seed and every diagram silently degrades to
%% an inert code block. Checked against rebar3_ex_doc v0.3.0, the newest
%% release -- if a later one fixes keyreplace, this line can go.
{before_closing_body_tag, #{html => ""}},
{with_mermaid, true}
]}.
{hex, [{doc, ex_doc}]}.
{cover_enabled, true}.
{cover_export_enabled, true}.
{cover_opts, [verbose]}.
{covertool, [
{coverdata_files, [
"ct.coverdata",
"eunit.coverdata"
]}
]}.
%% == Common Test ==
{ct_opts, []}.
%% == Shell ==
{shell, [{apps, [ergon]}, {config, "config/sys.config"}]}.
%% == Dialyzer ==
{dialyzer, [
{warnings, [unknown]},
%% pg_types is transitive through pgo but must be named explicitly, or
%% `pgo:result()` resolves against a type dialyzer has never seen.
{plt_extra_apps, [pgo, pg_types, migraterl, epgsql, worker_pool, backoff]}
]}.
%% == Profiles ==
{profiles, [
%% The strictness that used to sit in the top-level erl_opts. Kept out of
%% `default` so it never ships to consumers, and out of `test` so that
%% `rebar3 as check compile` is a standalone gate rather than something you
%% only reach by running the suite.
{check, [
{erl_opts, [warnings_as_errors, verbose, report]}
]},
{test, [
{erl_opts, [debug_info, nowarn_export_all, warnings_as_errors]},
%% proper backs the property tests over ergon_fsm and
%% ergon_temporal_period, the two modules that are pure, total, and
%% boundary-sensitive. Test-profile only, so it never reaches rebar.lock
%% and never appears in deps.nix.
{deps, [{proper, "1.5.0"}]}
]},
%% rebar3_hex lives in its own profile rather than in project_plugins, so
%% `rebar3 compile` never tries to load it. It is fetched from hex on demand
%% and only used by the publish workflow, on a version tag. Pinned, because
%% an unpinned plugin means the release job resolves whatever is newest at
%% tag time -- the one job where a surprise is least welcome.
{publish, [
{plugins, [{rebar3_hex, "7.2.0"}]}
]}
]}.