Skip to content

Commit babe038

Browse files
rockyshi1993Copilot
andcommitted
refactor(cache): 统一所有内部缓存到 cache-hub MemoryCache
- function-cache: in-flight Map 改为 per-call MemoryCache 实例(修正跨调用 key 冲突) - find-page: _asyncTotalsCache Map 改为 MemoryCache({ maxEntries: 10_000 }) - runtime-core: _iidCache / _modelInstances 从 Map 改为 MemoryCache - 联动更新 runtime-db-facade / runtime-admin-bridge / runtime-compat-accessors / types/internal/runtime - memory-cache: 新增 has() 兼容方法(委托 exists()) - 新增 cache-refactor-guard.test.js 回归守卫(4 项) - verify:full 通过(lint + type-check + tests + examples + server-matrix) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5bde8e5 commit babe038

12 files changed

Lines changed: 253 additions & 160 deletions

File tree

‎index.mjs‎

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ var MemoryCache = class _MemoryCache {
4848
exists(key) {
4949
return this._hub.exists(key);
5050
}
51+
has(key) {
52+
return this.exists(key);
53+
}
5154
getMany(keys) {
5255
const output = {};
5356
for (const key of keys) {
@@ -5083,7 +5086,10 @@ function mergeFilters(base, extra) {
50835086
}
50845087
return { $and: [base, extra] };
50855088
}
5086-
var _asyncTotalsCache = /* @__PURE__ */ new Map();
5089+
var _asyncTotalsCache = new MemoryCache({
5090+
maxEntries: 1e4,
5091+
enableStats: false
5092+
});
50875093
async function computeTotals(coll, query, limit, totals) {
50885094
const mode = totals.mode ?? "sync";
50895095
if (mode === "sync") {
@@ -5101,8 +5107,9 @@ async function computeTotals(coll, query, limit, totals) {
51015107
if (mode === "async") {
51025108
const cacheKey = JSON.stringify({ q: query });
51035109
const token = Buffer.from(cacheKey).toString("base64url");
5104-
if (_asyncTotalsCache.has(cacheKey)) {
5105-
return { mode: "async", total: _asyncTotalsCache.get(cacheKey), token };
5110+
const cachedTotal = _asyncTotalsCache.get(cacheKey);
5111+
if (cachedTotal !== void 0) {
5112+
return { mode: "async", total: cachedTotal, token };
51065113
}
51075114
setImmediate(async () => {
51085115
try {
@@ -6962,7 +6969,10 @@ function createRuntimeAccessors(config) {
69626969
throw error;
69636970
}
69646971
if (!config.getIidCache()) {
6965-
config.setIidCache(/* @__PURE__ */ new Map());
6972+
config.setIidCache(new MemoryCache({
6973+
maxEntries: 1e5,
6974+
enableStats: false
6975+
}));
69666976
}
69676977
return config.defaultDb.collection(name);
69686978
},
@@ -7074,7 +7084,10 @@ function getRuntimeDatabaseName(value) {
70747084
function getCompatModelInstanceCache(value) {
70757085
const record = asRuntimeCompatRecord(value);
70767086
if (!record._modelInstances) {
7077-
record._modelInstances = /* @__PURE__ */ new Map();
7087+
record._modelInstances = new MemoryCache({
7088+
maxEntries: 1e5,
7089+
enableStats: false
7090+
});
70787091
}
70797092
return record._modelInstances;
70807093
}
@@ -8757,7 +8770,6 @@ function resolveScopedCollection(config) {
87578770

87588771
// src/capabilities/function-cache/index.ts
87598772
import { createHash as createHash3 } from "node:crypto";
8760-
var inflightFunctions = /* @__PURE__ */ new Map();
87618773
function withCache(fn, options = {}) {
87628774
if (typeof fn !== "function") {
87638775
throw createError(ErrorCodes.INVALID_ARGUMENT, "withCache: fn must be a function.");
@@ -8789,6 +8801,10 @@ function withCache(fn, options = {}) {
87898801
calls: 0,
87908802
totalTime: 0
87918803
};
8804+
const inflightCache = new MemoryCache({
8805+
maxEntries: 1e4,
8806+
enableStats: false
8807+
});
87928808
const wrapped = (async (...args) => {
87938809
const startedAt = Date.now();
87948810
let cacheKey;
@@ -8820,8 +8836,8 @@ function withCache(fn, options = {}) {
88208836
stats.errors += 1;
88218837
}
88228838
}
8823-
if (inflightFunctions.has(cacheKey)) {
8824-
const pending = inflightFunctions.get(cacheKey);
8839+
const pending = inflightCache.get(cacheKey);
8840+
if (pending) {
88258841
const result = await pending;
88268842
if (enableStats) {
88278843
stats.hits += 1;
@@ -8851,10 +8867,10 @@ function withCache(fn, options = {}) {
88518867
}
88528868
return result;
88538869
} finally {
8854-
inflightFunctions.delete(cacheKey);
8870+
inflightCache.delete(cacheKey);
88558871
}
88568872
})();
8857-
inflightFunctions.set(cacheKey, runner);
8873+
inflightCache.set(cacheKey, runner);
88588874
try {
88598875
const result = await runner;
88608876
if (enableStats) {
@@ -8935,14 +8951,11 @@ var FunctionCache = class {
89358951
if (options && typeof options !== "object") {
89368952
throw new Error("options must be an object");
89378953
}
8938-
const cachedFn = withCache(fn, {
8939-
...options,
8940-
cache: options.cache ?? this.cache,
8941-
namespace: `${this.options.namespace ?? "action"}:${name}`,
8942-
ttl: options.ttl ?? this.options.defaultTTL ?? 6e4,
8943-
enableStats: options.enableStats ?? this.options.enableStats ?? true
8954+
this.functions.set(name, {
8955+
source: fn,
8956+
options,
8957+
cached: this.createCachedFunction(name, fn, options)
89448958
});
8945-
this.functions.set(name, cachedFn);
89468959
}
89478960
/**
89488961
* Execute a registered function.
@@ -8954,11 +8967,11 @@ var FunctionCache = class {
89548967
* @since v1.3.0
89558968
*/
89568969
async execute(name, ...args) {
8957-
const fn = this.functions.get(name);
8958-
if (!fn) {
8970+
const entry = this.functions.get(name);
8971+
if (!entry) {
89598972
throw createError("FUNCTION_NOT_REGISTERED", `Function not registered: ${name}`);
89608973
}
8961-
return fn(...args);
8974+
return entry.cached(...args);
89628975
}
89638976
/**
89648977
* Invalidate the cached result for a registered function under the given arguments.
@@ -8973,11 +8986,11 @@ var FunctionCache = class {
89738986
if (!name || typeof name !== "string") {
89748987
throw new Error("Function name must be a non-empty string");
89758988
}
8976-
const fn = this.functions.get(name);
8977-
if (!fn) {
8989+
const entry = this.functions.get(name);
8990+
if (!entry) {
89788991
throw createError("FUNCTION_NOT_REGISTERED", `Function not registered: ${name}`);
89798992
}
8980-
return fn.invalidate(...args);
8993+
return entry.cached.invalidate(...args);
89818994
}
89828995
/**
89838996
* Bulk-invalidate cache keys under the current namespace matching a pattern.
@@ -9003,11 +9016,11 @@ var FunctionCache = class {
90039016
getStats(name) {
90049017
if (name) {
90059018
if (this.options.enableStats === false) return null;
9006-
const stats = this.functions.get(name)?.getCacheStats();
9019+
const stats = this.functions.get(name)?.cached.getCacheStats();
90079020
return stats ? { ...stats } : null;
90089021
}
90099022
return Object.fromEntries(
9010-
[...this.functions.entries()].map(([functionName, fn]) => [functionName, fn.getCacheStats()])
9023+
[...this.functions.entries()].map(([functionName, entry]) => [functionName, entry.cached.getCacheStats()])
90119024
);
90129025
}
90139026
/**
@@ -9029,17 +9042,11 @@ var FunctionCache = class {
90299042
resetStats(name) {
90309043
const names = name ? [name] : [...this.functions.keys()];
90319044
for (const functionName of names) {
9032-
const fn = this.functions.get(functionName);
9033-
if (!fn) {
9045+
const entry = this.functions.get(functionName);
9046+
if (!entry) {
90349047
continue;
90359048
}
9036-
const replacement = withCache(async (...args) => fn(...args), {
9037-
cache: this.cache,
9038-
namespace: `${this.options.namespace ?? "action"}:${functionName}:reset`,
9039-
ttl: 0
9040-
});
9041-
replacement.invalidate = fn.invalidate;
9042-
this.functions.set(functionName, replacement);
9049+
entry.cached = this.createCachedFunction(functionName, entry.source, entry.options);
90439050
}
90449051
}
90459052
/**
@@ -9051,6 +9058,15 @@ var FunctionCache = class {
90519058
clear() {
90529059
this.functions.clear();
90539060
}
9061+
createCachedFunction(name, fn, options = {}) {
9062+
return withCache(fn, {
9063+
...options,
9064+
cache: options.cache ?? this.cache,
9065+
namespace: `${this.options.namespace ?? "action"}:${name}`,
9066+
ttl: options.ttl ?? this.options.defaultTTL ?? 6e4,
9067+
enableStats: options.enableStats ?? this.options.enableStats ?? true
9068+
});
9069+
}
90549070
};
90559071
function resolveCache(cacheOrDb) {
90569072
if (cacheOrDb && typeof cacheOrDb === "object" && typeof cacheOrDb.getCache === "function") {
@@ -9105,7 +9121,10 @@ var MonSQLizeRuntime = class {
91059121
this._transactionManager = null;
91069122
this._lockManager = null;
91079123
this._iidCache = null;
9108-
this._modelInstances = /* @__PURE__ */ new Map();
9124+
this._modelInstances = new MemoryCache({
9125+
maxEntries: 1e5,
9126+
enableStats: false
9127+
});
91099128
this._connectionPromise = null;
91109129
const type = options.type;
91119130
if (!type || !["mongodb"].includes(type)) {
@@ -9263,7 +9282,12 @@ var MonSQLizeRuntime = class {
92639282
}
92649283
const dbInstance = requireCompatDbInstance(this);
92659284
if (this._client) {
9266-
if (!this._iidCache) this._iidCache = /* @__PURE__ */ new Map();
9285+
if (!this._iidCache) {
9286+
this._iidCache = new MemoryCache({
9287+
maxEntries: 1e5,
9288+
enableStats: false
9289+
});
9290+
}
92679291
return this.db().collection(name);
92689292
}
92699293
return dbInstance.collection(name);

0 commit comments

Comments
 (0)