@dee-wan/cache

中文文档
2.2.0发布于 2026/11/04MITTypeScriptES Module构建来源已验证近 30 天下载 2049

Prisma 读取 Cloudflare 工人和 D1 的缓存, 由持久对象协调

中文使用文档
文档目录13 节
  1. 生成配置
  2. 把它接入一个工人
  3. 区域Prisma读取
  4. 选项
  5. 原始 SQL 写入
  6. 规划行为
  7. 运行时间要求
  8. 发展
  9. D1 有防守的Prisma 写出栅栏
  10. 明确授权如下:
  11. 区域读取缓存
  12. D1 书签客户端运输
  13. D1届会议

@dee-wan/ cache (英语)

Prisma 读取 Cloudflare 工人和 D1 的缓存 。 永久对象坐标无效, 填充锁 和缓存值。 默认值为检查协调员 。 可选区域条文允许有限度地僵化.

合同,包括每项无效规则和限制,均在 文件/合同。 。 。 .

生成配置

generator cache {
  provider = "dee-wan-cache-generator"
  output   = "../src/generated/cache"
  exclude  = ["AuditLog"]   // optional
}

/// @cache.skip
model Session {
  id String @id
}

运行 npx prisma generate (或运行 npm 脚本) prisma generate写作 cache-config.ts。 。 。 . 提供者名称解决通过 node_modules/.bin因此,Prisma二进制必须运行 npm PATH。 。 。 . 每个模型都可以缓存,除非它携带 /// @cache.skip 或列于 exclude读取 包括不缓存的选定退出模式。 更新此软件包后再生成: 扩展 拒绝其它格式的配置.

把它接入一个工人

import { PrismaD1 } from "@prisma/adapter-d1";
import { createCacheExtension } from "@dee-wan/cache";
import { createDurableObjectStore } from "@dee-wan/cache/cloudflare";
import { cacheConfig } from "./generated/cache/cache-config";
import { Prisma, PrismaClient } from "./generated/prisma";

export { CacheCoordinator } from "@dee-wan/cache/cloudflare";

export default {
  async fetch(request, env, ctx) {
    const prisma = new PrismaClient({ adapter: new PrismaD1(env.DB) }).$extends(
      createCacheExtension({
        config: cacheConfig,
        decimal: Prisma.Decimal,
        enabled: env.CACHE_ENABLED !== "false",
        generation: env.CACHE_GENERATION,
        scope: "public",
        store: createDurableObjectStore(env.CACHE_COORDINATOR, { name: "main-db" }),
        waitUntil: (promise) => ctx.waitUntil(promise),
      }),
    );
    // ...
  },
} satisfies ExportedHandler<Env>;
{
  "durable_objects": { "bindings": [{ "name": "CACHE_COORDINATOR", "class_name": "CacheCoordinator" }] },
  "migrations": [{ "tag": "cache-v1", "new_sqlite_classes": ["CacheCoordinator"] }]
}

Prisma运行的查询扩展按应用顺序排在最外端(在Prisma 6.19.3上核实). 在缓存前应用 prisma- guard 等按调用扩展 :

const client = base.$extends(guardFor(caller)).$extends(createCacheExtension({ ...options, scope }));

然后每读一读,包括点击率和重写论点(例如租户) filter)是缓存密钥的一部分. 在命中跳过缓存后应用的扩展名 。 使用 scope 任何调用者都会改变结果而不改变论据.

区域Prisma读取

createRegionalStore 将本地 Cloudflare Cache API 读取到同一协调商店 。 选择到 最多有5秒的数据被隔离 授权和警卫延期仍在运行.

import { createDurableObjectStore, createRegionalStore } from '@dee-wan/cache/cloudflare';

const name = 'main-db';
const generation = `${deploymentGeneration}:${cacheConfig.cacheVersion}`;
const store = createRegionalStore(createDurableObjectStore(env.CACHE_COORDINATOR, { name }), {
  namespace: env.CACHE_COORDINATOR.idFromName(name).toString(),
  generation,
  ttlMs: 5000,
  waitUntil: promise => ctx.waitUntil(promise),
});
const extension = createCacheExtension({
  config: cacheConfig,
  store,
  coordinationGeneration: generation,
  scope: callerScope,
  decimal: Prisma.Decimal,
  waitUntil: promise => ctx.waitUntil(promise),
});

保持命名空间稳定 跨来电者和作家。 它确定一个协调员和数据库,而不是 用户。 保持呼叫权限 scope。 。 。 . coordinationGeneration 必须匹配包装的一代. 接受和协调员的点击加上已知的新最后期限可以输入区域条目。 他们 寿命从不超过源新鲜度的最后期限。 仍未完成的旧/海关商店 工作,但他们的点击率没有覆盖区域条目。 刷新符号从不重复区域播放 . 与 waitUntil后半期区域租约的点击率 背景情况。 续作每把按键被分解并保持相同的新鲜度. 读取/释放 等待被限制; 超时后释放后锁. 续约失败允许再次尝试 而不延迟前景命中;已过期的条目仍然使用协调器. 本地突变阻断了旧的读取和填充. 按顺序共享写符的操作; 排队操作保持栅栏,直到实际的协调员呼叫得到解决,包括在呼叫后 暂停 。 跨同位素变化在区域租约内趋同. 区域读取屏蔽。 与 waitUntil,后面读取在有限制的背景通行证中重试协调员。 只恢复缓存 在承认后, 永远不要仅仅因为时间流逝。 追踪失败溢出或再利用 未解决的写入失败令牌使隔离禁用 . 缓存 API 失败使用协调器; 协调员读取失败使用原始数据库路径.

生成的后端使用此包装并 createResponseWarmup 从同一个入口。 他们暖和 以当前呼叫者的资质,通过正常的授权,设定了边界生成的GET路由. 发热是最好的努力;未知的查询变体和先行请求可以保持冷. 写作和认证 裁决不缓存。 取暖读取的目标并不是所有网络请求的暂时性保证.

选项

无效的选项扔出 a TypeError 在建筑.

选项默认含义
config—— 说生成相克.
store—— 说createDurableObjectStore(namespace, { name, attempts?, locationHint? })。 。 。 .
decimal无Prisma.Decimal当方案有十进制字段时需要.
enabledtruefalse:读写跳过协调员. $cacheInvalidate 仍然叫着它.
scope""每把钥匙的一部分.
generation无1.256 chars, 与协调员有联系的每个工人都一样。 更改它会使每个条目都失效一次 .
excludeModels[]在生成的配置上运行时间选择退出 .
shape新鲜3600 s,负600 s,软比0.8{ default, byModel }. TTL必须最多为28,747,636 s.
waitUntil无启用软 TTL 后刷新 .
leaseMs60 000 个写作租赁,最多60万.
lockMs3万块最多30万个.
fillPollDelaysMs20,40,80,160,320,640 (英语)等待时另一个请求会填充相同的密钥 。 持卡人持锁时间超过整个预算后,读者停止等待.
maxValueBytes150000 (150000) (韩语)提供了更大的结果,但没有缓存。 最多为1900.
onError无接收协调器, 序列化和写出错误 .

createDurableObjectStore(namespace, { name, attempts, locationHint })数字 :

  • name (需要)识别D1数据库. 密钥不包括数据库, 所以有两个数据库 共享一个协调员名称将共享缓存行 。 每个数据库使用一个名字.
  • attempts (默认 3, 最多为 10) 是针对可重试协调器错误的尝试总数 开始,结束和无效.
  • locationHint (单位:千美元)wnam, (中文(简体) ), enam, (中文(简体) ), sam, (中文(简体) ), weur, (中文(简体) ), eeur, (中文(简体) ), apac, (中文(简体) ), oc, (中文(简体) ), afr, (中文(简体) ), me将 第一创作协调员,尽最大努力.

原始 SQL 写入

Raw SQL 不通过扩展. 包起来:

await prisma.$cacheRawWrite({ models: ["Post"] }, () => env.DB.prepare("UPDATE Post SET ...").run());
await prisma.$cacheInvalidate({ entities: [{ model: "Post", pk: [42] }] });
await prisma.$cacheInvalidate({ all: true });

通过外国密钥提及目标的模式也被作废. 未知的模型名称丢出 .

规划行为

  • 读取器无法到达:读取到D1,没有被缓存.
  • 无法接触或在写作前超载的协调员: CacheUnavailableError 被抛出并写下 不运行。 缓存读取和写取共享一个协调器,因此重读负载可以拒绝写取.
  • 写作时 enabled: false 没有跟踪。 变动 generation 当缓存转回时 打开或呼叫 $cacheInvalidate({ all: true })。从不一起运行禁用版本和启用版本.
  • 一个新的计划或软件包版本会使第一次接触时的每个条目无效. 不同工人 绑定在一个协调员身上的版本,在其中一个版本保留之前,一直相互无效.
  • 回滚到发布会 与一个年长的协调员 存储计划 使得每写失败 CacheUnavailableError前进.
  • 批次内读取 $transaction([...]) 未缓存。 Prisma 的 D1 适配器拒绝交互 交易.
  • 通过D1读取 withSession 不支持复制件 .
  • 一个协调员的持久目标有1 000个每秒请求的软限制。 测量 2026-09-17 来自一个客户端:约1,030个缓存每秒读取21ms p50,没有出错,对: 约340每秒215米直接读取D1. 高比率没有计量.
  • 每名协调员打一通电话、一通失事、二通失事、七通费用; 每个书写需要2个,加上复写。 关于"工人自由计划", 要求让许多普里斯玛打电话 可以达到子请求限制(参见合同"Cost per Prisma call").
  • 每个给模型的书写都会使模型的缓存列表,计数和关系读取无效.
  • 缓存条目上限为每名协调员1GiB;最接近到期的条目被先被拆出.
  • 每个被缓存的读物都会到一个协调员地点进行往返。 从亚洲测量 2026-09-17:击出8-14分 协调员在 apac 和171至210毫秒,装入 weur慢点 而不是直接读取附近的D1(48–103 ms). 将协奏器放置在大部分流量附近 locationHint;远离它的用户读取速度比没有缓存要慢.

运行时间要求

  • Cloudflare 工人有一个 SQLite 支持的持久对象和 D1. 核心条目和Cloudflare条目不需要 nodejs_compat; 工人导入 @dee-wan/cache/d1 这需要它.
  • Prisma 6.19.3 或较新的 6.x 与 @prisma/adapter-d1 (以6.19.3测试).
  • 发电机:节点20或更新(CI运行于20,22和24日). Wrangler 4和Miniflare需要22号节点.

发展

npm run build
npm run lint
npm run typecheck        # builds, generates the test client, then checks src and tests
npm run test:unit        # Node 22.5+ (node:sqlite)
npm run test:workerd
npm run test:consumer    # packs, installs into a fresh Worker project, runs it on workerd

所部署的烟雾(仅在可支配账户上使用;测试工人对持有的呼叫者任意使用SQL) 符号 :

npm run test:prepare
npx wrangler d1 create <name>                       # put the id into a copy of test/deployed/wrangler.example.jsonc
npx wrangler d1 execute <name> --remote --file test/workerd/.build/schema.sql
npx wrangler deploy -c <copy> --var SMOKE_TOKEN:<random>
CACHE_SMOKE_URL=https://<worker> CACHE_SMOKE_TOKEN=<random> npm run test:deployed
npx wrangler delete --name <worker> && npx wrangler d1 delete <name>

test/workerd/.build/schema.sql 作者为 npm run test:workerd。 。 。 .

D1 有防守的Prisma 写出栅栏

@dee-wan/cache/d1 出口 cacheD1Env, (中文(简体) ), wrapD1Handler, (中文(简体) ), createD1CacheRuntime, (中文(简体) ), d1PrismaCacheExtension,以及 fenceD1Writes消费者提供 D1CacheProfile 带有环境前缀,D1绑定名称和前缀,协调对象名前缀, 普里斯马 readModels,并明确证明 unfencedWriteTables编辑器 通行证直接通过和栅栏 原始D1写,包括批发,执行,和 届会。 未知或模棱两可的文字使用全球围栏。 仅在 它的图案证明它的写作不能通过触发或级联来改变被缓存的数据.

环绕每一个可以触摸到协调器的获取、 预定处理器和单独的写入器 D1数据库. 应用 d1PrismaCacheExtension 只有在获得客户授权后,才给予客户 扩展范围。 当缓存或缓存读取时, 运行时间返回不扩展 开始 独立控制和认证客户端应当保持畅通无阻. @dee-wan/cache/d1/config 验证工人绑定、数据库身份地图和配对 编剧,并提供通用编剧配置编辑. 消费者必须提供真正的D1 UUIDs,从不绑定对象身份.

coordinationGeneration 让 Prisma 扩展共享字面协调器生成 升级时使用生-D1写出栅栏. 如果省略,则从现有规划/配置中得出 协调员的产生保持不变。 Prisma 缓存密钥中总是包含规划器和 生成配置版本。 不将各代协调者混为一谈 推出后,必须让每个作者在允许缓存读取之前参与。 外部 D1 写入 不被截取: 酌情禁用已缓存的读取和写作, 然后使用新鲜的 重现前的刻画.

该套装的Prisma对等支持仍为Prisma 6.19.3和后6.x. D1 写入适配器 独立于 Prisma; 其他 Prisma 版本尚未被此软件包验证 .

明确授权如下:

d1CacheEpoch(database) 返回一个不透明的数据库身份命名空间, 生成和全球写作时代。 在读取该数据库之前抓取该数据库并包含 每个依赖者都会在外部缓存密钥中捕获命名空间. 错过了时间, 禁用读取, 等待写入或协调器失败返回 null; 绕出外部 缓存读取并填入此选项 。 旧的飞行中填充物保留了旧的取名空间. 这不授权请求或取消下游浏览器缓存.

cacheD1Read(database, { key, scope, dependencies, ttlMs, cacheable }, load) 缓存 a 明确选择在呼叫者完成授权后阅读。 包含全文 演员、网站、当前权限和所有查询输入 scope 财务报告和审定财务报表 key列表中 装入器在 dependencies。帮助者检查每个独特的 装订全球栅栏在检查前,包括它的一代和关键时代,以及 再检查一次,然后给一个击中或存储一个填充。 未知运行时间的待写, 较旧的协调员、 检查失败或禁用读取会绕过缓存 。 默认 TTL 30秒,最多5分钟。 值和密钥为边框; 不支持 对象绕行缓存。 日期、大字节和字节数组使用现有的值编码器.

cacheD1JsonRead(database, { key, scope, dependencies, ttlMs, request, buffered: true }, load) 被调用者知道JSON是缓冲器, 它会保持 错失时的原始响应,并保留了命中时的响应头. 条件、范围、, 预览和能力请求、错误答复、饼干、下载、不安全 Vary, (中文(简体) ), 编码后的尸体和体型过大的尸体绕行了缓冲. 无 buffered: true,回应 绕行;从不为流设置. 反应缓冲是字节并有时间限制的. 这些帮助者使用私人持久对象存储,而不是公共缓存 API.

对于本地 Prisma 读取, 也取决于另一个 D1 数据库, 使用 withD1PrismaCache(client, database, config, { scope, dependencies }) 打电话后 警卫 范围必须包括完整的行为者、网站和许可背景。 业务 键包括依赖时间并重新检查点击率的依赖性。 最初的三论 形式保留其现有行为。 所有参与的作家必须用同样的栅栏 物理数据库协调员.

D1协调员的电话每次有2秒钟的截止日期。 失败时读取回 D1 ; 写入需要成功的开始 。 失败的结束保存数据库结果并保存 租赁保守派 晚起后和读取锁在和解后被清理.

keyArgs 可选地将参数读取为缓存键身份。 保留这个身份中所有改变结果的输入. 执行和无效使用原始参数. 回调错误绕过缓存 .

区域读取缓存

cacheD1Read 范围 d1PrismaCacheExtension 编号 : withD1PrismaCache 接受 regionalTtlMs 从0到5000。 默认为0(严格协调). 一个正值选择在本地 Cloudflare Cache API 中产生有边框的 Stale ; 其它作者的更改可能不会在最长的间隔内被忽略 。 严格读取使用 0 。 Cache API 失败回到了严格的路径. 此选项缓存值, 而不是 HTTP 响应 .

关键内容包括数据库和协调员身份、世代、范围和查询身份. regionalModels 可选择限制 Prisma 区域读取其根和所有相关模型被列出的查询。 呼叫者必须提供一个范围,将影响结果的每一个授权背景分开. keyArgs 必须保留每个改变结果的论点。 习惯 createD1CacheRuntime 提供稳定、独特的 regionalIdentity 每名协调员;没有一位协调员,则绕过区域层.

cacheRegionalResponse(request, { namespace, ttlMs, waitUntil? }, load) 是一个选择进入的区域缓存 匿名公众Get JSON 响应。 使用稳定的部署/版本命名空间和不超过5000毫秒的TTL. 证书、预览、有条件和缓存通道请求到达 load仅明确公开作出正面反应 s-maxage 资格。 浏览器的响应需要重新验证;内部过期自启动起仍受限制 load。缓存 API 错误返回到 load。呼叫者必须将此仅适用于公共线路,并且必须在请求或命名空间中包括所有响应-不同请求输入.

wrapD1ReadResponseLease(handler, profile) 从 @dee-wan/cache/d1/response-lease 可选择的再利用认证得到回复。 设定 readResponseLease.maxSeconds 从1起至300起(违约5起),并明确设定 <PREFIX>_READ_ACCESS_SECONDS 从 1 到该最大值( 默认 0) 。 把它包进去 wrapD1Handler. JSON 响应机构在填充时被验证,最多可有8,000,000活字节;在不解码和保存客户端头的情况下点击缓存机构流. 普通区域读取值仍以1 500 000字节为上限。 配置文件提供数据库绑定,部署环境变量,被认可路径,证书和变化头,以及新鲜-cookie名. A 类 * 路径段匹配一个非空段。 密钥包括完整请求的 URL, 配置的证书和不同的标题, 配置, 释放, 以及配置的 D1 身份 。 可选 cookieNames 为密钥选择对大小写敏感的 cookie 名称, 同时保留每次发生及其顺序; 它需要 cookie 内 credentialHeaders 在生成模式中, 列表中的新鲜度饼干。 包含用于认证或响应变异的每个饼干. 没有它,就会使用完整的 Cookie 头条. bypassQueryParams 可选地列出绕过租赁的精确查询密钥. ignoreRequestCacheControl 浏览器发送时可选择允许租赁点击 no-cache 或者说 no-store; 默认为假. 设定 refreshAheadSeconds 到整数从 0 到 0 maxSeconds (缺省0)在背景中刷新有效租赁,即将到期 waitUntil 已提供。 当窗口超过活动租赁期限时,刷新前端被禁用 。 命中值保持即时状态,每把密钥在隔离区重新聚集。 成功的新鲜、经授权的反应将产生新的有限度的租约;失败的刷新使旧的到期不变。 一个配置 freshnessHeader 强制读取源。 符合条件的成功反应取代了普通租约;不安全反应不能取代租约。 过期仍受新的源请求和授权/数据最后期限的限制。 配置每个证书和响应变化头 。 工人需要 nodejs_compat。 。 。 .

成功认证后, 拨打 limitD1ReadLeaseUntil 与证书的绝对过期 以时间为毫秒。 缺少、未确定或已过期的最后期限,无法填补。 来源收到 Cache-Control: no-cache 租借失败。 成功的突变设置了 HttpOnly 新鲜的饼干,用于配置的最大值 。 默认 bypass 模式,请求携带它绕过租赁。 可选 freshnessCookieMode: 'generation' 需求 cookie 内 credentialHeaders:每个突变产生新的饼干值,其第一次读取时使用新数据后,反应才能被再用. 遗留或无效的标记仍然绕行. 一个再利用的区域查询值在该值的原始到期时上限响应租赁;一个新的源负载不会被查询-cache TTL所上限. freshnessCookieExcludedPaths 可选地将已知的非移动路径从此 cookie 中排除,使用相同的整块路径匹配。 在有效的租赁中, 匹配 If-None-Match 或者说 If-Modified-Since 返回无体 304; If-None-Match 以优先为准。 其他先决条件和范围到达处理者。 除了无体的304以外,客户反应头没有改变。 写总是执行处理器。 其他行为者的授权变更可延续到租赁期,对缓存的读物生效.

响应-租赁和区域 D1 缓存检查最多等待100 ms;超时使用误差. 前景寒冷读取最多100 ms等待相同的密钥,然后可以替换被停滞的主人. 前场失事可以立即替换出一个背景温暖的主人. 开始的旧缓存在替换填充前完成 .

内部温暖的读取和背景刷新了一次绑定的JSON,然后重放这些字节用于缓存填充和发现. 前景反应持续流出.

当认证运行在一个单独的可信服务绑定中时, 将服务处理器包入 wrapD1ReadLeaseOrigin(handler) 和使用情况 forwardD1ReadLease(request, service) 在网关租赁处理器内。 原产地包提供了请求- 本地截止范围 。 转发方只将已核实的最后期限转移至装订后,在回复前取出其内部头条. 一个网关必须信任绑定的服务来验证证书并保护这个内部证据.

浏览器客户端可以导入 createReadFreshness(policy) 从 @dee-wan/cache/client 使用相同的 readResponseLease 政策。 打电话 observe(scope, method, url, transport?) 成功响应后,然后合并 headers(scope, method) 输入请求。 使用生成模式,通过请求源、基址和 withCredentials: true 将饼干用于确认的同源写作;其他运输工具则保持新发头倒置。 数据突变可以使每个范围配置的最大值有新的 GET 头; 排除路径使用与服务器相同的整块规则 .

对于没有D1协调的应用程序,导入 wrapReadResponseLease 财务报告和审定财务报表 limitReadResponseLeaseUntil 从 @dee-wan/cache/response-lease。通过处理器和一个包含稳定非空的选项对象 namespace, (中文(简体) ), deployment,以及 database 身份, 活动 seconds 价值,以及上述相同的响应-租赁政策领域(不包括 databaseBinding 财务报告和审定财务报表 deploymentEnv) (中文(简体) ). 认证后, 拨打 limitReadResponseLeaseUntil 与实际的证书过期时的相差相差数以毫秒; 没有未来的最后期限, 无法存储回复。 当部署或基础数据源发生变化时,身份必须改变。 本条目使用缓存 API 存储,不需要 D1 运行时间或持久对象 。 这需要工人 nodejs_compat (c) 请求-当地截止日期范围。 可选 wrapReadResponseLeaseOrigin 财务报告和审定财务报表 forwardReadLease 支持与 D1 适配器相同的可信服务约束截止日期运输.

独立反应租赁接受可选 warmup 政策。 与一个 waitUntil 上下文中,它从背景开始,在符合条件的缓存命中或成功的 JSON 源响应以及未来的授权期限后读取。 第一位冷小姐仍然到达源头. 在任何需要的瞄准镜后,用 scope: null 先运行,然后学习目标, 在普通种子之前。 配置 scopeHeader 内 varyHeaders; 如果缺少温度, 则取消温度。 例如,将这些字段添加到独立的租赁选项中:

{
  varyHeaders: ['x-scope-id'],
  warmup: {
    scopeHeader: 'x-scope-id',
    seeds: ['/api/context', '/api/items'],
    discoverScopeFrom: '/api/context',
    discover: (url, body) => {
      if (url.pathname === '/api/context' && body && typeof body === 'object' && 'scope' in body && typeof body.scope === 'string') {
        return { scope: body.scope, targets: ['/api/items/recent'] };
      }
      return { targets: [] };
    },
    portable: (url) => url.pathname === '/api/items/recent',
  },
}

seeds 和发现的目标必须是租赁路径和查询政策所承认来源相同的URL. 一个终端 ** 路径段匹配后人; * 仍然匹配一个非空段。 导入 matchesReadResponsePath 从 @dee-wan/cache/response-lease 在调用者政策中应用相同的路径。 发现可能在原始请求没有范围标题时提供范围. 设定 discoverScopeFrom (c) 其余目标等待其授权的响应和有效范围。 如果发现范围失败,则批量停止。 当范围已经知道时,范围种子作为普通的去迭代种子运行. 运行时要考虑目标预算 此选项需要 discover 和条目 seeds只标记一个 URL portable 当它的路径和查询没有包含任何秘密,并且在该范围内可以安全分享时;默认是虚假的。 区域目录只存储可移植的URL,大致数和时间,而不是证书或反应机构. 缓存的回复仍按现有演员资格和不同标题键。 区域缓存 API 更新是相近的, 可能会有比赛 .

用于每件有信誉的多范围变暖 catalogScope: 'credential'。边框目录按键为已配置的证书和不同标题,但 scopeHeader,加上租赁身份。 它按其合并的URL计数排序范围,再按计数排序URL. 使用 { url, scope } 内 seeds 或发现目标,将瞄准标头设为1; scope: null 将取去. 字符串目标使用当前范围. 任选第三项 discover 参数包含触发请求 scope (或用靴子解决的范围) popularScopes 从证书目录。 设定 discoveryPriority: 'next' 以排队的冷种子为前期目标, 被发现的目标保持了发现顺序;在能力上可以替换排队的冷种子,而不是更早的发现. 他们仍然有同样的预算目标。 每个反应仍然使用普通的证书和范围租赁钥匙和授权。 瞄准镜头不得同时是证书头. 仅 portable URL输入目录. 目录认证身份省略了新鲜度饼干,所以所学的受欢迎能活下来;反应键和批组保留了那块饼干.

D1,通过 { warmup } 作为可选的第三个参数 wrapD1ReadResponseLease; 保持可序列化的配置文件 .

默认为每批48个目标,所有热量批次的4个同时请求以一个包装,25秒的最后期限包括档等,每个范围32个目录条目,24小时TTL. 默认的30秒冷却从批量截止日期后开始. 已完成的批次保留了它的冷却;未完成的被废弃的批次释放出自己的冷却,以便下一个合格的前地读取可以再试取. 在冷却期间,符合条件的前台访问仍然更新了受欢迎程度,但不会再开始另一批. 以 maxTargets, (中文(简体) ), concurrency, (中文(简体) ), maxMilliseconds, (中文(简体) ), maxEntries, (中文(简体) ), catalogTtlMs,以及 cooldownMs. 已排队的暖源呼叫向主动前地Get处理器屈服. 温暖使用来电者的资质和普通租赁授权. 温暖读取不会引发更多批次或受欢迎的更新. 可选纯度 isCurrent() 当包装器配置退出时调回错误; 排队和运行工作检查并停止, 后批不开始 。 外部写成功 freshnessCookieExcludedPaths 取消排队工作,并阻止更老的前地读取在目前隔离范围内填充租约或开始一批;新鲜度世代保留后续反应租约。 被排除的存在,草稿和预览操作使温暖分批运行. 缓存或取暖失败不会改变前景反应.

createMutationInvalidation(policy) 从 @dee-wan/cache/client 信号在听众和浏览器标签之间成功写入。 打电话 publish(scope, method, url) 成功后和 subscribe(scope, listener) 待收款项 { scope, method, pathname }; 调用返回的函数以取消订阅 dispose() 当完成。 URL的查询和证书没有发送. 使用无证书范围 。 阅读方法和 freshnessCookieExcludedPaths 被忽略。 该频道仅在工厂在浏览器中运行时才打开.

createRevalidationWindow(intervalMs, now?) 每个瞄准镜自动检查. remaining(scope) (一) 规定一个期限,但以后不提出; take(scope) 允许在最后期限之前或之后立即有未初始化的范围并初始化的范围。 变异通知仍然立即发出,不使用这个窗口.

createSingleFlight<Key, Value>() 同时分享 run(key, load) 打电话 已完成和失败的电话被删除; forget(key) 允许在旧电话仍在运行时使用新电话.

createIntentWarmup(cooldownMs?, now?) 温暖读取导航意图,而不存储响应值。 打电话 setScope(siteAndActor) 使用前和 warm(key, async isCurrent => ...) 在鼠标徘徊或键盘焦点上。 一项任务正在进行;只有最新的等待意图。 检查 isCurrent() 在顺序读取之间。 成功的任务默认冷却60秒. 范围变化和 invalidate() 清晰的等待任务和冷却;旧的完成不能温暖新的范围。 使用与普通读取相同的 URL, 证书和信头的无声, 有边框, 只读请求 。 不将结果输入活动编辑器存储或启动启动扇形.

cacheReadValue 从 @dee-wan/cache/scoped-read 提供缓存 API 值缓存,而不包含 D1 或持久对象。 递出一个非空的 namespace,结构化 key,则a validate 带有源装入器的类型守护。 在密钥中包含每个授权和结果差异范围; 不将证书放入缓存值 . ttlMs 默认为 5000; 除非 maxTtlMs 明确提高限额(最高可达30万). maxBytes 默认为1,500,000,并且可以降低。 可选 cache 财务报告和审定财务报表 now 允许提供缓存 API 执行和时钟。 缓存失败、 无效值和过期的条目返回加载器; 加载器错误被传播 。 满载器运行前即为过期. 可选 refresh: { aheadMs, waitUntil, load } 在背景中刷新符合条件的命中,而不扩展现有条目;成功的重载从开始就收到一个新的TTL.

刷新加载器:读取新源;关闭已丢弃的响应机构. 保存失败或无效刷新 旧的过期。 同时更新每个密钥和缓存的去dupe 。 前景错失使老一点失效 刷新; 已启动的刷新在更新前完成 .

D1 书签客户端运输

可以设置有界点的 UI advanceOn: 'mutations-and-fresh-reads', (中文(简体) ), freshnessHeader 和可选 excludedPaths普通人不会推进 存储的地板。 成功的突变方法反应 和明确的新鲜得到做. 非GET/HEAD/OPTIONS方法保守地计算,包括只读的POST. 被排除的平时道路不会推进它. 每一个请求仍然发送存储和 电话供应楼层。 保持乐观调节和审校检查. 放弃这个选项,保留每个响应中的进步.

createD1BookmarkFetch(fetch) 将抓取执行包裹并记住有效 X-Dee-Wan-D1-Bookmarks 响应头。 以后的请求最多 每个物理数据库都看到书签。 每个独立创建一包 客户端上下文。 书签地图以64个数据库UUID和8192为界 字符; 无效的地图被忽略 。 过 { storage } 作为继续使用原生地图的第二个论据 getItem编号 :setItem 存储诸如会话Storage。 存储出错倒回内存.

D1届会议

云花板工人进口 @dee-wan/cache/d1 要求 nodejs_compat 兼容旗,包括D1会话未启用时.

环绕 HTTP 处理器 wrapD1ReadSessionHandler(handler, options) 外部 wrapD1Handler设置 bindingNames, (中文(简体) ), bindingPrefixes, (中文(简体) ), databaseIdsEnv,以及 可选择 primaryBindings, (中文(简体) ), freshnessHeader,以及 ignoreRequestCacheControl。命名的环境变量包含一个 JSON 从每个已配置的绑定名称到其物理 D1 UUID 的映射。 约束 共享 UUID 共享请求会话。 如果变量不存在, 绑定会保留 他们的原始行为。 无效的地图失败配置; 无效的书签 信头返回 HTTP 400.

对于可再使用的 Prisma D1 适配器,通过 prismaD1SessionDatabase(database) 改为 PrismaD1 并运行每个 Prisma 操作通过 runD1SessionOperation(database, operation),包括计划业务. 在同一物理数据库中,录用最多等待30秒,以进行更早的操作。 应用 sessionD1Env(env, options) 在缓存包装预定绑定之前 这些手术都使用同样的外观。 普通D1呼叫使用常规 装订。 允许和曝光 X-Dee-Wan-D1-Bookmarks 在 CORS 配置中,浏览器客户端需要它. D1缓存源填补从主端开始;缓存点击再利用源书签. 常规 Prisma 缓存必须设置 sessionCache: d1SessionCacheHooks(database)。在发送流式响应信头后启动的查询无法推进这些信头。 WebSocket 升级绕行会话.

版本与发布记录

@dee-wan/cache 共发布 12 个版本,首次发布于 2026/09/21;过去 12 个月发布了 12 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.2.0latest2026/11/0410 天前
2.1.12026/11/0410 天前
2.1.02026/11/0311 天前
2.0.62026/11/0311 天前
2.0.52026/11/0311 天前
2.0.42026/11/0311 天前

关于 @dee-wan/cache 的常见问题

@dee-wan/cache 是什么?

Prisma 读取 Cloudflare 工人和 D1 的缓存, 由持久对象协调

如何安装 @dee-wan/cache?

在项目目录运行 npm install @dee-wan/cache,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 dee-wan-cache-generator,可以用 npx dee-wan-cache-generator 直接运行。

@dee-wan/cache 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dee-wan/cache 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@dee-wan/cache 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dee-wan/cache 可以商用吗?

@dee-wan/cache 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dee-wan/cache 的下载量有多少?

根据 npm 官方下载统计,@dee-wan/cache 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,049 次,日均约 68 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dee-wan/cache 还在维护吗?

最新版本 2.2.0 发布于 2026/11/04(10 天前);至今共发布 12 个版本,其中过去 12 个月发布了 12 个;首次发布于 2026/09/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。