fix(theme): avoid repeated host NIF probes - #108
Conversation
Cache NIF availability after the first serialized probe while allowing a later native code load to restore the native path. Bead: clarity-7mu
Route platform, theme updates, and appearance reads through one serialized availability state and isolate deterministic load recovery tests. Bead: clarity-7mu
|
Addressed the adversarial review in 3fd3df1:
Ready for rereview. |
|
Adversarially reviewed. Approve. Mechanism verified correct: lock-free persistent_term read in steady state, :global.trans-serialized first probe (12 concurrent callers → exactly one on_load report, proven by the new test), re-probe gated on :code.is_loaded flipping — and the device path can't regress because device NIFs are statically linked (ERL_NIF_INIT + -DSTATIC_ERLANG_NIF on both platforms), so first-load is deterministic and this PR only changes retry-after-failure behavior. Hot-code-push cycle (load→unload→reload) covered by the new recovery test. Empirical: full-suite 'Failed to load NIF library' warnings 199 → 78 (Theme's own sites fully quiet — focused theme run 17 → 1, and that 1 is the by-design single probe report). Gates: 1282 tests / 0 failures, format, credo --strict, warnings-as-errors all clean. Rebase: branch sits directly on the 0.7.35 tag, no conflicts. Non-blocking notes: (1) a genuine device NIF failure now logs once then falls back silently forever — an explicit one-shot Logger.warning in mark_nif_unavailable/1 would make that intentional rather than incidental; (2) recovery from :unavailable relies on another caller loading mob_nif — fine given the renderer, worth a comment; (3) the shared nif_call rescues broader than safe_platform/0's old UndefinedFunctionError/ErlangError set — a transient badarg briefly latches :unavailable (self-heals); (4) the remaining 78 warnings are Mob.Device/DNS probes outside this PR's scope — filing a follow-up issue. Merging. |
Summary
Validation
Bead: app-7mu