Failed batch evicts a replacement cache entry after clear/prime

オープン
#403 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

@Claire-ovo がすでに取り組んでいます。

2026年10月27日 から。

  • #404 @Claire-ovo による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
57/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
javascript, node.js
領域
backend, databases

調査の方向性

Start by reading failedDispatch() in the current source, then inspect the cache handling and tests for failed batches, clear() and prime(). Use the manual scheduler reproduction in the issue to confirm that an old rejection preserves a replacement cache entry while still allowing failed requests to retry. Done means the reproduction passes and custom cache maps, duplicate keys across batches, and normalized cache keys behave as described.

索引モデルが issue の本文から書いたものです。

説明

Expected Behavior

If a pending load is cleared and replaced with prime() (or another load()), failure of the old batch should reject its own requests without evicting the replacement cache entry. A failed request should still be evicted when the cache contains that request's promise, so subsequent loads can retry.

Current Behavior

With dataloader 2.2.3 on Node v22.23.1, an old batch failure clears the replacement entry. The reproduction below returns backend:a and makes two backend calls, instead of returning replacement with one backend call.

The same unconditional clear is present in failedDispatch() on current main, commit 65be452f5ffad3eede2d862dc26c96003fa87ef3. I inspected that source; the reproduction was run against the published 2.2.3 package.

Possible Solution

Retain the cache-promise identity associated with each queued request and only evict it if the current entry for the normalized cache key still belongs to that request. The batch's own rejection should remain unchanged. This needs to preserve ordinary failed-batch retries, custom cache maps, and duplicate keys across batches.

Steps to Reproduce

Install [email protected] and run this script with Node. It uses a manual batch scheduler and a controlled rejection, with no timing delays:

const assert = require('node:assert/strict');
const DataLoader = require('dataloader');

(async () => {
  let rejectOld;
  const firstBatch = new Promise((_, reject) => { rejectOld = reject; });
  let dispatch;
  let batches = 0;
  const loader = new DataLoader(keys => {
    batches++;
    return batches === 1 ? firstBatch : Promise.resolve(keys.map(k => `backend:${k}`));
  }, { batchScheduleFn: fn => { dispatch = fn; } });

  const old = loader.load('a').catch(error => error.message);
  dispatch();
  loader.clear('a').prime('a', 'replacement');
  rejectOld(new Error('old batch failed'));
  assert.equal(await old, 'old batch failed');

  const next = loader.load('a');
  dispatch();
  const value = await next;
  console.log({ value, batches }); // { value: 'backend:a', batches: 2 }
  assert.equal(value, 'replacement'); // Fails on 2.2.3.
  assert.equal(batches, 1);
})().catch(error => { console.error(error); process.exitCode = 1; });

Context

This was also reproduced in the Python port: https://github.com/syrusakbary/aiodataloader/issues/59, with a proposed fix at https://github.com/syrusakbary/aiodataloader/pull/60. Its maintainer requested an upstream report because the port aims to mirror DataLoader's behavior. The Python PR is still open; this report does not assume that its implementation can be copied directly to JavaScript.

Additional local diagnostics reproduce the eviction after a replacement load has completed (an unnecessary third backend batch), and with a normalized cache key. Controls with a successful old batch or a different primed key retain the replacement. This changes observable cache behavior, so the release/compatibility implications should be considered alongside the fix.

主要言語
JavaScript
スター
13.4k
フォーク
522
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

graphql/dataloader のほかの issue

graphql/dataloader の issue をすべて見る

似ている issue

JavaScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。