Loading the parity record
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Fetching the measured run — the pinned upstream oracle, every symbol and every case.
Parity / Oban
Every number on this page was produced by running both implementations over the same cases: the real oban package pinned at 2.23.1 answers first, and its answer is the expectation the Go port is held to. Nothing is a hand-written expectation, so a new upstream release re-scores the port on its own. See Oban for the port's own documentation. Source: github.com/malcolmston/oban.
Not a generic diagram: every node below names an artefact of this harness — the pinned package it installed, the runner files it started, the case files it streamed, and the counts it wrote out.
| Case group | Cases | Match | Mismatch | Group parity |
|---|---|---|---|---|
| cron-eval | 65 | 0 | 0 | 0.0% |
| cron-parse | 46 | 0 | 0 | 0.0% |
| cron-macros | 22 | 0 | 0 | 0.0% |
| backoff | 16 | 0 | 0 | 0.0% |
| job | 16 | 0 | 0 | 0.0% |
Every exported symbol of the upstream package, and what the port offers for it. The upstream list is derived mechanically, never from a README: run from parity/oban/elixir with MIX_ENV=prod mix run --no-start
Application.load(:oban)
for m <- Enum.sort(Application.spec(:oban, :modules)) do
exports =
m.module_info(:exports)
|> Enum.reject(fn {f, _a} ->
f in [:module_info, :__info__, :__struct__, :__impl__, :behaviour_info,
:__protocol__, :__using__, :__after_compile__, :__opts__]
end)
|> Enum.reject(fn {f, _a} -> String.starts_with?(Atom.to_string(f), "-") end)
|> Enum.sort()
|> Enum.map(fn {f, a} -> "#{f}/#{a}" end)
hidden? =
match?({:docs_v1, _, _, _, h, _, _} when h in [:hidden, :none…. A symbol with no case is untested, never a match.
| Upstream symbol | Go symbol | Status | Cases | Note |
|---|---|---|---|---|
| Oban.Cron.Expression.parse/1 | oban.ParseCron, oban.ParseCronSpec | differs | all 57 cron_parse cases: 46 parse-* + 11 macro-* (49/57 agree) | error-returning arity, the one the Go runner actually calls; same code path as parse!/1. Divergences below. |
| Oban.Cron.Expression.parse!/1 | oban.MustParseCron, oban.MustParseCronSpec | differs | same as above | raising arity; upstream raises ArgumentError, the port panics |
| Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | differs | 17 now-* + macro-reboot-now (17/18 agree) | only @reboot diverges; the day-of-month/day-of-week AND rule agrees exactly |
| Oban.Cron.Expression.now?/1 | — | untested | — | defaults to DateTime.utc_now/0; excluded as non-deterministic |
| Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | differs | 26 next-* + 8 macro-* + 9 upcoming-* (41/43 agree) | only @reboot and weekday 7 diverge |
| Oban.Cron.Expression.next_at/1 | — | untested | — | timezone-string arity; needs a tz database (see above) |
| Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | match | 14 prev-* + macro-daily-prev (15/15 agree) | |
| Oban.Cron.Expression.last_at/1 | — | untested | — | timezone-string arity, and for @reboot it is derived from VM uptime, which is not reproducible |
| Oban.Backoff.exponential/2 | — | missing | exp-attempt-1, exp-mult-100, exp-min-pad-10, exp-attempt-10, exp-attempt-11-clamped | no Go counterpart: the port has no exponential helper parameterised by mult/max_pow/min_pad, and ExponentialBackoff cannot express min_pad at all. All five cases fail on the Go side. |
| Oban.Backoff.exponential/1 | — | missing | — | default-options arity of the above |
| Oban.Backoff.jitter/2 | oban.ExponentialBackoff.Jitter field | differs | worker-backoff-jitter-mode | upstream jitter has three modes (:inc/:dec/:both) and a multiplier; the port has a single Jitter fraction that only ever *subtracts*, i.e. it is :dec-shaped, and the default policy applies none at all |
| Oban.Backoff.jitter/1 | — | missing | — | default-options arity |
| Oban.Backoff.with_retry/1, with_retry/2 | — | missing | — | retries a *database* interaction on DBConnection/Postgrex errors; not applicable without a repo |
| Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next (the default when Config.Backoff is nil) | differs | worker-backoff-1/2/3/5/10/20, worker-backoff-clamped-attempt, worker-backoff-bounds-1/5/20 (3/10 agree) | the default retry schedule is not the same algorithm** — see below |
| Oban.Worker.timeout/1 | oban.Config.JobTimeout / WorkerOptions | untested | — | upstream default is :infinity per job; the port has an engine-level per-attempt timeout. Different shape, no repo-free comparison. |
| Oban.Worker.to_string/1 | — | missing | — | module-name normalisation; the port names workers with plain strings |
| Oban.Worker.from_string/1 | (*oban.Registry).Lookup | untested | — | upstream resolves a worker *module* from a string; the port resolves a Worker from a registry, which is not the same operation |
| Oban.Worker.merge_opts/2 | oban.WorkerOptions | untested | — | use Oban.Worker option merging has no analogue; Go workers are configured with a struct |
| MACRO-Oban.Worker.__using__/2 | oban.Worker interface, oban.WorkerFunc | untested | — | use-macro code generation; not a comparable call |
| Oban.Job.new/2 | oban.NewJob + oban.JobOptions | differs | all 16 job-* cases (11/16 agree) | agrees on the default queue (default), default max_attempts (20), default state (available), explicit queue, explicit valid max_attempts and priority, schedule_in normalising the state to scheduled, args round-tripping (including nesting, key ordering, floats, booleans and nulls), the empty-worker rejection, and the unknown-option rejection. Diverges on validation, below. |
| Oban.Job.new/1 | oban.NewJob | untested | — | args-only arity; the port always requires a worker name |
| Oban.Job.to_map/1 | — | untested | — | changeset → insertable map; the Elixir runner uses Ecto.Changeset.apply_action!/2 instead so that invalid changesets surface as ok:false |
| Oban.Job.update/2 | oban.ReplaceField | untested | — | changeset update path used by :replace; not exercised without a repo |
| Oban.Job.states/0 | oban.State constants | untested | — | the port has the same seven states as typed constants but no enumerating function |
| Oban.Job.unique_states/1 | oban internal unfinishedStates | untested | — | the port's equivalent set is unexported, so there is nothing to call |
| Oban.Job.validate_unique/1 | oban.UniqueBy | untested | — | option validation for uniqueness; the port validates nothing up front |
| Oban.Job.warn_unique/1 | — | missing | — | deprecation warning for legacy unique options |
| Oban.Job.validate_replace/1 | oban.ReplaceField | untested | — | |
| Oban.Job.cast_period/1 | — | missing | — | {5, :minutes} → seconds; the port takes a time.Duration and needs no coercion |
| Oban.Job.cast_unique_group/1 | — | missing | — | expands :incomplete/:successful/… state groups |
| Oban.Job.format_attempt/1 | oban.AttemptError | missing | — | formats an unsaved_error into the errors array |
| Oban.Job.query/1 | oban.JobFilter | untested | — | builds an Ecto.Queryable; Postgres-only for args/meta containment |
| Oban.Period.to_seconds/1 | — | missing | — | {5, :minutes} → 300; the port uses time.Duration throughout |
| MACRO-Oban.Period.is_seconds/2 | — | missing | — | guard macro |
| MACRO-Oban.Period.is_valid_period/2 | — | missing | — | guard macro |
| Inspect.Oban.Cron.Expression *(hidden)* | 1 | untested | — | |
| Mix.Tasks.Oban.Install | 1 | untested | — | |
| Mix.Tasks.Oban.Install.Docs *(hidden)* | 3 | untested | — | |
| Oban | 55 | untested | — | |
| Oban.Application *(hidden)* | 2 | untested | — | |
| Oban.Config | 7 | untested | — | |
| Oban.CrashError | 3 | untested | — | |
| Oban.Cron *(hidden)* | 5 | untested | — | |
| Oban.Engine | 30 | untested | — | |
| Oban.Engines.Basic | 32 | untested | — | |
| Oban.Engines.Dolphin | 30 | untested | — | |
| Oban.Engines.Inline | 30 | untested | — | |
| Oban.Engines.Lite | 30 | untested | — | |
| Oban.Errors *(hidden)* | 2 | untested | — | |
| Oban.Harbor *(hidden)* | 5 | untested | — | |
| Oban.JSON *(hidden)* | 4 | untested | — | |
| Oban.Midwife *(hidden)* | 7 | untested | — | |
| Oban.Migration | 4 | untested | — | |
| Oban.Migrations *(hidden)* | 2 | untested | — | |
| Oban.Migrations.MyXQL *(hidden)* | 3 | untested | — | |
| Oban.Migrations.Postgres *(hidden)* | 5 | untested | — | |
| Oban.Migrations.Postgres.V01–V14 *(hidden)* | 2 each (28) | untested | — | |
| Oban.Migrations.SQLite *(hidden)* | 3 | untested | — | |
| Oban.Notifier | 15 | untested | — | |
| Oban.Notifiers.Isolated *(hidden)* | 12 | untested | — | |
| Oban.Notifiers.PG | 12 | untested | — | |
| Oban.Nursery *(hidden)* | 6 | untested | — | |
| Oban.Peer | 6 | untested | — | |
| Oban.Peers.Database | 9 | untested | — | |
| Oban.Peers.Global | 9 | untested | — | |
| Oban.Peers.Isolated *(hidden)* | 9 | untested | — | |
| Oban.PerformError | 3 | untested | — | |
| Oban.Plugin | 4 | untested | — | |
| Oban.Plugins.Cron | 8 | untested | — | |
| Oban.Plugins.Gossip *(hidden)* | 2 | untested | — | |
| Oban.Plugins.Lifeline | 8 | untested | — | |
| Oban.Plugins.Pruner | 8 | untested | — | |
| Oban.Plugins.Reindexer | 8 | untested | — | |
| Oban.Plugins.Repeater *(hidden)* | 2 | untested | — | |
| Oban.Queue.Drainer *(hidden)* | 1 | untested | — | |
| Oban.Queue.Executor *(hidden)* | 10 | untested | — | |
| Oban.Queue.Producer *(hidden)* | 9 | untested | — | |
| Oban.Queue.Supervisor *(hidden)* | 3 | untested | — | |
| Oban.Queue.Watchman *(hidden)* | 6 | untested | — | |
| Oban.Registry | 8 | untested | — | |
| Oban.Repo | 28 | untested | — | |
| Oban.Sonar *(hidden)* | 8 | untested | — | |
| Oban.Stager *(hidden)* | 8 | untested | — | |
| Oban.Telemetry | 8 | untested | — | |
| Oban.Testing | 30 | untested | — | |
| Oban.TimeoutError | 3 | untested | — | |
| Oban.Validation *(hidden)* | 8 | untested | — |
Every case the harness streamed to both runners, with the exact upstream symbol and Go symbol it exercised. A deliberate, documented difference is a deviation and is counted apart from a mismatch.
| Case | Group | Upstream symbol | Go symbol | Status | Note |
|---|---|---|---|---|---|
| exp-attempt-1 | backoff | Oban.Backoff.exponential/2 | — | unknown | upstream doctest: 2 |
| exp-mult-100 | backoff | Oban.Backoff.exponential/2 | — | unknown | upstream doctest: 200 |
| exp-min-pad-10 | backoff | Oban.Backoff.exponential/2 | — | unknown | upstream doctest: 12 |
| exp-attempt-10 | backoff | Oban.Backoff.exponential/2 | — | unknown | upstream doctest: 1024 |
| exp-attempt-11-clamped | backoff | Oban.Backoff.exponential/2 | — | unknown | upstream doctest: 1024 (exponent clamped by max_pow) |
| worker-backoff-1 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-2 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-3 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-5 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-10 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-20 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-clamped-attempt | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | max_attempts above 20 scales the attempt into 1..20 upstream |
| worker-backoff-jitter-mode | backoff | Oban.Backoff.jitter/2 | oban.ExponentialBackoff.Jitter | unknown | which jitter the default retry policy applies |
| worker-backoff-bounds-1 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | jittered value must stay inside [base, base + 10%] |
| worker-backoff-bounds-5 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| worker-backoff-bounds-20 | backoff | Oban.Worker.backoff/1 | (*oban.ExponentialBackoff).Next | unknown | |
| now-wild-true | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-daily-hit | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-daily-miss | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-seconds-ignored | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | sub-minute components are dropped |
| now-step-hit | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-step-miss | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-range-hit | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-range-miss | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-dow-name-hit | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | 2026-01-01 is a Thursday |
| now-dow-name-miss | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-month-name-hit | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-month-name-miss | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | |
| now-both-days-aligned | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | 2026-02-13 is a Friday: satisfies both day fields |
| now-both-days-dom-only | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | Vixie-cron either-day rule would fire (13th, but a Tuesday); Oban ANDs the two fields |
| now-both-days-dow-only | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | Vixie-cron either-day rule would fire (Friday, but not the 13th); Oban ANDs the two fields |
| now-dom-wild-dow-set | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | a wildcard day-of-month is always satisfied |
| now-dom-set-dow-wild | cron-eval | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | a wildcard day-of-week is always satisfied |
| next-wild | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-wild-mid-minute | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | reference instant has non-zero seconds |
| next-hourly | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-daily-1am | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-daily-1am-after | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | strictly after the reference instant |
| next-weekly-sunday | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-monthly | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-yearly | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | crosses the year boundary |
| next-leap-day-from-leap-year | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-leap-day-from-common-year | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | must skip forward to 2028 |
| next-step-minutes | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-open-range-step | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-range-hours | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | rolls to the next day |
| next-range-step-hours | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-list-hours | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-month-name-list | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-dow-name-range | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | Friday evening rolls to Monday |
| next-year-end | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-dow-saturday | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-month-step | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| next-dom-step-10 | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | days 1,11,21,31 — January has a 31st |
| next-dom-step-10-into-february | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | February has no 31st, so the next fire is in March |
| next-dom-31-only | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | skips February, March is next |
| next-both-days-aligned | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | the either-day rule would give 2026-01-02; ANDing gives the next Friday the 13th |
| next-both-days-first-monday | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | the 1st that is also a Monday |
| next-dow-7-alias | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | 7 as Sunday |
| prev-wild | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-wild-mid-minute | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-hourly | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-daily-1am | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | strictly before the reference instant |
| prev-daily-1am-later | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-monthly | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-yearly | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | crosses back over the year boundary |
| prev-weekly-sunday | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-leap-day | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | must walk back to 2024 |
| prev-step-minutes | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-range-hours | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | rolls back to the previous day |
| prev-dom-31-only | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | February has no 31st, so January is the answer |
| prev-both-days-aligned | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| prev-dow-name-range | cron-eval | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | Sunday walks back to Friday |
| upcoming-step-minutes | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | upstream side iterates next_at/2 |
| upcoming-daily | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | |
| upcoming-weekdays | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | must skip the weekend |
| upcoming-dom-list | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | |
| upcoming-month-step | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | crosses the year boundary |
| upcoming-dow-step | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | |
| upcoming-leap-days | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | 2020 and 2024; the port's search horizon is five years |
| upcoming-zero | cron-eval | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | n <= 0 yields nothing |
| macro-hourly-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-daily-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-midnight-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-weekly-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-monthly-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-yearly-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-annually-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | |
| macro-hourly-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-daily-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-midnight-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-weekly-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | 2026-03-15 is a Sunday |
| macro-monthly-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-yearly-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-annually-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | |
| macro-daily-prev | cron-macros | Oban.Cron.Expression.last_at/2 | (*oban.Schedule).Prev | unknown | |
| macro-weekly-upcoming | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Upcoming | unknown | |
| macro-reboot-parse | cron-macros | Oban.Cron.Expression.parse!/1 | oban.ParseCronSpec | unknown | upstream has a reboot? flag; the port has no equivalent |
| macro-reboot-now | cron-macros | Oban.Cron.Expression.now?/2 | (*oban.Schedule).Matches | unknown | upstream now?/2 is unconditionally true for @reboot |
| macro-reboot-next | cron-macros | Oban.Cron.Expression.next_at/2 | (*oban.Schedule).Next | unknown | upstream returns :unknown |