mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
land: area/client-reliability 4bc52f9ded (client-reliability)
This commit is contained in:
commit
0bd0b1c3e3
15 files changed
+292
-2
No files matched your search
@@ -0,0 +1,3 @@
|
||||
# client-reliability-5
|
||||
|
||||
Investigation at0c1dd7e8:bounded active URL success/timeout cleanly settle; disposed active primary media error starts1 new mirror HEAD(expected0). Shared/rejoin and later same-source controls pass. Evidence test_logs/TEST_LOG_2026-10-20_13-30-00_client-reliability-5.md; scratch /tmp/bitvid-client-reliability-5-active-url.mjs. Await dispatch routing; no product/regression changes.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Item5 implementation
|
||||
|
||||
Controller-only6-line pre-candidate ownership guard. Six new lifecycle scenarios reproduce2 baseline failures and pass18/18 fixed;6 reverted mutants rejected. Unique integrity note test_logs/TEST_INTEGRITY_client-reliability-5.md. Focused/lint/build running; awaiting explicit dispatch full-suite/browser slots and verified unstable merge before final checks/landing. No active abort/observer/cache/limit changes.
|
||||
@@ -0,0 +1,3 @@
|
||||
# client-reliability-5
|
||||
|
||||
Do not equate retained active work with a leak: explicit success and controlled real timeout release resources/slots and cache correctly. Route only demonstrated new mirror HEAD after disposal; guard candidate continuation in controller before considering active abort or broader resource policy. Existing observer token is sufficient.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Item5 continuation boundary
|
||||
|
||||
- Keep bounded already-active success/failure caching. Check existing lifecycle owners only BEFORE starting each candidate in probeUrlList; zero owners marks existing record cancelled and returns explicit cancellation. No probe abort or observer/cache/TTL/concurrency change.
|
||||
- Shared and rejoining owners remain eligible because record owners are checked at continuation time. Completed final-source failure keeps original cache behavior; cancelled mirror chains never cache offline.
|
||||
- Six focused regressions exercise actual observer/controller/cache plus external IO twins; unique integrity file during parallel trial.
|
||||
- Dispatch resource coordination: local full suite is next after administrative drain but requires explicit grant; browser belongs initially to playback QA. All CLI/gate launches clear inherited NODE_TEST_CONTEXT operationally; no kit/runner change.
|
||||
@@ -28,6 +28,12 @@
|
||||
|
||||
## client-reliability
|
||||
|
||||
- 2026-10-20: item5 ready atmergedf2a392fa(product12f92732):full427/427 files60s-bound exit0,focused28/lifecycle18,six reverted mutants,lint11/build-artifact/native Chromium+Firefox smoke pass;obsolete mirror HEAD1→0,shared/rejoin/retry/hidden reveal pass,0 external/pageerrors. Full-slot wait10m57s recorded;browser released,expensive slot held through normal landing. Remaining queue/durable ancestry/close;active abort/real playback/CPU unverified.
|
||||
|
||||
- 2026-10-20: item5 routed controller-only pre-candidate guard implemented; baseline16pass/2fail→fixed18/18 lifecycle,6 rejected/reverted mutants,focused28/4files,lint11/build+artifact pass. No full/browser launch while dispatch administrative drain/QA reservation holds; slot requested13:32:54UTC,await explicit grant and verified unstable merge. No active abort/observer/cache/limits change; actual fallback/CPU unverified. Unique integrity/evidence in test_logs/*client-reliability-5*.
|
||||
|
||||
- 2026-10-20: item5 investigation at0c1dd7e8:active URL success/real4000ms controlled timeout release media/slot correctly;disposed active primary media error starts1 obsolete mirror HEAD(expected0),strict assertion naturally exits1 after cleanup/retry. Shared/rejoin owner and later same-source controls pass. Proposed controller-only pre-candidate ownership guard + focused tests; await dispatch routing. No product/tests changed; active abort/browser/fallback/CPU unverified. See test_logs/TEST_LOG_2026-10-20_13-30-00_client-reliability-5.md.
|
||||
|
||||
- 2026-10-20: item4 done/closed after normal landing89ccb907(submission7055496b,gate exit0,unstable ancestry exit0). Full427/427 files,focused22,lifecycle12,13 reverted mutants,lint11,build/artifact/native Chromium+Firefox controlled IO pass;obsolete starts1→0. Dispatch landing event sent; preview refresh owned by dispatch. No further item without routing. Actual media fallback/live peers/active abort/CPU and whole Stage3 unverified. Closure metadata/final event follow.
|
||||
|
||||
- 2026-10-20: item4 ready atce1381f5; full427/427 file exits0 with60s/file bound,focused22/22,lifecycle12/12,13 rejected/reverted mutants,lint11/11,build/artifact and Chromium+Firefox controlled native-observer smoke pass (obsolete starts0). Remaining normal queue/durable landing/ancestry then close/report. Actual fallback/live IO/active abort/CPU remain unverified.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"id": "client-reliability-5",
|
||||
"area": "client-reliability",
|
||||
"status": "open",
|
||||
"status": "in-progress",
|
||||
"title": "Reproduce remaining active URL or torrent probe lifecycle defect before scoping a fix",
|
||||
"blockedOn": null,
|
||||
"addedOn": "2026-10-20",
|
||||
"filedAt": "3f627f5df3da7bcd28d910d9f8161844fa77ff74"
|
||||
"filedAt": "3f627f5df3da7bcd28d910d9f8161844fa77ff74",
|
||||
"evidence": "Controller guard12f92732,mergedf2a392fa:full427/427files,focused28/lifecycle18,six reverted mutants,lint11/build/browser pass;obsolete mirrorHEAD1\u21920. Slot wait10m57s respected. Normal product queue/durable ancestry pending. See test_logs/TEST_LOG_2026-10-20_13-51-00_client-reliability-5-ready.md"
|
||||
}
|
||||
@@ -463,6 +463,12 @@ export default class UrlHealthController {
|
||||
}
|
||||
let sawTimeout = false;
|
||||
for (const url of list) {
|
||||
// Completed active work may still cache its result, but starting another
|
||||
// source requires a live owner (including a card that rejoined meanwhile).
|
||||
if (options.lifecycle && !options.lifecycle.owners.size) {
|
||||
options.lifecycle.cancelled = true;
|
||||
return { outcome: "cancelled" };
|
||||
}
|
||||
let result;
|
||||
try {
|
||||
result = await this.probeUrl(url, options);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Item5 integrity note
|
||||
|
||||
```yaml
|
||||
test_integrity_note:
|
||||
change_type: ["new_tests"]
|
||||
scenarios:
|
||||
- id: SCN-active-primary-disposed-mirror
|
||||
given: "primary media is active, with an alternate mirror"
|
||||
when: "the last owner disposes then primary media errors"
|
||||
then: "no mirror HEAD starts; chain settles null without cache or stale UI, later fresh request succeeds"
|
||||
- id: SCN-active-shared-mirror
|
||||
given: "two registrations share active media"
|
||||
when: "one owner disposes and primary errors"
|
||||
then: "ordered mirror serves live owner, healthy cache avoids later requests, disposed badge stays unchanged"
|
||||
- id: SCN-active-rejoin-mirror
|
||||
given: "primary active media survives last-owner disposal"
|
||||
when: "same-source live owner rejoins before primary error"
|
||||
then: "dedup survives and ordered mirror serves new owner without duplicate primary IO"
|
||||
- id: SCN-active-later-mirror-disposal
|
||||
given: "first mirror media is active and another mirror exists"
|
||||
when: "last owner disposes then first mirror errors"
|
||||
then: "next mirror HEAD does not start, cancellation settles without cache or stale UI"
|
||||
- id: SCN-active-timeout-cleanup-retry
|
||||
given: "media is active with real configured initial and longer retry deadlines"
|
||||
when: "last owner disposes and controlled clock reaches initial timeout"
|
||||
then: "slot/source clear, no new retry resources or cache, later fresh request is healthy"
|
||||
- id: SCN-completed-active-final-error-cache
|
||||
given: "active primary has no further candidate"
|
||||
when: "last owner disposes then media errors"
|
||||
then: "completed active failure keeps existing offline cache result without stale UI"
|
||||
observable_outcomes:
|
||||
- "fetch/media starts, source cleanup, slot release, promise settlement and actual cache/inflight records"
|
||||
- "live/disposed connected badge state and ordered mirror requests"
|
||||
determinism_controls:
|
||||
- "Real observer/controller/cache with controlled IntersectionObserver, jsdom native media event APIs and stubbed external fetch/media IO"
|
||||
- "node:test mock clock advances configured4000ms timeout; no sleeps, retries, public network or forced exit"
|
||||
anti_cheat_rationale:
|
||||
prevents:
|
||||
- "returning cancelled for live shared/rejoining owners"
|
||||
- "guarding only first mirror or discarding completed active results"
|
||||
- "caching cancellation as offline or starting obsolete retry resources"
|
||||
- "over-mocking queue/controller instead of service boundaries"
|
||||
relaxation:
|
||||
did_relax_any_assertion: false
|
||||
if_true_explain_spec_basis: ""
|
||||
```
|
||||
|
||||
Existing assertions unchanged; six new scenarios (18 total lifecycle scenarios). Baseline before guard naturally exits1 with new primary/later-mirror failures (16pass/2fail/0cancelled). Fixed18pass/0fail/0cancelled. Unique note avoids shared integrity-file writes during parallel trial.
|
||||
|
||||
`python3 /tmp/item5-mutants.py`: six deliberately broken variants each naturally exit1 with named assertion failures,0 cancelled, restored in finally before gates. Missing candidate guard kills primary/later-mirror scenarios; cancelling live mirrors kills shared+rejoin controls; checking only first mirror kills later-mirror case; caching cancellation kills null/cache expectations; discarding final active errors kills existing-offline-cache scenario; removing both media no-owner checks kills timeout cleanup/retry. Results `/tmp/item5-mutants.json` and `/tmp/item5-mutant-*.log`. No gate/test-registration changes or timed-out mutants counted.
|
||||
@@ -0,0 +1,28 @@
|
||||
# client-reliability-5 active URL investigation
|
||||
|
||||
## Scope and source
|
||||
|
||||
- HEAD `0c1dd7e86be3e28edc96aca47f7753a98990dde0`; compared filedAt `3f627f5df3da7bcd28d910d9f8161844fa77ff74`: no observer/controller product differences. Claimed item5 after merge/read updated routing; no product or regression changes.
|
||||
- Scratch `/tmp/bitvid-client-reliability-5-active-url.mjs`, SHA256 `31c7fa62c306b28008ee663fc69d25834904ee38cbf34711230ff0d3cdc66fd7`.
|
||||
- Real attachUrlHealthBadges/cardObserver/controller/probeUrlList/probeUrl/media wait queue and actual state/cache functions. Callback shape matches VideoListView and feedCoordinator. jsdom/native DOM event APIs; only external fetch responses and media load/pause are controlled. Deferred fetch records and explicit loadeddata/error events; node:test mock clock advances the real configured4000ms deadline. No sleeps/retries/live network/forced exit. Mock timers reset and DOM closed before failing assertion. Real media decoding/resources are virtualized; counts describe IO boundary retention, not CPU/RSS.
|
||||
- First mailbox_read hit automatic approval-review deadline, not rejection; one allowed retry succeeded. Pickup reported to dispatch; no bypass/control change.
|
||||
|
||||
## Commands and observations
|
||||
|
||||
All commands use `env -u NODE_TEST_CONTEXT node /tmp/bitvid-client-reliability-5-active-url.mjs <mode>`. Each uses one event/source, optional mirror and actual in-flight deduplication. Initial primary HEAD is explicitly resolved to create one active media probe before disposal. Disposed DOM stays connected to expose stale UI. Before/after disposal: HEAD starts1, media resource1, active slot1, queued0, settled0, no cache. Observer disconnect confirmed.
|
||||
|
||||
- `success`: natural exit0. Explicit loadeddata after disposal releases resource/slot to0, settles1, stores healthy once; old connected badge remains checking. Later same-source registration uses healthy cache, adds0 HEAD requests and paints healthy. This is intentional bounded active caching, not a demonstrated leak.
|
||||
- `timeout`: natural exit0. Advancing real4000ms media deadline with mock clock releases resource/slot to0, settles1, no health cache or additional media. Existing longer retry option is configured via actual cache constants, but no-owner lifecycle prevents another media start. Later same source starts1 fresh HEAD/media and paints healthy; final settled2, one healthy store from retry only.
|
||||
- `mirror-disposed --expect-no-obsolete-head`: natural exit1 AFTER cleanup/retry, AssertionError `1 !== 0` at line50, message `disposed last-owner active failure must not start a fresh mirror HEAD`. Primary media error after disposal starts mirror HEAD2: obsolete new HEAD count1(expected0), unresolved HEAD1, media resource0, active slot0, queued0, unsettled original promise. Resolving that controlled mirror HEAD eventually settles original null with no cache and no new media/stale badge. Later retry starts1 fresh primary HEAD/media, healthy cache/badge, all media/slots0; final settled2.
|
||||
- `mirror-shared`: natural exit0. A second live registration requests same event/source before original disposal: still1 initial HEAD and1 in-flight promise. Primary error starts one ordered mirror HEAD; resolving it starts one mirror media and loadeddata settles healthy for live badge; disposed badge stays checking. Final initial-chain media/slots0, settled1, healthy cache, later retry adds0 HEAD.
|
||||
- `mirror-rejoin`: natural exit0. Same as shared control, but the second same-source registration arrives AFTER original disposal while its primary media remains active. It deduplicates onto original promise, restores live ownership, and mirror success paints healthy; no duplicated primary request, stale badge or retained media/slot after completion.
|
||||
|
||||
## Smallest reproduced defect and proposed routing
|
||||
|
||||
Active primary media failure after the LAST owner is disposed starts a NEW mirror HEAD request. This is additional obsolete work and promise retention, distinct from allowing an already-active bounded probe to settle/cache. `probeUrlList` moves from a completed error result to the next candidate without checking live ownership; the media-stage guard is later, after that mirror HEAD has started.
|
||||
|
||||
Proposed scope: `js/ui/urlHealthController.js` lifecycle check BEFORE starting a subsequent candidate, focused URL lifecycle regression scenarios, Test Integrity Note and evidence. Existing observer token/unregister hook is sufficient. No active HEAD/media/HLS/torrent abort, shared observer/app/cache-module edits, TTL/limit changes or broad Stage3 work proposed.
|
||||
|
||||
Acceptance:0 new mirror HEAD starts after last-owner active error; cancelled chain settles without negative cache/stale effects; active healthy caching remains; shared live/rejoining owner still gets ordered mirror success; timeout and later same-source requests retain slot/cache/inflight safety. Preserve existing mirror fallthrough for live owners.
|
||||
|
||||
Unverified: active HEAD/HLS/torrent teardown, real media decoding/network/browser fallback/live peers, CPU/RSS and whole Stage3. No browser/full-suite/lint/build reruns for evidence-only investigation; prior item4 qualification not repeated. Preview3000 untouched. Await dispatch independent assessment and routing before product/tests.
|
||||
@@ -0,0 +1,10 @@
|
||||
# Item5 precommit evidence
|
||||
|
||||
- `env -u NODE_TEST_CONTEXT node tests/url-health-lifecycle.test.mjs` before guard: natural exit1,16pass/2fail/0cancelled, disposed active primary and later-mirror cases fail. After guard and formatting: natural exit0,18/18,0 failed/cancelled/skipped (`/tmp/item5-lifecycle-final.log`).
|
||||
- `python3 /tmp/item5-mutants.py`: six/six reverted variants naturally exit1 with named assertion failures,0 cancelled; no timeouts or survivors. Unique integrity mapping test_logs/TEST_INTEGRITY_client-reliability-5.md.
|
||||
- `env -u NODE_TEST_CONTEXT node scripts/run-unit-tests.mjs url-health health-disposal`: natural exit0,4 files/28 scenarios (lifecycle18,controller4,multisource4,view lifecycle2). `/tmp/item5-focused.log`.
|
||||
- `env -u NODE_TEST_CONTEXT npm run lint` with approved git subprocess access: exit0,11 stages (`/tmp/item5-lint.log`).
|
||||
- `env -u NODE_TEST_CONTEXT npm run build`: exit0 including artifact verification (`/tmp/item5-build.log`). No dependency/runner/gate changes.
|
||||
- First mailbox_read tool review hit its deadline; accumulated visible tool waits at least57s, exact approval wall duration not separately instrumented. It was a tool/approval stall, not product failure or rejection. One permitted retry succeeded; pickup mailbox sent13:27:49 UTC.
|
||||
- Full-suite/browser slots requested13:32:54 UTC. Dispatch queued local full slot behind administrative drain and reserves initial browser to QA; no full/browser launches made. Full-slot wait duration will be measured through grant, not inferred from silence.
|
||||
- Current code/tests based on0c1dd7e8 plus notes-only140618f8; final verified unstable merge, full/browser grants/checks, unchanged normal landing/durable ancestry remain. Active abort,real decoding/playback/live peers/CPU and whole Stage3 unverified.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Item5 ready on merged f2a392fa3b969a66cdaca2ee5e8877c72658bcdf
|
||||
|
||||
- Product12f927321fdd0a945f3bdcfb3a618ef16b54ff7c; non-destructive merge of verified unstableb922c186 printedf2a392fa. Tree clean through checks; product/controller diff remains6lines.
|
||||
- Resource request13:32:54UTC; dispatch explicit exclusive full→browser→product-landing grant13:43:51.426UTC:10m57s waiting. Merge completed13:44:06,check-start event13:44:28. Full pass/browser-start event13:50:44,browser done by13:50:49. No full/browser launched before grant. Initial pickup13:27:49; approval-review deadline stall is tooling, not product failure/rejection (see precommit note).
|
||||
- `env -u NODE_TEST_CONTEXT UNIT_TEST_TIMEOUT_MS=60000 npm test`: natural exit0,427/427 files,0 quarantined; log `/tmp/item5-full-merged.log`. No aggregate scenario count exposed by runner.
|
||||
- `env -u NODE_TEST_CONTEXT npm run lint` with approved git subprocess access: exit0,11stages (`/tmp/item5-lint-merged.log`).
|
||||
- `env -u NODE_TEST_CONTEXT npm run build`: exit0 including artifact verification (`/tmp/item5-build-merged.log`).
|
||||
- Relevant focused4files/28scenarios pass,including18 lifecycle; six new scenarios baseline16pass/2fail→fixed18pass/0fail/0cancelled; six restored mutants naturally exit1 with named failures/0cancelled. Unique integrity note `test_logs/TEST_INTEGRITY_client-reliability-5.md`.
|
||||
- `env -u NODE_TEST_CONTEXT node /tmp/item5-browser.mjs` with approved private loopback/browser access: exit0, Chromium+Firefox built-dist/native IntersectionObserver, external media/fetch IO virtualized. Each obsolete mirror HEAD0 vs baseline1; cancelled result null/no cache/old connected badge checking; later same-source retry healthy; shared/rejoin controls each one ordered mirror with live healthy/old checking and resource/slot0; hidden reveal works; external requests0/pageerrors0. Browser cache is a twin, unit uses actual cache module. Owned server/browser closed and preview3000 untouched.
|
||||
- Browser released after smoke,exclusive expensive slot retained through normal product landing as granted. Next normal CLI submit clears NODE_TEST_CONTEXT without changing gate/runner/assertions; durable landing/unstable ancestry/close/final events remain.
|
||||
- Out of scope/unverified: active HEAD/media/HLS/torrent abort, actual media decoding/playback fallback/live peers,CPU-RSS/full Stage3,production/signers/wallet/deploy.
|
||||
@@ -436,3 +436,144 @@ test("shared inflight ownership also survives a second controller using the same
|
||||
assert.equal(badge.dataset.urlHealthState, "healthy");
|
||||
assert.equal(f.heads.length, 4);
|
||||
});
|
||||
|
||||
test("active primary error after last-owner disposal starts no mirror HEAD and permits a fresh request", async (t) => {
|
||||
const f = fixture(t),
|
||||
v = f.video("disposed-active-mirror");
|
||||
v.sources = [{ url: "https://mirror.invalid/obsolete.mp4" }];
|
||||
const old = f.feed([v]);
|
||||
old.observer.show();
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 1);
|
||||
assert.equal(f.media.length, 1);
|
||||
old.dispose();
|
||||
f.done(f.media[0], "error");
|
||||
await flush();
|
||||
assert.equal(
|
||||
f.heads.length,
|
||||
1,
|
||||
"disposed chain must not start a mirror HEAD"
|
||||
);
|
||||
assert.equal(await f.promises[0], null);
|
||||
assert.equal(cache.getCachedUrlHealth(v.id, v.url), null);
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
assert.equal(f.media[0].getAttribute("src"), null);
|
||||
assert.equal(old.badges[0].dataset.urlHealthState, "checking");
|
||||
const fresh = f.feed([v]);
|
||||
fresh.observer.show();
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
assert.equal(f.media.length, 2);
|
||||
f.done(f.media[1]);
|
||||
await flush();
|
||||
assert.equal(fresh.badges[0].dataset.urlHealthState, "healthy");
|
||||
assert.equal(cache.getCachedUrlHealth(v.id, v.url).status, "healthy");
|
||||
});
|
||||
|
||||
for (const timing of ["shared", "rejoin"]) {
|
||||
test(`active primary error preserves ordered mirror for a ${timing} live owner`, async (t) => {
|
||||
const f = fixture(t),
|
||||
v = f.video(`active-${timing}`);
|
||||
v.sources = [
|
||||
{ url: "https://mirror.invalid/live-first.mp4" },
|
||||
{ url: "https://mirror.invalid/unused-second.mp4" }
|
||||
];
|
||||
const old = f.feed([v]);
|
||||
old.observer.show();
|
||||
await flush();
|
||||
if (timing === "rejoin") old.dispose();
|
||||
const live = f.feed([v]);
|
||||
live.observer.show();
|
||||
await flush();
|
||||
if (timing === "shared") old.dispose();
|
||||
assert.equal(f.heads.length, 1);
|
||||
assert.equal(f.promises.length, 1);
|
||||
f.done(f.media[0], "error");
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
assert.equal(f.heads[1].source, v.sources[0].url);
|
||||
assert.equal(f.media.length, 2);
|
||||
f.done(f.media[1]);
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2, "healthy first mirror must stop fallback");
|
||||
assert.equal(live.badges[0].dataset.urlHealthState, "healthy");
|
||||
assert.equal(old.badges[0].dataset.urlHealthState, "checking");
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
const cached = f.feed([v]);
|
||||
cached.observer.show();
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
assert.equal(cached.badges[0].dataset.urlHealthState, "healthy");
|
||||
});
|
||||
}
|
||||
|
||||
test("active first mirror error after disposal does not start the next mirror", async (t) => {
|
||||
const f = fixture(t),
|
||||
v = f.video("later-mirror");
|
||||
v.sources = [
|
||||
{ url: "https://mirror.invalid/first.mp4" },
|
||||
{ url: "https://mirror.invalid/obsolete-second.mp4" }
|
||||
];
|
||||
const old = f.feed([v]);
|
||||
old.observer.show();
|
||||
await flush();
|
||||
f.done(f.media[0], "error");
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
old.dispose();
|
||||
f.done(f.media[1], "error");
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
assert.equal(f.media.length, 2);
|
||||
assert.equal(await f.promises[0], null);
|
||||
assert.equal(cache.getCachedUrlHealth(v.id, v.url), null);
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
assert.equal(old.badges[0].dataset.urlHealthState, "checking");
|
||||
});
|
||||
|
||||
test("disposed active media timeout releases its slot without retry resources and later requests remain playable", async (t) => {
|
||||
const f = fixture(t),
|
||||
v = f.video("active-timeout");
|
||||
f.controller.constants = {
|
||||
URL_PROBE_TIMEOUT_MS: cache.URL_PROBE_TIMEOUT_MS,
|
||||
urlHealthConstants: cache.urlHealthConstants
|
||||
};
|
||||
t.mock.timers.enable({ apis: ["setTimeout"] });
|
||||
const old = f.feed([v]);
|
||||
old.observer.show();
|
||||
await flush();
|
||||
old.dispose();
|
||||
t.mock.timers.tick(cache.URL_PROBE_TIMEOUT_MS);
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 1);
|
||||
assert.equal(f.media.length, 1);
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
assert.equal(f.media[0].getAttribute("src"), null);
|
||||
assert.equal(await f.promises[0], null);
|
||||
assert.equal(cache.getCachedUrlHealth(v.id, v.url), null);
|
||||
assert.equal(old.badges[0].dataset.urlHealthState, "checking");
|
||||
const fresh = f.feed([v]);
|
||||
fresh.observer.show();
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 2);
|
||||
assert.equal(f.media.length, 2);
|
||||
f.done(f.media[1]);
|
||||
await flush();
|
||||
assert.equal(fresh.badges[0].dataset.urlHealthState, "healthy");
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
});
|
||||
|
||||
test("completed active failure without another candidate preserves its existing offline cache result", async (t) => {
|
||||
const f = fixture(t),
|
||||
v = f.video("final-active-failure"),
|
||||
old = f.feed([v]);
|
||||
old.observer.show();
|
||||
await flush();
|
||||
old.dispose();
|
||||
f.done(f.media[0], "error");
|
||||
await flush();
|
||||
assert.equal(f.heads.length, 1);
|
||||
assert.equal(f.controller.activeVideoProbes, 0);
|
||||
assert.equal(cache.getCachedUrlHealth(v.id, v.url).status, "offline");
|
||||
assert.equal(old.badges[0].dataset.urlHealthState, "checking");
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
# client-reliability-5
|
||||
|
||||
- [x] Merge rules/brief,check filedAt,claim.
|
||||
- [x] Actual observer/controller/cache active success/timeout resource measurements.
|
||||
- [x] Reproduce obsolete mirror HEAD1(expected0),assertion after cleanup naturally exits1.
|
||||
- [x] Shared owner,rejoin and later same-source controls naturally exit0.
|
||||
- [x] Report smallest scope/acceptance to dispatch.
|
||||
- [ ] Dispatch independent assessment/routing before product/regression changes.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Item5
|
||||
|
||||
- [x] Reproduce/independent route.
|
||||
- [x] Controller-only guard/six scenarios and six rejected mutants.
|
||||
- [ ] Focused/lint/build results and committed merged-tree checks.
|
||||
- [ ] Explicit full-suite slot and browser slot/QA coverage.
|
||||
- [ ] Normal clean-env queue,durable status/ancestry/close/dispatch events.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Item5
|
||||
|
||||
- [x] Controller pre-candidate guard,six new regressions/six restored mutants.
|
||||
- [x] Focused28,lifecycle18,full427files,lint11,build/artifact,native Chromium+Firefox controlled smoke.
|
||||
- [x] Respect/measured full/browser wait10m57s;browser released.
|
||||
- [ ] Normal clean-env product queue,durable landed status/unstable ancestry.
|
||||
- [ ] Close metadata,dispatch landing/final/slot-release.
|
||||
Reference in new issue
Block a user