Failed batch evicts a replacement cache entry after clear/prime

未关闭
#403 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

@Claire-ovo 已经在做这个了。

开始于 2026年10月27日。

  • #404 来自 @Claire-ovo —— 未关闭

评估

难度
4/5
预计耗时
3-5 天
新手友好度
57/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
领域
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

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

graphql/dataloader 的其他 Issue

查看 graphql/dataloader 的全部 Issue

相似的 Issue

更多 JavaScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。