@open-mercato/shared 0.6.8-develop.7091.1.15ffbe30ce → 0.6.8-develop.7093.1.700c5c8d96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,6 +22,7 @@ import { warnOnCiphertextLikeFallback } from "./ciphertext-search-warning.js";
22
22
  import { resolveEncryptedSortFields, resolveEncryptedSortMaxRows, sortRowsInMemory } from "./encrypted-sort.js";
23
23
  import { resolveListCountCap } from "./count-cap.js";
24
24
  import { mapWithConcurrency } from "./bounded-decrypt.js";
25
+ import { parseNumberWithDefault } from "../number.js";
25
26
  import { createLogger } from "../logger/index.js";
26
27
  const logger = createLogger("shared").child({ component: "query" });
27
28
  const DECRYPT_CONCURRENCY = 8;
@@ -48,6 +49,32 @@ async function resolveEncryptedLikeFieldSet(read, entity, tenantId) {
48
49
  function clearEncryptedLikeFieldsCache() {
49
50
  encryptedLikeFieldsCache.clear();
50
51
  }
52
+ const COLUMN_EXISTS_CACHE_DEFAULT_TTL_MS = 3e5;
53
+ const COLUMN_EXISTS_CACHE_DEFAULT_MAX_ENTRIES = 1e4;
54
+ const columnExistsCache = /* @__PURE__ */ new Map();
55
+ function resolveColumnExistsCacheTtlMs() {
56
+ return parseNumberWithDefault(process.env.OM_QUERY_COLUMN_EXISTS_CACHE_MS, COLUMN_EXISTS_CACHE_DEFAULT_TTL_MS, { integer: true, min: 0 });
57
+ }
58
+ function resolveColumnExistsCacheMaxEntries() {
59
+ return parseNumberWithDefault(process.env.OM_QUERY_COLUMN_EXISTS_CACHE_MAX_ENTRIES, COLUMN_EXISTS_CACHE_DEFAULT_MAX_ENTRIES, { integer: true, min: 1 });
60
+ }
61
+ function storeColumnExists(key, value, ttlMs) {
62
+ const maxEntries = resolveColumnExistsCacheMaxEntries();
63
+ if (columnExistsCache.size >= maxEntries) {
64
+ const now = Date.now();
65
+ for (const [entryKey, entry] of columnExistsCache) {
66
+ if (entry.expiresAt <= now) columnExistsCache.delete(entryKey);
67
+ }
68
+ if (columnExistsCache.size >= maxEntries) columnExistsCache.clear();
69
+ }
70
+ columnExistsCache.set(key, { value, expiresAt: Date.now() + ttlMs });
71
+ }
72
+ function clearColumnExistsCache() {
73
+ columnExistsCache.clear();
74
+ }
75
+ function columnExistsCacheSize() {
76
+ return columnExistsCache.size;
77
+ }
51
78
  const ENTITY_ID_PATTERN = /^[a-z][a-z0-9_]*:[a-z][a-z0-9_]*$/;
52
79
  const isValidEntityIdShape = (value) => ENTITY_ID_PATTERN.test(value);
53
80
  const pluralizeBaseName = (name) => {
@@ -164,7 +191,6 @@ class BasicQueryEngine {
164
191
  this.em = em;
165
192
  this.getDbFn = getDbFn;
166
193
  this.resolveEncryptionService = resolveEncryptionService;
167
- this.columnCache = /* @__PURE__ */ new Map();
168
194
  this.searchAliasSeq = 0;
169
195
  this.searchAvailabilityInstance = null;
170
196
  }
@@ -1115,16 +1141,13 @@ class BasicQueryEngine {
1115
1141
  }
1116
1142
  async columnExists(table, column) {
1117
1143
  const key = `${table}.${column}`;
1118
- if (this.columnCache.has(key)) {
1119
- const cached = this.columnCache.get(key);
1120
- if (cached === true) return true;
1121
- this.columnCache.delete(key);
1122
- }
1144
+ const ttlMs = resolveColumnExistsCacheTtlMs();
1145
+ const cached = columnExistsCache.get(key);
1146
+ if (cached && cached.expiresAt > Date.now()) return cached.value;
1123
1147
  const db = this.getDb();
1124
1148
  const exists = await db.selectFrom("information_schema.columns").select(sql`1`.as("one")).where("table_name", "=", table).where("column_name", "=", column).limit(1).executeTakeFirst();
1125
1149
  const present = !!exists;
1126
- if (present) this.columnCache.set(key, true);
1127
- else this.columnCache.delete(key);
1150
+ if (ttlMs > 0) storeColumnExists(key, present, ttlMs);
1128
1151
  return present;
1129
1152
  }
1130
1153
  applySearchTokens(q, opts) {
@@ -1334,7 +1357,9 @@ class BasicQueryEngine {
1334
1357
  export {
1335
1358
  BasicQueryEngine,
1336
1359
  ENTITY_ID_PATTERN,
1360
+ clearColumnExistsCache,
1337
1361
  clearEncryptedLikeFieldsCache,
1362
+ columnExistsCacheSize,
1338
1363
  isEncryptedLikeField,
1339
1364
  isValidEntityIdShape,
1340
1365
  resolveEncryptedLikeFieldSet,