Forum teuk.org

🦉🛡️ Mediabot v3 — The Owl Never Comes Back Silent

in Mediabot · started by TeuK · 1w ago

TeuK · 1w ago

Development chronicle — mb640 to mb641 · Shared HTTP policy, crash-aware version checks and truthful worker termination

The remote version checker already knew how to contact GitHub.

What this round fixes is more fundamental:

when the check fails, Mediabot must always be able to say why.

mb640 fixes two real production failures discovered on an OVH/Kimsufi host.

mb641 then closes the remaining terminal worker states so that a fork failure, reap failure, signal, non-zero exit, empty payload or malformed payload can never quietly collapse into:

github: Undefined

with no explanation.

No database schema change was required.

🌐 mb640 — One HTTP policy for the whole bot

The version checker had created its own HTTP::Tiny client with SSL verification explicitly enabled.

That conflicted with Mediabot’s existing HTTP policy in:

Mediabot::External::_make_http

which already contains the compatibility rules used by the rest of the application.

The version checker now uses that shared client too.

One application, one HTTP policy, no hidden TLS exception inside the update subsystem.

🗣️ A crash is now a diagnostic

The more serious defect was an exception hidden inside an eval.

If getVersion died, the child could return no useful result while the parent still had a cached local version:

local: 3.4dev-...
github: Undefined

The reason had disappeared.

A programming crash and a network failure could therefore look identical.

mb640 converts the exception into an explicit diagnostic such as:

version check crashed: Can't locate object method ...

Perl source-location noise is removed, multiline errors are flattened and excessively large messages are bounded for IRC.

Both the asynchronous worker path and the no-event-loop compatibility path preserve the reason.

🛡️ mb641 — Every terminal worker state tells the truth

The final audit found a few rarer process-level exits that could still leave the remote version undefined without an explanation.

mb641 closes them.

A failure to create the worker now has a reason.

A failure to reap the worker has a reason.

A worker terminated by a signal has a reason.

A non-zero worker exit has a reason.

An empty worker payload has a reason.

A non-empty but invalid structured payload has a reason.

And if the child already supplied a valid diagnostic, the parent preserves it instead of overwriting it.

The contract is now simple:

remote version unavailable
        ↓
there is a reason

📦 Empty and malformed results are different

An empty worker result becomes an explicit:

version check worker produced no result

A non-empty payload that cannot be decoded is treated as an invalid worker result.

Those are different failures and are no longer collapsed into silence.

The cached local version is also normalized before being reused on failure paths.

🧪 Regression coverage

The focused regression chain now covers:

138  getVersion HTTP behaviour
207  guarded HTTP failure handling
539  non-blocking asynchronous worker
814  IRC update command
818  remote-version diagnostics
819  timeout / URL override / VERSION validation
820  mb640 — version checks never fail silently
821  mb641 — terminal worker-state truth

Test 820 protects the high-level promise:

a silent or invalid worker result always has a reason

Test 821 owns the detailed worker-state machinery.

Keeping those responsibilities separate avoids fragile tests that depend on the exact formatting of the implementation while retaining strong behavioural coverage.

The final targeted validation completed green before commit.

🏰 Final parchment

The update owl already knew the roads to GitHub.

Then it learned how to explain a blocked road.

Now it has learned one final lesson:

if it falls from the sky, loses its message, is stopped by a signal, cannot be dispatched, or returns with a damaged parchment, that too is part of the report.

The administrator may still receive:

github: Undefined

when no remote version can be trusted.

But it should never again mean:

something went wrong somewhere — good luck.

A failed check is acceptable. A silent one is not.

You must be logged in to reply.