fix(plugin-sdk): bound live catalog cache expiry · openclaw/openclaw@4f0e3cb
steipete
·
2026-05-31
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -90,6 +90,31 @@ describe("provider-catalog-shared live catalog cache", () => {
|
90 | 90 | ).resolves.toBe("ok"); |
91 | 91 | expect(load).toHaveBeenCalledTimes(2); |
92 | 92 | }); |
| 93 | + |
| 94 | +it("does not cache live catalog loads when the expiry would exceed Date range", async () => { |
| 95 | +const load = vi |
| 96 | +.fn<() => Promise<string>>() |
| 97 | +.mockResolvedValueOnce("first") |
| 98 | +.mockResolvedValueOnce("second"); |
| 99 | + |
| 100 | +await expect( |
| 101 | +getCachedLiveCatalogValue({ |
| 102 | +keyParts: ["provider", "models", "overflow"], |
| 103 | + load, |
| 104 | +ttlMs: 1, |
| 105 | +now: () => 8_640_000_000_000_000, |
| 106 | +}), |
| 107 | +).resolves.toBe("first"); |
| 108 | +await expect( |
| 109 | +getCachedLiveCatalogValue({ |
| 110 | +keyParts: ["provider", "models", "overflow"], |
| 111 | + load, |
| 112 | +ttlMs: 1, |
| 113 | +now: () => 8_640_000_000_000_000, |
| 114 | +}), |
| 115 | +).resolves.toBe("second"); |
| 116 | +expect(load).toHaveBeenCalledTimes(2); |
| 117 | +}); |
93 | 118 | }); |
94 | 119 | |
95 | 120 | describe("provider-catalog-shared native streaming usage compat", () => { |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -15,6 +15,7 @@ import type {
|
15 | 15 | ModelCatalogModel, |
16 | 16 | ModelCatalogTieredCost, |
17 | 17 | } from "../model-catalog/types.js"; |
| 18 | +import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "../shared/number-coercion.js"; |
18 | 19 | import type { ModelProviderConfig } from "./provider-model-shared.js"; |
19 | 20 | |
20 | 21 | export type { ProviderCatalogContext, ProviderCatalogResult } from "../plugins/types.js"; |
@@ -51,18 +52,26 @@ export async function getCachedLiveCatalogValue<T>(params: {
|
51 | 52 | ttlMs?: number; |
52 | 53 | now?: () => number; |
53 | 54 | }): Promise<T> { |
54 | | -const now = params.now?.() ?? Date.now(); |
| 55 | +const rawNow = params.now?.() ?? Date.now(); |
| 56 | +const now = asDateTimestampMs(rawNow); |
55 | 57 | const ttlMs = params.ttlMs ?? 30_000; |
56 | 58 | const key = buildLiveCatalogCacheKey(params.keyParts); |
57 | 59 | const existing = liveCatalogCache.get(key) as LiveCatalogCacheEntry<T> | undefined; |
58 | | -if (existing && existing.expiresAt > now) { |
59 | | -return await existing.value; |
| 60 | +if (existing) { |
| 61 | +const expiresAt = asDateTimestampMs(existing.expiresAt); |
| 62 | +if (now !== undefined && expiresAt !== undefined && expiresAt > now) { |
| 63 | +return await existing.value; |
| 64 | +} |
| 65 | +liveCatalogCache.delete(key); |
60 | 66 | } |
61 | 67 | const value = params.load(); |
62 | | -liveCatalogCache.set(key, { |
63 | | -expiresAt: now + ttlMs, |
64 | | - value, |
65 | | -}); |
| 68 | +const expiresAt = resolveExpiresAtMsFromDurationMs(ttlMs, { nowMs: rawNow }); |
| 69 | +if (expiresAt !== undefined) { |
| 70 | +liveCatalogCache.set(key, { |
| 71 | + expiresAt, |
| 72 | + value, |
| 73 | +}); |
| 74 | +} |
66 | 75 | try { |
67 | 76 | return await value; |
68 | 77 | } catch (err) { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。