@twin.org/auditable-item-graph-service 0.0.3-next.13 → 0.0.3-next.15
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/es/auditableItemGraphRoutes.js +162 -1
- package/dist/es/auditableItemGraphRoutes.js.map +1 -1
- package/dist/es/auditableItemGraphService.js +208 -11
- package/dist/es/auditableItemGraphService.js.map +1 -1
- package/dist/es/entities/auditableItemGraphChangeset.js +8 -0
- package/dist/es/entities/auditableItemGraphChangeset.js.map +1 -1
- package/dist/es/entities/auditableItemGraphVertex.js +8 -0
- package/dist/es/entities/auditableItemGraphVertex.js.map +1 -1
- package/dist/es/models/IAuditableItemGraphServiceConstructorOptions.js.map +1 -1
- package/dist/types/auditableItemGraphRoutes.d.ts +17 -1
- package/dist/types/auditableItemGraphService.d.ts +26 -1
- package/dist/types/entities/auditableItemGraphChangeset.d.ts +4 -0
- package/dist/types/entities/auditableItemGraphVertex.d.ts +4 -0
- package/dist/types/models/IAuditableItemGraphServiceConstructorOptions.d.ts +4 -0
- package/docs/changelog.md +29 -0
- package/docs/open-api/spec.json +284 -0
- package/docs/reference/classes/AuditableItemGraphChangeset.md +8 -0
- package/docs/reference/classes/AuditableItemGraphService.md +98 -0
- package/docs/reference/classes/AuditableItemGraphVertex.md +8 -0
- package/docs/reference/functions/auditableItemGraphVersionGet.md +31 -0
- package/docs/reference/functions/auditableItemGraphVersionList.md +31 -0
- package/docs/reference/index.md +2 -0
- package/docs/reference/interfaces/IAuditableItemGraphServiceConstructorOptions.md +8 -0
- package/locales/en.json +3 -0
- package/package.json +3 -2
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import { AuditableItemGraphContexts, AuditableItemGraphDataTypes, AuditableItemGraphTopics, AuditableItemGraphTypes, VerifyDepth } from "@twin.org/auditable-item-graph-models";
|
|
3
|
+
import { AuditableItemGraphContexts, AuditableItemGraphDataTypes, AuditableItemGraphMetricIds, AuditableItemGraphMetrics, AuditableItemGraphTopics, AuditableItemGraphTypes, VerifyDepth } from "@twin.org/auditable-item-graph-models";
|
|
4
4
|
import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
|
|
5
|
-
import { ArrayHelper, ComponentFactory, GeneralError, Guards, Is, JsonHelper, NotFoundError, ObjectHelper, RandomHelper, StringHelper, Urn, Validation } from "@twin.org/core";
|
|
5
|
+
import { ArrayHelper, Coerce, ComponentFactory, GeneralError, Guards, Is, JsonHelper, NotFoundError, ObjectHelper, RandomHelper, StringHelper, Urn, Validation } from "@twin.org/core";
|
|
6
6
|
import { DataTypeHelper } from "@twin.org/data-core";
|
|
7
7
|
import { JsonLdDataTypes, JsonLdHelper, JsonLdProcessor } from "@twin.org/data-json-ld";
|
|
8
8
|
import { ComparisonOperator, LogicalOperator, SortDirection } from "@twin.org/entity";
|
|
9
9
|
import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
|
|
10
10
|
import { ImmutableProofContexts, ImmutableProofFailure, ImmutableProofTypes } from "@twin.org/immutable-proof-models";
|
|
11
11
|
import { SchemaOrgContexts, SchemaOrgDataTypes, SchemaOrgTypes } from "@twin.org/standards-schema-org";
|
|
12
|
+
import { MetricHelper } from "@twin.org/telemetry-models";
|
|
12
13
|
/**
|
|
13
14
|
* Class for performing auditable item graph operations.
|
|
14
15
|
*/
|
|
@@ -61,6 +62,11 @@ export class AuditableItemGraphService {
|
|
|
61
62
|
* @internal
|
|
62
63
|
*/
|
|
63
64
|
_eventBusComponent;
|
|
65
|
+
/**
|
|
66
|
+
* The telemetry component.
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
_telemetryComponent;
|
|
64
70
|
/**
|
|
65
71
|
* Create a new instance of AuditableItemGraphService.
|
|
66
72
|
* @param options The dependencies for the auditable item graph connector.
|
|
@@ -69,9 +75,8 @@ export class AuditableItemGraphService {
|
|
|
69
75
|
this._immutableProofComponent = ComponentFactory.get(options?.immutableProofComponentType ?? "immutable-proof");
|
|
70
76
|
this._vertexStorage = EntityStorageConnectorFactory.get(options?.vertexEntityStorageType ?? "auditable-item-graph-vertex");
|
|
71
77
|
this._changesetStorage = EntityStorageConnectorFactory.get(options?.changesetEntityStorageType ?? "auditable-item-graph-changeset");
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
78
|
+
this._eventBusComponent = ComponentFactory.getIfExists(options?.eventBusComponentType);
|
|
79
|
+
this._telemetryComponent = ComponentFactory.getIfExists(options?.telemetryComponentType);
|
|
75
80
|
SchemaOrgDataTypes.registerRedirects();
|
|
76
81
|
AuditableItemGraphDataTypes.registerTypes();
|
|
77
82
|
JsonLdDataTypes.registerTypes();
|
|
@@ -83,6 +88,15 @@ export class AuditableItemGraphService {
|
|
|
83
88
|
className() {
|
|
84
89
|
return AuditableItemGraphService.CLASS_NAME;
|
|
85
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Register all AIG metrics with the telemetry component.
|
|
93
|
+
*/
|
|
94
|
+
async start() {
|
|
95
|
+
if (Is.undefined(this._telemetryComponent)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
await MetricHelper.createMetrics(this._telemetryComponent, AuditableItemGraphMetrics);
|
|
99
|
+
}
|
|
86
100
|
/**
|
|
87
101
|
* Create a new graph vertex.
|
|
88
102
|
* @param vertex The vertex to create.
|
|
@@ -124,11 +138,13 @@ export class AuditableItemGraphService {
|
|
|
124
138
|
await this.updateEdgeList(context, vertexModel, vertex.edges);
|
|
125
139
|
delete originalEntity.aliasIndex;
|
|
126
140
|
delete originalEntity.resourceTypeIndex;
|
|
127
|
-
await this.addChangeset(context, originalEntity, vertexModel, true);
|
|
141
|
+
await this.addChangeset(context, originalEntity, vertexModel, true, 0);
|
|
142
|
+
vertexModel.version = 0;
|
|
128
143
|
await this._vertexStorage.set({
|
|
129
144
|
...vertexModel,
|
|
130
145
|
...this.buildIndexes(vertexModel)
|
|
131
146
|
});
|
|
147
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerticesCreated);
|
|
132
148
|
const fullId = new Urn(AuditableItemGraphService.NAMESPACE, id).toString();
|
|
133
149
|
await this._eventBusComponent?.publish(AuditableItemGraphTopics.VertexCreated, { id: fullId });
|
|
134
150
|
return fullId;
|
|
@@ -183,14 +199,21 @@ export class AuditableItemGraphService {
|
|
|
183
199
|
await this.updateAliasList(context, newEntity, vertex.aliases);
|
|
184
200
|
await this.updateResourceList(context, newEntity, vertex.resources);
|
|
185
201
|
await this.updateEdgeList(context, newEntity, vertex.edges);
|
|
186
|
-
const
|
|
202
|
+
const nextVersion = Is.empty(vertexEntity.version)
|
|
203
|
+
? (await this.internalGetChangesets(vertexId)).length
|
|
204
|
+
: vertexEntity.version + 1;
|
|
205
|
+
const patches = await this.addChangeset(context, originalEntity, newEntity, false, nextVersion);
|
|
187
206
|
if (patches.length > 0) {
|
|
188
207
|
newEntity.dateModified = context.now;
|
|
208
|
+
newEntity.version = nextVersion;
|
|
189
209
|
const indexes = this.buildIndexes(newEntity);
|
|
190
210
|
await this._vertexStorage.set({
|
|
191
211
|
...newEntity,
|
|
192
212
|
...indexes
|
|
193
213
|
});
|
|
214
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerticesUpdated, {
|
|
215
|
+
patchCount: patches.length
|
|
216
|
+
});
|
|
194
217
|
await this._eventBusComponent?.publish(AuditableItemGraphTopics.VertexUpdated, { id: vertex.id, patches });
|
|
195
218
|
}
|
|
196
219
|
}
|
|
@@ -287,6 +310,14 @@ export class AuditableItemGraphService {
|
|
|
287
310
|
throw new NotFoundError(AuditableItemGraphService.CLASS_NAME, "vertexNotFound", id);
|
|
288
311
|
}
|
|
289
312
|
const chunk = await this.verifyChangesetChunk(vertexId, options?.verifySignatureDepth ?? VerifyDepth.None, cursor, limit);
|
|
313
|
+
if ((options?.verifySignatureDepth ?? VerifyDepth.None) !== VerifyDepth.None) {
|
|
314
|
+
if (chunk.verified) {
|
|
315
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsSucceeded);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsFailed);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
290
321
|
const changesetList = {
|
|
291
322
|
"@context": [
|
|
292
323
|
SchemaOrgContexts.Context,
|
|
@@ -340,6 +371,14 @@ export class AuditableItemGraphService {
|
|
|
340
371
|
if (verifySignatureDepth !== VerifyDepth.None) {
|
|
341
372
|
changesetModel["@context"]?.push(ImmutableProofContexts.Context);
|
|
342
373
|
changesetModel.verification = await this.verifyChangesetSignature(changesetModel);
|
|
374
|
+
if (changesetModel.verification?.verified) {
|
|
375
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsSucceeded);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsFailed, {
|
|
379
|
+
failureReason: changesetModel.verification?.failure
|
|
380
|
+
});
|
|
381
|
+
}
|
|
343
382
|
}
|
|
344
383
|
const result = await JsonLdProcessor.compact(changesetModel, changesetModel["@context"]);
|
|
345
384
|
return result;
|
|
@@ -348,6 +387,105 @@ export class AuditableItemGraphService {
|
|
|
348
387
|
throw new GeneralError(AuditableItemGraphService.CLASS_NAME, "getFailed", undefined, error);
|
|
349
388
|
}
|
|
350
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Get a graph vertex at a specific version.
|
|
392
|
+
* @param id The id of the vertex.
|
|
393
|
+
* @param versionId The id of the version (changeset id) to retrieve.
|
|
394
|
+
* @returns The vertex reconstructed at that version.
|
|
395
|
+
* @throws NotFoundError if the vertex or version is not found.
|
|
396
|
+
*/
|
|
397
|
+
async getVersion(id, versionId) {
|
|
398
|
+
Guards.stringValue(AuditableItemGraphService.CLASS_NAME, "id", id);
|
|
399
|
+
Guards.stringValue(AuditableItemGraphService.CLASS_NAME, "versionId", versionId);
|
|
400
|
+
const urnParsed = Urn.fromValidString(id);
|
|
401
|
+
if (urnParsed.namespaceIdentifier() !== AuditableItemGraphService.NAMESPACE) {
|
|
402
|
+
throw new GeneralError(AuditableItemGraphService.CLASS_NAME, "namespaceMismatch", {
|
|
403
|
+
namespace: AuditableItemGraphService.NAMESPACE,
|
|
404
|
+
id
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
const vertexId = urnParsed.namespaceSpecific(0);
|
|
409
|
+
const vertexEntity = await this._vertexStorage.get(vertexId);
|
|
410
|
+
if (Is.empty(vertexEntity)) {
|
|
411
|
+
throw new NotFoundError(AuditableItemGraphService.CLASS_NAME, "vertexNotFound", id);
|
|
412
|
+
}
|
|
413
|
+
const targetChangeset = await this._changesetStorage.get(versionId);
|
|
414
|
+
if (Is.empty(targetChangeset) || targetChangeset.vertexId !== vertexId) {
|
|
415
|
+
throw new NotFoundError(AuditableItemGraphService.CLASS_NAME, "versionNotFound", versionId);
|
|
416
|
+
}
|
|
417
|
+
const changesets = await this.internalGetChangesets(vertexId, {
|
|
418
|
+
maxVersion: targetChangeset.version
|
|
419
|
+
});
|
|
420
|
+
let entityState = {
|
|
421
|
+
id: vertexEntity.id,
|
|
422
|
+
dateCreated: vertexEntity.dateCreated,
|
|
423
|
+
organizationIdentity: vertexEntity.organizationIdentity
|
|
424
|
+
};
|
|
425
|
+
for (const changeset of changesets) {
|
|
426
|
+
entityState = JsonHelper.patch(entityState, changeset.patches);
|
|
427
|
+
}
|
|
428
|
+
const vertexModel = this.vertexEntityToJsonLd(entityState);
|
|
429
|
+
vertexModel.version = targetChangeset.version;
|
|
430
|
+
const result = await JsonLdProcessor.compact(vertexModel, vertexModel["@context"]);
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
throw new GeneralError(AuditableItemGraphService.CLASS_NAME, "getVersionFailed", undefined, error);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Get all versions of a graph vertex.
|
|
439
|
+
* @param id The id of the vertex.
|
|
440
|
+
* @param options Additional options for the operation.
|
|
441
|
+
* @param options.after Only return versions created after this ISO 8601 timestamp (exclusive).
|
|
442
|
+
* @param options.before Only return versions created before this ISO 8601 timestamp (exclusive).
|
|
443
|
+
* @returns The list of vertex versions.
|
|
444
|
+
* @throws NotFoundError if the vertex is not found.
|
|
445
|
+
*/
|
|
446
|
+
async getVersions(id, options) {
|
|
447
|
+
Guards.stringValue(AuditableItemGraphService.CLASS_NAME, "id", id);
|
|
448
|
+
const urnParsed = Urn.fromValidString(id);
|
|
449
|
+
if (urnParsed.namespaceIdentifier() !== AuditableItemGraphService.NAMESPACE) {
|
|
450
|
+
throw new GeneralError(AuditableItemGraphService.CLASS_NAME, "namespaceMismatch", {
|
|
451
|
+
namespace: AuditableItemGraphService.NAMESPACE,
|
|
452
|
+
id
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
const vertexId = urnParsed.namespaceSpecific(0);
|
|
457
|
+
const vertexEntity = await this._vertexStorage.get(vertexId);
|
|
458
|
+
if (Is.empty(vertexEntity)) {
|
|
459
|
+
throw new NotFoundError(AuditableItemGraphService.CLASS_NAME, "vertexNotFound", id);
|
|
460
|
+
}
|
|
461
|
+
const beforeDate = Coerce.dateTime(options?.before);
|
|
462
|
+
const afterDate = Coerce.dateTime(options?.after);
|
|
463
|
+
const allChangesets = await this.internalGetChangesets(vertexId, {
|
|
464
|
+
before: beforeDate?.toISOString()
|
|
465
|
+
});
|
|
466
|
+
const versions = [];
|
|
467
|
+
for (const changeset of allChangesets) {
|
|
468
|
+
const changesetDate = Coerce.dateTime(changeset.dateCreated);
|
|
469
|
+
const afterExcluded = !Is.empty(afterDate) && !Is.empty(changesetDate) && changesetDate <= afterDate;
|
|
470
|
+
if (!afterExcluded) {
|
|
471
|
+
versions.push(changeset.version ?? 0);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const versionList = {
|
|
475
|
+
"@context": [
|
|
476
|
+
SchemaOrgContexts.Context,
|
|
477
|
+
AuditableItemGraphContexts.Context,
|
|
478
|
+
AuditableItemGraphContexts.ContextCommon
|
|
479
|
+
],
|
|
480
|
+
type: [SchemaOrgTypes.ItemList, AuditableItemGraphTypes.VertexVersionList],
|
|
481
|
+
[SchemaOrgTypes.ItemListElement]: versions
|
|
482
|
+
};
|
|
483
|
+
return await JsonLdProcessor.compact(versionList, versionList["@context"]);
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
throw new GeneralError(AuditableItemGraphService.CLASS_NAME, "getVersionsFailed", undefined, error);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
351
489
|
/**
|
|
352
490
|
* Remove the verifiable storage for an item.
|
|
353
491
|
* @param id The id of the vertex to get.
|
|
@@ -474,6 +612,10 @@ export class AuditableItemGraphService {
|
|
|
474
612
|
[SchemaOrgTypes.ItemListElement]: models
|
|
475
613
|
};
|
|
476
614
|
const result = await JsonLdProcessor.compact(vertexList, vertexList["@context"]);
|
|
615
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.QueriesExecuted, {
|
|
616
|
+
resultCount: models.length,
|
|
617
|
+
hasMore: Is.stringValue(results.cursor)
|
|
618
|
+
});
|
|
477
619
|
return {
|
|
478
620
|
entries: result,
|
|
479
621
|
cursor: results.cursor
|
|
@@ -599,10 +741,47 @@ export class AuditableItemGraphService {
|
|
|
599
741
|
patchFrom: p.from,
|
|
600
742
|
patchValue: p.value
|
|
601
743
|
})),
|
|
602
|
-
proofId: changesetEntity.proofId
|
|
744
|
+
proofId: changesetEntity.proofId,
|
|
745
|
+
version: changesetEntity.version
|
|
603
746
|
};
|
|
604
747
|
return model;
|
|
605
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* Fetch all changesets for a vertex in ascending date order.
|
|
751
|
+
* @param vertexId The internal vertex id.
|
|
752
|
+
* @param options Optional filtering options.
|
|
753
|
+
* @param options.before Only fetch changesets created strictly before this ISO 8601 timestamp.
|
|
754
|
+
* @param options.maxVersion Only fetch changesets with version <= this value.
|
|
755
|
+
* @returns All changeset entities sorted ascending by dateCreated.
|
|
756
|
+
* @internal
|
|
757
|
+
*/
|
|
758
|
+
async internalGetChangesets(vertexId, options) {
|
|
759
|
+
const all = [];
|
|
760
|
+
let cursor;
|
|
761
|
+
const conditions = [
|
|
762
|
+
{ property: "vertexId", value: vertexId, comparison: ComparisonOperator.Equals }
|
|
763
|
+
];
|
|
764
|
+
if (Is.stringValue(options?.before)) {
|
|
765
|
+
conditions.push({
|
|
766
|
+
property: "dateCreated",
|
|
767
|
+
value: options.before,
|
|
768
|
+
comparison: ComparisonOperator.LessThan
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
if (!Is.empty(options?.maxVersion)) {
|
|
772
|
+
conditions.push({
|
|
773
|
+
property: "version",
|
|
774
|
+
value: options.maxVersion,
|
|
775
|
+
comparison: ComparisonOperator.LessThanOrEqual
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
do {
|
|
779
|
+
const result = await this._changesetStorage.query({ conditions, logicalOperator: LogicalOperator.And }, [{ property: "dateCreated", sortDirection: SortDirection.Ascending }], undefined, cursor);
|
|
780
|
+
all.push(...result.entities);
|
|
781
|
+
cursor = result.cursor;
|
|
782
|
+
} while (Is.stringValue(cursor));
|
|
783
|
+
return all;
|
|
784
|
+
}
|
|
606
785
|
/**
|
|
607
786
|
* Update the aliases of a vertex model.
|
|
608
787
|
* @param context The context for the operation.
|
|
@@ -617,6 +796,7 @@ export class AuditableItemGraphService {
|
|
|
617
796
|
for (const alias of active) {
|
|
618
797
|
if (!aliases?.find(a => a.id === alias.id)) {
|
|
619
798
|
alias.dateDeleted = context.now;
|
|
799
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.AliasesDeleted);
|
|
620
800
|
}
|
|
621
801
|
}
|
|
622
802
|
}
|
|
@@ -662,6 +842,7 @@ export class AuditableItemGraphService {
|
|
|
662
842
|
unique: alias.unique
|
|
663
843
|
};
|
|
664
844
|
vertex.aliases.push(model);
|
|
845
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.AliasesAdded);
|
|
665
846
|
}
|
|
666
847
|
else if (existing.aliasFormat !== alias.aliasFormat ||
|
|
667
848
|
!ObjectHelper.equal(existing.annotationObject, alias.annotationObject, false) ||
|
|
@@ -671,6 +852,7 @@ export class AuditableItemGraphService {
|
|
|
671
852
|
existing.aliasFormat = alias.aliasFormat;
|
|
672
853
|
existing.annotationObject = alias.annotationObject;
|
|
673
854
|
existing.unique = alias.unique;
|
|
855
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.AliasesModified);
|
|
674
856
|
}
|
|
675
857
|
}
|
|
676
858
|
/**
|
|
@@ -697,6 +879,7 @@ export class AuditableItemGraphService {
|
|
|
697
879
|
for (const resource of active) {
|
|
698
880
|
if (!resources?.find(a => this.getResourceId(a) === this.getResourceId(resource))) {
|
|
699
881
|
resource.dateDeleted = context.now;
|
|
882
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.ResourcesDeleted);
|
|
700
883
|
}
|
|
701
884
|
}
|
|
702
885
|
}
|
|
@@ -731,11 +914,13 @@ export class AuditableItemGraphService {
|
|
|
731
914
|
resourceObject: resource.resourceObject
|
|
732
915
|
};
|
|
733
916
|
vertex.resources.push(model);
|
|
917
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.ResourcesAdded);
|
|
734
918
|
}
|
|
735
919
|
else if (!ObjectHelper.equal(existing.resourceObject, resource.resourceObject, false)) {
|
|
736
920
|
// Existing resource found, update the resourceObject.
|
|
737
921
|
existing.dateModified = context.now;
|
|
738
922
|
existing.resourceObject = resource.resourceObject;
|
|
923
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.ResourcesModified);
|
|
739
924
|
}
|
|
740
925
|
}
|
|
741
926
|
/**
|
|
@@ -752,6 +937,7 @@ export class AuditableItemGraphService {
|
|
|
752
937
|
for (const edge of active) {
|
|
753
938
|
if (!edges?.find(e => Is.stringValue(e.id) && this.reduceEdgeId(e.id) === edge.id)) {
|
|
754
939
|
edge.dateDeleted = context.now;
|
|
940
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.EdgesDeleted);
|
|
755
941
|
}
|
|
756
942
|
}
|
|
757
943
|
}
|
|
@@ -803,6 +989,7 @@ export class AuditableItemGraphService {
|
|
|
803
989
|
edgeRelationships: edge.edgeRelationships
|
|
804
990
|
};
|
|
805
991
|
vertex.edges.push(model);
|
|
992
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.EdgesAdded);
|
|
806
993
|
}
|
|
807
994
|
else if (existing.targetId !== edge.targetId ||
|
|
808
995
|
!ArrayHelper.matches(existing.edgeRelationships, edge.edgeRelationships) ||
|
|
@@ -812,6 +999,7 @@ export class AuditableItemGraphService {
|
|
|
812
999
|
existing.dateModified = context.now;
|
|
813
1000
|
existing.edgeRelationships = edge.edgeRelationships;
|
|
814
1001
|
existing.annotationObject = edge.annotationObject;
|
|
1002
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.EdgesModified);
|
|
815
1003
|
}
|
|
816
1004
|
}
|
|
817
1005
|
/**
|
|
@@ -820,10 +1008,11 @@ export class AuditableItemGraphService {
|
|
|
820
1008
|
* @param original The original vertex.
|
|
821
1009
|
* @param updated The updated vertex.
|
|
822
1010
|
* @param isNew Whether this is a new item.
|
|
1011
|
+
* @param version The version number of the vertex after this changeset.
|
|
823
1012
|
* @returns True if there were changes.
|
|
824
1013
|
* @internal
|
|
825
1014
|
*/
|
|
826
|
-
async addChangeset(context, original, updated, isNew) {
|
|
1015
|
+
async addChangeset(context, original, updated, isNew, version) {
|
|
827
1016
|
const patches = JsonHelper.diff(original, updated);
|
|
828
1017
|
// If there is a diff set or this is the first time the item is created.
|
|
829
1018
|
if (patches.length > 0 || isNew) {
|
|
@@ -832,15 +1021,17 @@ export class AuditableItemGraphService {
|
|
|
832
1021
|
vertexId: updated.id,
|
|
833
1022
|
dateCreated: context.now,
|
|
834
1023
|
userIdentity: context.contextIds?.[ContextIdKeys.User],
|
|
835
|
-
patches
|
|
1024
|
+
patches,
|
|
1025
|
+
version
|
|
836
1026
|
};
|
|
837
1027
|
// Create the JSON-LD object we want to use for the proof
|
|
838
1028
|
// this is a subset of fixed properties from the changeset object.
|
|
839
1029
|
const reducedChangesetJsonLd = this.changesetEntityToJsonLd(original.id, ObjectHelper.pick(changesetEntity, AuditableItemGraphService._PROOF_KEYS_CHANGESET));
|
|
840
1030
|
// Create the proof for the changeset object
|
|
841
|
-
changesetEntity.proofId = await this._immutableProofComponent.create(reducedChangesetJsonLd);
|
|
1031
|
+
changesetEntity.proofId = await this._immutableProofComponent.create(JsonLdHelper.toNodeObject(reducedChangesetJsonLd));
|
|
842
1032
|
// Link the verifiable storage id to the changeset
|
|
843
1033
|
await this._changesetStorage.set(changesetEntity);
|
|
1034
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.ChangesetsCreated);
|
|
844
1035
|
return patches;
|
|
845
1036
|
}
|
|
846
1037
|
return [];
|
|
@@ -865,6 +1056,12 @@ export class AuditableItemGraphService {
|
|
|
865
1056
|
}
|
|
866
1057
|
changesets.push(...chunk.changesets);
|
|
867
1058
|
} while (Is.stringValue(cursor));
|
|
1059
|
+
if (verified) {
|
|
1060
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsSucceeded);
|
|
1061
|
+
}
|
|
1062
|
+
else {
|
|
1063
|
+
await MetricHelper.metricIncrement(this._telemetryComponent, AuditableItemGraphMetricIds.VerificationsFailed);
|
|
1064
|
+
}
|
|
868
1065
|
return {
|
|
869
1066
|
verified,
|
|
870
1067
|
changesets
|