@utaba/deep-memory-storage-cosmosdb 0.8.1 → 0.9.1
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 +260 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -1
- package/dist/index.d.ts +35 -1
- package/dist/index.js +261 -40
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -41,6 +41,8 @@ var import_deep_memory5 = require("@utaba/deep-memory");
|
|
|
41
41
|
|
|
42
42
|
// src/CosmosDbConnection.ts
|
|
43
43
|
var import_gremlin = __toESM(require("gremlin"), 1);
|
|
44
|
+
var import_node_async_hooks = require("async_hooks");
|
|
45
|
+
var usageScope = new import_node_async_hooks.AsyncLocalStorage();
|
|
44
46
|
var CosmosDbConnection = class {
|
|
45
47
|
client = null;
|
|
46
48
|
config;
|
|
@@ -88,11 +90,18 @@ var CosmosDbConnection = class {
|
|
|
88
90
|
const resultSet = await this.client.submit(query, bindings);
|
|
89
91
|
const items = resultSet.toArray();
|
|
90
92
|
const requestCharge = extractRequestCharge(resultSet);
|
|
93
|
+
const acc = usageScope.getStore();
|
|
94
|
+
if (acc) {
|
|
95
|
+
acc.calls++;
|
|
96
|
+
if (typeof requestCharge === "number") acc.ru += requestCharge;
|
|
97
|
+
}
|
|
91
98
|
return { items, requestCharge };
|
|
92
99
|
} catch (err) {
|
|
93
100
|
lastError = err;
|
|
94
101
|
if (isTransientError(err) && attempt < this.config.maxRetries) {
|
|
95
102
|
const retryAfterMs = getRetryAfterMs(err, attempt);
|
|
103
|
+
const acc = usageScope.getStore();
|
|
104
|
+
if (acc) acc.retries++;
|
|
96
105
|
await sleep(retryAfterMs);
|
|
97
106
|
continue;
|
|
98
107
|
}
|
|
@@ -910,6 +919,7 @@ async function exploreNeighborhood(conn, repositoryId, entityId, options) {
|
|
|
910
919
|
for (let depth = 0; depth < options.depth; depth++) {
|
|
911
920
|
const layer = {};
|
|
912
921
|
const nextFrontier = /* @__PURE__ */ new Set();
|
|
922
|
+
const layerCache = /* @__PURE__ */ new Map();
|
|
913
923
|
for (const currentId of frontier) {
|
|
914
924
|
const rels = await getRelationshipsForEntity(conn, repositoryId, currentId, options);
|
|
915
925
|
for (const rel of rels) {
|
|
@@ -923,20 +933,20 @@ async function exploreNeighborhood(conn, repositoryId, entityId, options) {
|
|
|
923
933
|
} else {
|
|
924
934
|
connectedId = rel.sourceEntityId;
|
|
925
935
|
}
|
|
926
|
-
if (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
936
|
+
if (visited.has(connectedId)) continue;
|
|
937
|
+
let entity = layerCache.get(connectedId);
|
|
938
|
+
if (entity === void 0) {
|
|
939
|
+
const loaded = await getEntityLight(conn, repositoryId, connectedId);
|
|
940
|
+
if (loaded && (!options.entityTypes || options.entityTypes.length === 0 || options.entityTypes.includes(loaded.entityType))) {
|
|
941
|
+
entity = loaded;
|
|
931
942
|
} else {
|
|
932
|
-
|
|
933
|
-
if (entity) {
|
|
934
|
-
layer[relType].entities.push(entity);
|
|
935
|
-
}
|
|
943
|
+
entity = null;
|
|
936
944
|
}
|
|
937
|
-
|
|
938
|
-
nextFrontier.add(connectedId);
|
|
945
|
+
layerCache.set(connectedId, entity);
|
|
946
|
+
if (entity) nextFrontier.add(connectedId);
|
|
939
947
|
}
|
|
948
|
+
if (!entity) continue;
|
|
949
|
+
layer[relType].entities.push(entity);
|
|
940
950
|
layer[relType].relationships.push(rel);
|
|
941
951
|
layer[relType].total = layer[relType].entities.length;
|
|
942
952
|
}
|
|
@@ -951,6 +961,9 @@ async function exploreNeighborhood(conn, repositoryId, entityId, options) {
|
|
|
951
961
|
if (Object.keys(layer).length > 0) {
|
|
952
962
|
layers.push(layer);
|
|
953
963
|
}
|
|
964
|
+
for (const id of nextFrontier) {
|
|
965
|
+
visited.add(id);
|
|
966
|
+
}
|
|
954
967
|
frontier = nextFrontier;
|
|
955
968
|
if (frontier.size === 0) break;
|
|
956
969
|
}
|
|
@@ -1328,14 +1341,17 @@ async function upsertRelationship(conn, repositoryId, rel) {
|
|
|
1328
1341
|
}
|
|
1329
1342
|
|
|
1330
1343
|
// src/CosmosDbProvider.ts
|
|
1344
|
+
var PROVIDER_NAME = "cosmosdb";
|
|
1331
1345
|
var SCHEMA_VERSION = 1;
|
|
1332
1346
|
var META_VERTEX_ID = "_meta:schema";
|
|
1333
1347
|
var CosmosDbProvider = class {
|
|
1334
1348
|
conn;
|
|
1335
1349
|
config;
|
|
1336
1350
|
compiler = new import_deep_memory5.GremlinCompiler();
|
|
1351
|
+
reportUsage;
|
|
1337
1352
|
constructor(config) {
|
|
1338
1353
|
this.config = config;
|
|
1354
|
+
this.reportUsage = (0, import_deep_memory5.createSafeSink)(config.reportUsage);
|
|
1339
1355
|
this.conn = new CosmosDbConnection({
|
|
1340
1356
|
endpoint: config.endpoint,
|
|
1341
1357
|
key: config.key,
|
|
@@ -1346,6 +1362,39 @@ var CosmosDbProvider = class {
|
|
|
1346
1362
|
rejectUnauthorized: config.rejectUnauthorized
|
|
1347
1363
|
});
|
|
1348
1364
|
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Run the given operation inside an async-local usage scope. While the
|
|
1367
|
+
* operation runs, every `conn.submit()` call accumulates its request charge
|
|
1368
|
+
* into a shared accumulator. When the operation completes (success or
|
|
1369
|
+
* failure), a single {@link OperationUsage} record is emitted to the sink.
|
|
1370
|
+
*
|
|
1371
|
+
* Nested public-method calls (e.g. `traverse` internally calls
|
|
1372
|
+
* `getVocabulary`) are detected: the inner call joins the outer scope
|
|
1373
|
+
* instead of starting a new one, so one user-visible operation produces
|
|
1374
|
+
* exactly one usage record covering all its internal round-trips.
|
|
1375
|
+
*
|
|
1376
|
+
* If no sink is configured, this is a zero-overhead pass-through.
|
|
1377
|
+
*/
|
|
1378
|
+
async track(operation, repositoryId, fn) {
|
|
1379
|
+
if (!this.reportUsage) return fn();
|
|
1380
|
+
if (usageScope.getStore()) return fn();
|
|
1381
|
+
const acc = { ru: 0, calls: 0, retries: 0 };
|
|
1382
|
+
try {
|
|
1383
|
+
return await usageScope.run(acc, fn);
|
|
1384
|
+
} finally {
|
|
1385
|
+
if (acc.calls > 0) {
|
|
1386
|
+
this.reportUsage({
|
|
1387
|
+
provider: PROVIDER_NAME,
|
|
1388
|
+
operation,
|
|
1389
|
+
unit: "RU",
|
|
1390
|
+
value: acc.ru,
|
|
1391
|
+
...repositoryId ? { repositoryId } : {},
|
|
1392
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1393
|
+
details: { calls: acc.calls, retries: acc.retries }
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1349
1398
|
/**
|
|
1350
1399
|
* Reject any repositoryId that is not a valid v4 UUID.
|
|
1351
1400
|
*
|
|
@@ -1371,6 +1420,9 @@ var CosmosDbProvider = class {
|
|
|
1371
1420
|
await this.conn.close();
|
|
1372
1421
|
}
|
|
1373
1422
|
async ensureSchema() {
|
|
1423
|
+
return this.track("ensureSchema", void 0, () => this.ensureSchemaImpl());
|
|
1424
|
+
}
|
|
1425
|
+
async ensureSchemaImpl() {
|
|
1374
1426
|
const restBase = this.getRestEndpoint();
|
|
1375
1427
|
const partitionKey = this.config.partitionKey ?? "/repositoryId";
|
|
1376
1428
|
let databaseCreated = false;
|
|
@@ -1449,72 +1501,139 @@ var CosmosDbProvider = class {
|
|
|
1449
1501
|
// ─── Repository ────────────────────────────────────────────────────
|
|
1450
1502
|
async createRepository(config) {
|
|
1451
1503
|
this.assertValidRepositoryId(config.repositoryId);
|
|
1452
|
-
return
|
|
1504
|
+
return this.track(
|
|
1505
|
+
"createRepository",
|
|
1506
|
+
config.repositoryId,
|
|
1507
|
+
() => createRepository(this.conn, config)
|
|
1508
|
+
);
|
|
1453
1509
|
}
|
|
1454
1510
|
async getRepository(repositoryId) {
|
|
1455
1511
|
this.assertValidRepositoryId(repositoryId);
|
|
1456
|
-
return
|
|
1512
|
+
return this.track(
|
|
1513
|
+
"getRepository",
|
|
1514
|
+
repositoryId,
|
|
1515
|
+
() => getRepository(this.conn, repositoryId)
|
|
1516
|
+
);
|
|
1457
1517
|
}
|
|
1458
1518
|
async listRepositories(filter) {
|
|
1459
|
-
return
|
|
1519
|
+
return this.track(
|
|
1520
|
+
"listRepositories",
|
|
1521
|
+
void 0,
|
|
1522
|
+
() => listRepositories(this.conn, filter)
|
|
1523
|
+
);
|
|
1460
1524
|
}
|
|
1461
1525
|
async updateRepository(repositoryId, updates) {
|
|
1462
1526
|
this.assertValidRepositoryId(repositoryId);
|
|
1463
|
-
return
|
|
1527
|
+
return this.track(
|
|
1528
|
+
"updateRepository",
|
|
1529
|
+
repositoryId,
|
|
1530
|
+
() => updateRepository(this.conn, repositoryId, updates)
|
|
1531
|
+
);
|
|
1464
1532
|
}
|
|
1465
1533
|
async deleteRepository(repositoryId, onProgress) {
|
|
1466
1534
|
this.assertValidRepositoryId(repositoryId);
|
|
1467
|
-
return
|
|
1535
|
+
return this.track(
|
|
1536
|
+
"deleteRepository",
|
|
1537
|
+
repositoryId,
|
|
1538
|
+
() => deleteRepository(this.conn, repositoryId, onProgress)
|
|
1539
|
+
);
|
|
1468
1540
|
}
|
|
1469
1541
|
async deleteAllContents(repositoryId, onProgress) {
|
|
1470
1542
|
this.assertValidRepositoryId(repositoryId);
|
|
1471
|
-
return
|
|
1543
|
+
return this.track(
|
|
1544
|
+
"deleteAllContents",
|
|
1545
|
+
repositoryId,
|
|
1546
|
+
() => deleteAllContents(this.conn, repositoryId, onProgress)
|
|
1547
|
+
);
|
|
1472
1548
|
}
|
|
1473
1549
|
async getRepositoryStats(repositoryId) {
|
|
1474
1550
|
this.assertValidRepositoryId(repositoryId);
|
|
1475
|
-
return
|
|
1551
|
+
return this.track(
|
|
1552
|
+
"getRepositoryStats",
|
|
1553
|
+
repositoryId,
|
|
1554
|
+
() => getRepositoryStats(this.conn, repositoryId)
|
|
1555
|
+
);
|
|
1476
1556
|
}
|
|
1477
1557
|
// ─── Vocabulary ────────────────────────────────────────────────────
|
|
1478
1558
|
async getVocabulary(repositoryId) {
|
|
1479
1559
|
this.assertValidRepositoryId(repositoryId);
|
|
1480
|
-
return
|
|
1560
|
+
return this.track(
|
|
1561
|
+
"getVocabulary",
|
|
1562
|
+
repositoryId,
|
|
1563
|
+
() => getVocabulary(this.conn, repositoryId)
|
|
1564
|
+
);
|
|
1481
1565
|
}
|
|
1482
1566
|
async saveVocabulary(repositoryId, vocabulary) {
|
|
1483
1567
|
this.assertValidRepositoryId(repositoryId);
|
|
1484
|
-
return
|
|
1568
|
+
return this.track(
|
|
1569
|
+
"saveVocabulary",
|
|
1570
|
+
repositoryId,
|
|
1571
|
+
() => saveVocabulary(this.conn, repositoryId, vocabulary)
|
|
1572
|
+
);
|
|
1485
1573
|
}
|
|
1486
1574
|
async getVocabularyChangeLog(repositoryId, options) {
|
|
1487
1575
|
this.assertValidRepositoryId(repositoryId);
|
|
1488
|
-
return
|
|
1576
|
+
return this.track(
|
|
1577
|
+
"getVocabularyChangeLog",
|
|
1578
|
+
repositoryId,
|
|
1579
|
+
() => getVocabularyChangeLog(this.conn, repositoryId, options)
|
|
1580
|
+
);
|
|
1489
1581
|
}
|
|
1490
1582
|
// ─── Entities ──────────────────────────────────────────────────────
|
|
1491
1583
|
async createEntity(repositoryId, entity) {
|
|
1492
1584
|
this.assertValidRepositoryId(repositoryId);
|
|
1493
|
-
return
|
|
1585
|
+
return this.track(
|
|
1586
|
+
"createEntity",
|
|
1587
|
+
repositoryId,
|
|
1588
|
+
() => createEntity(this.conn, repositoryId, entity)
|
|
1589
|
+
);
|
|
1494
1590
|
}
|
|
1495
1591
|
async getEntity(repositoryId, entityId) {
|
|
1496
1592
|
this.assertValidRepositoryId(repositoryId);
|
|
1497
|
-
return
|
|
1593
|
+
return this.track(
|
|
1594
|
+
"getEntity",
|
|
1595
|
+
repositoryId,
|
|
1596
|
+
() => getEntity(this.conn, repositoryId, entityId)
|
|
1597
|
+
);
|
|
1498
1598
|
}
|
|
1499
1599
|
async getEntityBySlug(repositoryId, slug) {
|
|
1500
1600
|
this.assertValidRepositoryId(repositoryId);
|
|
1501
|
-
return
|
|
1601
|
+
return this.track(
|
|
1602
|
+
"getEntityBySlug",
|
|
1603
|
+
repositoryId,
|
|
1604
|
+
() => getEntityBySlug(this.conn, repositoryId, slug)
|
|
1605
|
+
);
|
|
1502
1606
|
}
|
|
1503
1607
|
async getEntities(repositoryId, entityIds) {
|
|
1504
1608
|
this.assertValidRepositoryId(repositoryId);
|
|
1505
|
-
return
|
|
1609
|
+
return this.track(
|
|
1610
|
+
"getEntities",
|
|
1611
|
+
repositoryId,
|
|
1612
|
+
() => getEntities(this.conn, repositoryId, entityIds)
|
|
1613
|
+
);
|
|
1506
1614
|
}
|
|
1507
1615
|
async updateEntity(repositoryId, entityId, updates) {
|
|
1508
1616
|
this.assertValidRepositoryId(repositoryId);
|
|
1509
|
-
return
|
|
1617
|
+
return this.track(
|
|
1618
|
+
"updateEntity",
|
|
1619
|
+
repositoryId,
|
|
1620
|
+
() => updateEntity(this.conn, repositoryId, entityId, updates)
|
|
1621
|
+
);
|
|
1510
1622
|
}
|
|
1511
1623
|
async deleteEntity(repositoryId, entityId) {
|
|
1512
1624
|
this.assertValidRepositoryId(repositoryId);
|
|
1513
|
-
return
|
|
1625
|
+
return this.track(
|
|
1626
|
+
"deleteEntity",
|
|
1627
|
+
repositoryId,
|
|
1628
|
+
() => deleteEntity(this.conn, repositoryId, entityId)
|
|
1629
|
+
);
|
|
1514
1630
|
}
|
|
1515
1631
|
async deleteEntities(repositoryId, ids) {
|
|
1516
1632
|
if (ids.length === 0) return { deleted: [], notFound: [] };
|
|
1517
1633
|
this.assertValidRepositoryId(repositoryId);
|
|
1634
|
+
return this.track("deleteEntities", repositoryId, () => this.deleteEntitiesImpl(repositoryId, ids));
|
|
1635
|
+
}
|
|
1636
|
+
async deleteEntitiesImpl(repositoryId, ids) {
|
|
1518
1637
|
const deleted = [];
|
|
1519
1638
|
const CHUNK = 100;
|
|
1520
1639
|
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
@@ -1553,32 +1672,59 @@ var CosmosDbProvider = class {
|
|
|
1553
1672
|
}
|
|
1554
1673
|
async deleteEntitiesByType(repositoryId, entityType) {
|
|
1555
1674
|
this.assertValidRepositoryId(repositoryId);
|
|
1556
|
-
return
|
|
1675
|
+
return this.track(
|
|
1676
|
+
"deleteEntitiesByType",
|
|
1677
|
+
repositoryId,
|
|
1678
|
+
() => deleteEntitiesByType(this.conn, repositoryId, entityType)
|
|
1679
|
+
);
|
|
1557
1680
|
}
|
|
1558
1681
|
async findEntities(repositoryId, query) {
|
|
1559
1682
|
this.assertValidRepositoryId(repositoryId);
|
|
1560
|
-
return
|
|
1683
|
+
return this.track(
|
|
1684
|
+
"findEntities",
|
|
1685
|
+
repositoryId,
|
|
1686
|
+
() => findEntities(this.conn, repositoryId, query)
|
|
1687
|
+
);
|
|
1561
1688
|
}
|
|
1562
1689
|
// ─── Relationships ─────────────────────────────────────────────────
|
|
1563
1690
|
async createRelationship(repositoryId, relationship) {
|
|
1564
1691
|
this.assertValidRepositoryId(repositoryId);
|
|
1565
|
-
return
|
|
1692
|
+
return this.track(
|
|
1693
|
+
"createRelationship",
|
|
1694
|
+
repositoryId,
|
|
1695
|
+
() => createRelationship(this.conn, repositoryId, relationship)
|
|
1696
|
+
);
|
|
1566
1697
|
}
|
|
1567
1698
|
async getRelationship(repositoryId, relationshipId) {
|
|
1568
1699
|
this.assertValidRepositoryId(repositoryId);
|
|
1569
|
-
return
|
|
1700
|
+
return this.track(
|
|
1701
|
+
"getRelationship",
|
|
1702
|
+
repositoryId,
|
|
1703
|
+
() => getRelationship(this.conn, repositoryId, relationshipId)
|
|
1704
|
+
);
|
|
1570
1705
|
}
|
|
1571
1706
|
async getEntityRelationships(repositoryId, entityId, options) {
|
|
1572
1707
|
this.assertValidRepositoryId(repositoryId);
|
|
1573
|
-
return
|
|
1708
|
+
return this.track(
|
|
1709
|
+
"getEntityRelationships",
|
|
1710
|
+
repositoryId,
|
|
1711
|
+
() => getEntityRelationships(this.conn, repositoryId, entityId, options)
|
|
1712
|
+
);
|
|
1574
1713
|
}
|
|
1575
1714
|
async deleteRelationship(repositoryId, relationshipId) {
|
|
1576
1715
|
this.assertValidRepositoryId(repositoryId);
|
|
1577
|
-
return
|
|
1716
|
+
return this.track(
|
|
1717
|
+
"deleteRelationship",
|
|
1718
|
+
repositoryId,
|
|
1719
|
+
() => deleteRelationship(this.conn, repositoryId, relationshipId)
|
|
1720
|
+
);
|
|
1578
1721
|
}
|
|
1579
1722
|
async deleteRelationships(repositoryId, ids) {
|
|
1580
1723
|
if (ids.length === 0) return { deleted: [], notFound: [] };
|
|
1581
1724
|
this.assertValidRepositoryId(repositoryId);
|
|
1725
|
+
return this.track("deleteRelationships", repositoryId, () => this.deleteRelationshipsImpl(repositoryId, ids));
|
|
1726
|
+
}
|
|
1727
|
+
async deleteRelationshipsImpl(repositoryId, ids) {
|
|
1582
1728
|
const deleted = [];
|
|
1583
1729
|
const CHUNK = 100;
|
|
1584
1730
|
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
@@ -1614,30 +1760,99 @@ var CosmosDbProvider = class {
|
|
|
1614
1760
|
}
|
|
1615
1761
|
async deleteRelationshipsByType(repositoryId, relationshipType) {
|
|
1616
1762
|
this.assertValidRepositoryId(repositoryId);
|
|
1617
|
-
return
|
|
1763
|
+
return this.track(
|
|
1764
|
+
"deleteRelationshipsByType",
|
|
1765
|
+
repositoryId,
|
|
1766
|
+
() => deleteRelationshipsByType(this.conn, repositoryId, relationshipType)
|
|
1767
|
+
);
|
|
1618
1768
|
}
|
|
1619
1769
|
// ─── Graph Traversal (StorageProvider) ─────────────────────────────
|
|
1620
1770
|
async exploreNeighborhood(repositoryId, entityId, options) {
|
|
1621
1771
|
this.assertValidRepositoryId(repositoryId);
|
|
1622
|
-
return
|
|
1772
|
+
return this.track(
|
|
1773
|
+
"exploreNeighborhood",
|
|
1774
|
+
repositoryId,
|
|
1775
|
+
() => exploreNeighborhood(this.conn, repositoryId, entityId, options)
|
|
1776
|
+
);
|
|
1623
1777
|
}
|
|
1624
1778
|
async findPaths(repositoryId, sourceId, targetId, options) {
|
|
1625
1779
|
this.assertValidRepositoryId(repositoryId);
|
|
1626
|
-
return
|
|
1780
|
+
return this.track(
|
|
1781
|
+
"findPaths",
|
|
1782
|
+
repositoryId,
|
|
1783
|
+
() => findPaths(this.conn, repositoryId, sourceId, targetId, options)
|
|
1784
|
+
);
|
|
1627
1785
|
}
|
|
1628
1786
|
// ─── Timeline ──────────────────────────────────────────────────────
|
|
1629
1787
|
async getTimeline(repositoryId, entityId, options) {
|
|
1630
1788
|
this.assertValidRepositoryId(repositoryId);
|
|
1631
|
-
return
|
|
1789
|
+
return this.track(
|
|
1790
|
+
"getTimeline",
|
|
1791
|
+
repositoryId,
|
|
1792
|
+
() => getTimeline(this.conn, repositoryId, entityId, options)
|
|
1793
|
+
);
|
|
1632
1794
|
}
|
|
1633
1795
|
// ─── Bulk Operations ───────────────────────────────────────────────
|
|
1634
1796
|
exportAll(repositoryId) {
|
|
1635
1797
|
this.assertValidRepositoryId(repositoryId);
|
|
1636
|
-
return exportAll(this.conn, repositoryId);
|
|
1798
|
+
return this.trackIterable("exportAll", repositoryId, exportAll(this.conn, repositoryId));
|
|
1637
1799
|
}
|
|
1638
1800
|
async importBulk(repositoryId, data, options) {
|
|
1639
1801
|
this.assertValidRepositoryId(repositoryId);
|
|
1640
|
-
return
|
|
1802
|
+
return this.track(
|
|
1803
|
+
"importBulk",
|
|
1804
|
+
repositoryId,
|
|
1805
|
+
() => importBulk(this.conn, repositoryId, data, options)
|
|
1806
|
+
);
|
|
1807
|
+
}
|
|
1808
|
+
/**
|
|
1809
|
+
* Wrap an AsyncIterable so every emitted chunk is generated inside the
|
|
1810
|
+
* usage scope. On each iteration step, the scope aggregates charges from
|
|
1811
|
+
* the next chunk's submits; when the iterator completes (or is closed), a
|
|
1812
|
+
* single usage record is emitted for the whole stream.
|
|
1813
|
+
*/
|
|
1814
|
+
trackIterable(operation, repositoryId, source) {
|
|
1815
|
+
if (!this.reportUsage) return source;
|
|
1816
|
+
const sink = this.reportUsage;
|
|
1817
|
+
return {
|
|
1818
|
+
[Symbol.asyncIterator]: () => {
|
|
1819
|
+
const iter = source[Symbol.asyncIterator]();
|
|
1820
|
+
const acc = { ru: 0, calls: 0, retries: 0 };
|
|
1821
|
+
let emitted = false;
|
|
1822
|
+
const emit = () => {
|
|
1823
|
+
if (emitted) return;
|
|
1824
|
+
emitted = true;
|
|
1825
|
+
if (acc.calls > 0) {
|
|
1826
|
+
sink({
|
|
1827
|
+
provider: PROVIDER_NAME,
|
|
1828
|
+
operation,
|
|
1829
|
+
unit: "RU",
|
|
1830
|
+
value: acc.ru,
|
|
1831
|
+
repositoryId,
|
|
1832
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1833
|
+
details: { calls: acc.calls, retries: acc.retries }
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
return {
|
|
1838
|
+
async next() {
|
|
1839
|
+
const step = await usageScope.run(acc, () => iter.next());
|
|
1840
|
+
if (step.done) emit();
|
|
1841
|
+
return step;
|
|
1842
|
+
},
|
|
1843
|
+
async return(value) {
|
|
1844
|
+
emit();
|
|
1845
|
+
if (iter.return) return iter.return(value);
|
|
1846
|
+
return { done: true, value };
|
|
1847
|
+
},
|
|
1848
|
+
async throw(err) {
|
|
1849
|
+
emit();
|
|
1850
|
+
if (iter.throw) return iter.throw(err);
|
|
1851
|
+
throw err;
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1641
1856
|
}
|
|
1642
1857
|
// ─── GraphTraversalProvider ────────────────────────────────────────
|
|
1643
1858
|
getCapabilities() {
|
|
@@ -1655,6 +1870,9 @@ var CosmosDbProvider = class {
|
|
|
1655
1870
|
}
|
|
1656
1871
|
async traverse(repositoryId, spec) {
|
|
1657
1872
|
this.assertValidRepositoryId(repositoryId);
|
|
1873
|
+
return this.track("traverse", repositoryId, () => this.traverseImpl(repositoryId, spec));
|
|
1874
|
+
}
|
|
1875
|
+
async traverseImpl(repositoryId, spec) {
|
|
1658
1876
|
const startTime = Date.now();
|
|
1659
1877
|
const vocabulary = await this.getVocabulary(repositoryId);
|
|
1660
1878
|
const compiled = this.compiler.compile(spec, vocabulary);
|
|
@@ -1748,6 +1966,9 @@ var CosmosDbProvider = class {
|
|
|
1748
1966
|
* repositoryId partition predicate.
|
|
1749
1967
|
*/
|
|
1750
1968
|
async executeNativeQuery(_repositoryId, query, params) {
|
|
1969
|
+
return this.track("executeNativeQuery", void 0, () => this.executeNativeQueryImpl(query, params));
|
|
1970
|
+
}
|
|
1971
|
+
async executeNativeQueryImpl(query, params) {
|
|
1751
1972
|
const startTime = Date.now();
|
|
1752
1973
|
try {
|
|
1753
1974
|
const result = await this.conn.submit(query, params);
|