Bug Fixes
-
[Repo] Conditionally reference database driver errors
The retryable_exceptions macro previously hard-coded references to
MyXQL.ErrorandPostgrex.Error, which Elixir v1.20.0.rc.2+ flags as missing module references at macro expansion time when the corresponding driver isn't a project dependency. The missing module reference could escalate into a deadlock, and compilation would halt entirely.Driver error lists are now resolved at compile time and only include modules that are actually loaded, so projects using
PostgrexwithoutMyXQL(or vice versa) compile cleanly. -
[Cron] Reject impossible combinations in cron expressions
Cron strings whose day and month fields could never align (e.g. "0 0 30 2 *", or "0 0 31 4 *") parsed, but caused
next_at/2andlast_at/2to loop indefinitely.Now expressions are validated to ensure at least one day fits within the maximum length of at least one selected month.
-
[Cron] Validate cron range bounds before expansion
Range parts like 0-99999999 were accepted and expanded into the full integer range before the out-of-bounds check fired. For sufficiently large upper bounds that could stall the BEAM and risk OOM. The same path was reachable via the step variant 0-99999999/1 and the open-ended form 99999999/1.
Expression parsing now compares against the field's allowed min/max and rejects out-of-range values before any range is materialized.
-
[Migration] Fix prefix escaping in Postgres migrations
Switch to the standard doubled-quote escape so it works under default Postgres configuration.
The escaped_prefix value was using
\'to escape single quotes, which hasn't been enabled by default since 9.1. Under default settings, the backslash was treated literally and the quote terminated the string, allowing a crafted prefix to break out of the SQL literal inmigrated_version/1and the notify trigger bodies. -
[Backoff] Narrow
with_retryexit catch to :timeoutExits never carry a database error module atom in the first tuple element. Connection failures surface as raised database exceptions, which the rescue clause above already handles. The catch now only matches
:exit, {:timeout, _}, the one shape that's actually reachable.