Interactive static assets stop loading after the browser stops the idle service worker, which keeps them only in memory
メンテナーはふだん 3 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 76/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
- 領域
- backend
調査の方向性
Start with packages/runtime-internal/src/interactive/worker.js and bootstrap.js to trace how static assets are registered and fetched; then read the named worker test and its Cache Storage test globals. Implement persistent asset storage across worker restarts, and verify the unit test plus the CDP end-to-end test in testing/src/specs/instrument-completion.spec.ts pass, including after a stopped worker is restarted.
索引モデルが issue の本文から書いたものです。
説明
An interactive instrument's static assets stop loading once the browser stops its idle service worker. worker.js keeps the assets only in a module-level Map. Browsers terminate a service worker that has handled no event for about 30 seconds (Chrome and Firefox both use a 30 s idle timeout), even while a page it controls is open, and the next fetch starts a fresh copy of the script with an empty map. bootstrap.js posts the assets only once, before render. So any asset first requested after a pause of more than 30 s with no network activity misses the map and goes to the network, where it does not exist. Typical cases are a stimulus image shown after an instruction screen, or a sound played on a later trial. The participant sees a broken image or hears nothing, partway through a task whose data is then recorded as if the stimulus had been shown.
Where
packages/runtime-internal/src/interactive/worker.js:5-6 and 53-77:
/** @type {Map<string, string>} */
const staticAssets = new Map();
// ...
addEventListener('message', (event) => {
// ...
Object.entries(data.staticAssets).forEach(([key, value]) => {
staticAssets.set(key, value);
});
event.ports[0]?.postMessage({ type: 'STATIC_ASSETS_READY' });
});
worker.addEventListener('fetch', (_event) => {
// ...
if (staticAssets.has(pathname)) {
packages/runtime-internal/src/interactive/bootstrap.js:49-74 sends STATIC_ASSETS once, at startup, and never again.
Reproduce
- Use the playground example "Interactive Instrument with Static Assets", changed so the
<img src="smiley.png">is inserted on a button click instead of being in the initial HTML. - Open it in
apps/webin Chrome. - Wait more than 30 s without interacting, or click "stop" for the worker under DevTools > Application > Service workers, which does the same as an idle termination. Then click the button.
Actual: the restarted worker has an empty staticAssets map, /runtime/v1/@opendatacapture/runtime-internal/interactive/smiley.png goes to the server, and the image is broken.
Expected: the asset is served however long the task has been running.
Tests
packages/runtime-internal/src/interactive/__tests__/worker.test.ts: it('should still serve registered assets after the worker script is re-evaluated, so an idle termination does not lose them'). Load the assets, call vi.resetModules() and re-import worker.js to simulate a restart, then fetch. This needs a stubbed caches (Cache Storage) in the test globals.
e2e, in testing/src/specs/instrument-completion.spec.ts: open an interactive instrument with static assets, stop its service worker through CDP (ServiceWorker.stopWorker), then trigger an asset request and assert it loads.
Suggested fix
Persist the assets where a restarted worker can read them. On STATIC_ASSETS, write each one as a Response into a named Cache Storage cache (caches.open(...)), and acknowledge only after the writes resolve. In fetch, respond from caches.match(pathname) and fall back to the network on a miss. Clear the cache whenever a new STATIC_ASSETS message arrives, so one instrument's assets are never served to the next.
- 主要言語
- TypeScript
- スター
- 119
- フォーク
- 19
- 平均マージ
- 6日 16分
- マージ済み PR(30日)
- 34
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
DouglasNeuroInformatics/OpenDataCapture のほかの issue
-
Area: Infrastructure Chore Difficulty: Low Priority: Medium
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
DouglasNeuroInformatics/OpenDataCapture#1835 ·
メンテナーはふだん 3 日以内に返信
-
Area: Instruments Bug Difficulty: Low Priority: Low
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
DouglasNeuroInformatics/OpenDataCapture#1824 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Area: Shared Bug Difficulty: Low Priority: Low
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
DouglasNeuroInformatics/OpenDataCapture#1813 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Multiple instructions show as one comma-joined paragraph ("questions., Conditional")対応中かも @Sanilas-ai が 5 日前に担当しました。 オープンArea: Shared Bug Difficulty: Low Good First Issue Priority: Low
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
DouglasNeuroInformatics/OpenDataCapture#1812 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
-
Area: Instruments Bug Difficulty: Low Priority: Low
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
DouglasNeuroInformatics/OpenDataCapture#1801 · コメント 1 件 ·
メンテナーはふだん 3 日以内に返信
DouglasNeuroInformatics/OpenDataCapture の issue をすべて見る
似ている issue
-
cloudflare-cache-binding: `unstorage://` keys are rejected by the Cache API, cache never storesオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 3 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 2 日以内に返信
-
reproduced
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
anomalyco/opencode#62052 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
strapi/design-system#2084 ·
メンテナーはふだん 3 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信