@utaba/deep-memory-storage-cosmosdb 0.12.0 → 0.14.0
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.
- package/dist/index.cjs +55 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +55 -33
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -147,7 +147,7 @@ declare class CosmosDbProvider implements StorageProvider, GraphTraversalProvide
|
|
|
147
147
|
* For agent-facing graph queries use {@link traverse}, which enforces the
|
|
148
148
|
* repositoryId partition predicate.
|
|
149
149
|
*/
|
|
150
|
-
executeNativeQuery(_repositoryId: string, query: string, params?: Record<string, unknown>): Promise<
|
|
150
|
+
executeNativeQuery(_repositoryId: string, query: string, params?: Record<string, unknown>): Promise<unknown[]>;
|
|
151
151
|
private executeNativeQueryImpl;
|
|
152
152
|
}
|
|
153
153
|
|
package/dist/index.d.ts
CHANGED
|
@@ -147,7 +147,7 @@ declare class CosmosDbProvider implements StorageProvider, GraphTraversalProvide
|
|
|
147
147
|
* For agent-facing graph queries use {@link traverse}, which enforces the
|
|
148
148
|
* repositoryId partition predicate.
|
|
149
149
|
*/
|
|
150
|
-
executeNativeQuery(_repositoryId: string, query: string, params?: Record<string, unknown>): Promise<
|
|
150
|
+
executeNativeQuery(_repositoryId: string, query: string, params?: Record<string, unknown>): Promise<unknown[]>;
|
|
151
151
|
private executeNativeQueryImpl;
|
|
152
152
|
}
|
|
153
153
|
|
package/dist/index.js
CHANGED
|
@@ -1090,41 +1090,71 @@ function isInTimeRange(timestamp, timeRange) {
|
|
|
1090
1090
|
|
|
1091
1091
|
// src/queries/adaptive-import.ts
|
|
1092
1092
|
import { ImportThrottleAbortError } from "@utaba/deep-memory";
|
|
1093
|
-
var DEFAULT_MIN =
|
|
1093
|
+
var DEFAULT_MIN = 1;
|
|
1094
1094
|
var DEFAULT_START = 5;
|
|
1095
1095
|
var DEFAULT_MAX = 32;
|
|
1096
1096
|
var DEFAULT_INCREASE_AFTER = 50;
|
|
1097
1097
|
var DEFAULT_COOLDOWN_MS = 1e3;
|
|
1098
|
+
var DEFAULT_RAMP_UP_COOLDOWN_MS = 5e3;
|
|
1098
1099
|
var DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN = 10;
|
|
1100
|
+
var DEFAULT_THROTTLE_CEILING_MULTIPLIER = 3;
|
|
1101
|
+
var NO_SOFT_CEILING = Number.POSITIVE_INFINITY;
|
|
1099
1102
|
function resolveOptions(opts) {
|
|
1100
1103
|
const min = Math.max(1, opts?.min ?? DEFAULT_MIN);
|
|
1101
1104
|
const max = Math.max(min, opts?.max ?? DEFAULT_MAX);
|
|
1102
1105
|
const start = Math.min(max, Math.max(min, opts?.start ?? DEFAULT_START));
|
|
1103
1106
|
const increaseAfter = Math.max(1, opts?.increaseAfter ?? DEFAULT_INCREASE_AFTER);
|
|
1104
1107
|
const cooldownMs = Math.max(0, opts?.cooldownMs ?? DEFAULT_COOLDOWN_MS);
|
|
1108
|
+
const rampUpCooldownMs = Math.max(0, opts?.rampUpCooldownMs ?? DEFAULT_RAMP_UP_COOLDOWN_MS);
|
|
1105
1109
|
const maxConsecutiveThrottlesAtMin = Math.max(
|
|
1106
1110
|
1,
|
|
1107
1111
|
opts?.maxConsecutiveThrottlesAtMin ?? DEFAULT_MAX_CONSECUTIVE_THROTTLES_AT_MIN
|
|
1108
1112
|
);
|
|
1113
|
+
const throttleCeilingMultiplier = Math.max(
|
|
1114
|
+
1,
|
|
1115
|
+
opts?.throttleCeilingMultiplier ?? DEFAULT_THROTTLE_CEILING_MULTIPLIER
|
|
1116
|
+
);
|
|
1109
1117
|
return {
|
|
1110
1118
|
min,
|
|
1111
1119
|
start,
|
|
1112
1120
|
max,
|
|
1113
1121
|
increaseAfter,
|
|
1114
1122
|
cooldownMs,
|
|
1123
|
+
rampUpCooldownMs,
|
|
1115
1124
|
maxConsecutiveThrottlesAtMin,
|
|
1125
|
+
throttleCeilingMultiplier,
|
|
1116
1126
|
onAdjust: opts?.onAdjust
|
|
1117
1127
|
};
|
|
1118
1128
|
}
|
|
1129
|
+
function resolveController(options, handle) {
|
|
1130
|
+
if (!handle) {
|
|
1131
|
+
return new AdaptiveConcurrencyController(options);
|
|
1132
|
+
}
|
|
1133
|
+
const cosmosHandle = handle;
|
|
1134
|
+
if (!cosmosHandle.controller) {
|
|
1135
|
+
cosmosHandle.controller = new AdaptiveConcurrencyController(options);
|
|
1136
|
+
}
|
|
1137
|
+
return cosmosHandle.controller;
|
|
1138
|
+
}
|
|
1119
1139
|
var AdaptiveConcurrencyController = class {
|
|
1120
1140
|
opts;
|
|
1121
1141
|
current;
|
|
1122
1142
|
streak = 0;
|
|
1123
1143
|
cooldownUntil = 0;
|
|
1144
|
+
rampFrozenUntil = 0;
|
|
1124
1145
|
completed = 0;
|
|
1125
1146
|
throttled = 0;
|
|
1126
1147
|
startEmitted = false;
|
|
1127
1148
|
consecutiveThrottlesAtMin = 0;
|
|
1149
|
+
/**
|
|
1150
|
+
* Highest concurrency at which a throttle has been observed and the
|
|
1151
|
+
* controller actually halved (i.e. concrete evidence the cluster could not
|
|
1152
|
+
* sustain that level). Re-approaching this level on subsequent ramp-ups
|
|
1153
|
+
* requires `increaseAfter * throttleCeilingMultiplier` consecutive successes
|
|
1154
|
+
* instead of just `increaseAfter`. Cleared once we've successfully held the
|
|
1155
|
+
* level without further throttling — see noteSuccess.
|
|
1156
|
+
*/
|
|
1157
|
+
softCeiling = NO_SOFT_CEILING;
|
|
1128
1158
|
constructor(opts) {
|
|
1129
1159
|
this.opts = resolveOptions(opts);
|
|
1130
1160
|
this.current = this.opts.start;
|
|
@@ -1162,14 +1192,21 @@ var AdaptiveConcurrencyController = class {
|
|
|
1162
1192
|
this.notify("start", this.current);
|
|
1163
1193
|
}
|
|
1164
1194
|
/** Record a throttle-free task completion. May trigger ramp-up. */
|
|
1165
|
-
noteSuccess() {
|
|
1195
|
+
noteSuccess(now = Date.now()) {
|
|
1166
1196
|
this.completed++;
|
|
1167
|
-
this.streak++;
|
|
1168
1197
|
this.consecutiveThrottlesAtMin = 0;
|
|
1169
|
-
if (
|
|
1198
|
+
if (now < this.rampFrozenUntil) return;
|
|
1199
|
+
this.streak++;
|
|
1200
|
+
if (this.current >= this.opts.max) return;
|
|
1201
|
+
const target = this.current + 1;
|
|
1202
|
+
const needed = target >= this.softCeiling ? this.opts.increaseAfter * this.opts.throttleCeilingMultiplier : this.opts.increaseAfter;
|
|
1203
|
+
if (this.streak >= needed) {
|
|
1170
1204
|
const previous = this.current;
|
|
1171
|
-
this.current = Math.min(this.opts.max,
|
|
1205
|
+
this.current = Math.min(this.opts.max, target);
|
|
1172
1206
|
this.streak = 0;
|
|
1207
|
+
if (this.current >= this.softCeiling) {
|
|
1208
|
+
this.softCeiling = NO_SOFT_CEILING;
|
|
1209
|
+
}
|
|
1173
1210
|
this.notify("ramp-up", previous);
|
|
1174
1211
|
}
|
|
1175
1212
|
}
|
|
@@ -1181,8 +1218,10 @@ var AdaptiveConcurrencyController = class {
|
|
|
1181
1218
|
const previous = this.current;
|
|
1182
1219
|
const next = Math.max(this.opts.min, Math.floor(this.current / 2));
|
|
1183
1220
|
this.cooldownUntil = now + this.opts.cooldownMs;
|
|
1221
|
+
this.rampFrozenUntil = now + this.opts.rampUpCooldownMs;
|
|
1184
1222
|
if (next !== previous) {
|
|
1185
1223
|
this.current = next;
|
|
1224
|
+
this.softCeiling = previous;
|
|
1186
1225
|
this.notify("throttle", previous);
|
|
1187
1226
|
}
|
|
1188
1227
|
if (this.current === this.opts.min) {
|
|
@@ -1191,6 +1230,15 @@ var AdaptiveConcurrencyController = class {
|
|
|
1191
1230
|
this.consecutiveThrottlesAtMin = 0;
|
|
1192
1231
|
}
|
|
1193
1232
|
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Current soft ceiling — the highest concurrency at which a throttle was
|
|
1235
|
+
* observed and the controller halved. {@link Number.POSITIVE_INFINITY} when
|
|
1236
|
+
* no ceiling is in effect. Re-approaching this level requires
|
|
1237
|
+
* `increaseAfter * throttleCeilingMultiplier` consecutive successes.
|
|
1238
|
+
*/
|
|
1239
|
+
getSoftCeiling() {
|
|
1240
|
+
return this.softCeiling;
|
|
1241
|
+
}
|
|
1194
1242
|
/** Configured circuit-breaker threshold. */
|
|
1195
1243
|
getMaxConsecutiveThrottlesAtMin() {
|
|
1196
1244
|
return this.opts.maxConsecutiveThrottlesAtMin;
|
|
@@ -1371,7 +1419,7 @@ async function importBulk(conn, repositoryId, data, options) {
|
|
|
1371
1419
|
let relationshipsImported = 0;
|
|
1372
1420
|
const errors = [];
|
|
1373
1421
|
const skipCheck = options?.skipExistenceCheck ?? false;
|
|
1374
|
-
const controller =
|
|
1422
|
+
const controller = resolveController(options?.adaptiveConcurrency, options?.adaptiveConcurrencyHandle);
|
|
1375
1423
|
for (const chunk of data) {
|
|
1376
1424
|
if (chunk.entities && chunk.entities.length > 0) {
|
|
1377
1425
|
const results = await runAdaptive(
|
|
@@ -2136,35 +2184,9 @@ var CosmosDbProvider = class {
|
|
|
2136
2184
|
return this.track("executeNativeQuery", void 0, () => this.executeNativeQueryImpl(query, params));
|
|
2137
2185
|
}
|
|
2138
2186
|
async executeNativeQueryImpl(query, params) {
|
|
2139
|
-
const startTime = Date.now();
|
|
2140
2187
|
try {
|
|
2141
2188
|
const result = await this.conn.submit(query, params);
|
|
2142
|
-
|
|
2143
|
-
const entities = [];
|
|
2144
|
-
for (const item of result.items) {
|
|
2145
|
-
try {
|
|
2146
|
-
const entity = entityFromGremlin(item);
|
|
2147
|
-
if (entity.id) {
|
|
2148
|
-
entities.push(entity);
|
|
2149
|
-
}
|
|
2150
|
-
} catch {
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
const queryMetadata = {
|
|
2154
|
-
executionTimeMs,
|
|
2155
|
-
resourceCost: result.requestCharge != null ? { units: "RU", value: result.requestCharge } : void 0,
|
|
2156
|
-
compiledQuery: query,
|
|
2157
|
-
compiledQueryLanguage: "gremlin",
|
|
2158
|
-
appliedLimits: { maxResults: entities.length },
|
|
2159
|
-
truncated: false
|
|
2160
|
-
};
|
|
2161
|
-
return {
|
|
2162
|
-
entities,
|
|
2163
|
-
total: entities.length,
|
|
2164
|
-
returned: entities.length,
|
|
2165
|
-
hasMore: false,
|
|
2166
|
-
queryMetadata
|
|
2167
|
-
};
|
|
2189
|
+
return result.items;
|
|
2168
2190
|
} catch (err) {
|
|
2169
2191
|
throw new ProviderError(
|
|
2170
2192
|
`Native Gremlin query failed: ${err instanceof Error ? err.message : String(err)}`,
|