@cratis/chronicle 0.0.1 → 0.1.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/Auditing/Causation.ts +29 -0
- package/Auditing/CausationManager.ts +51 -0
- package/Auditing/CausationType.ts +38 -0
- package/Auditing/ICausationManager.ts +29 -0
- package/Auditing/index.ts +15 -0
- package/Correlation/CorrelationId.ts +33 -0
- package/Correlation/CorrelationIdManager.ts +30 -0
- package/Correlation/ICorrelationIdAccessor.ts +15 -0
- package/Correlation/ICorrelationIdSetter.ts +21 -0
- package/Correlation/index.ts +15 -0
- package/EventSequences/EventSequence.ts +48 -50
- package/Identity/IIdentityProvider.ts +26 -0
- package/Identity/Identity.ts +61 -0
- package/Identity/IdentityProvider.ts +28 -0
- package/Identity/index.ts +14 -0
- package/Projections/Projections.ts +75 -20
- package/Projections/declarative/ProjectionBuilderFor.ts +19 -2
- package/Projections/declarative/projection.ts +6 -2
- package/Projections/modelBound/index.ts +0 -2
- package/Projections/modelBound/setFromContext.ts +20 -2
- package/README.md +1 -1
- package/Reactors/Reactors.ts +1 -0
- package/Reducers/Reducers.ts +66 -2
- package/Schemas/JsonSchemaGenerator.ts +20 -3
- package/artifacts/DefaultClientArtifactsProvider.ts +0 -5
- package/artifacts/IClientArtifactsProvider.ts +0 -3
- package/connection/Guid.ts +29 -1
- package/dist/Auditing/Causation.d.ts +22 -0
- package/dist/Auditing/Causation.d.ts.map +1 -0
- package/dist/Auditing/Causation.js +30 -0
- package/dist/Auditing/Causation.js.map +1 -0
- package/dist/Auditing/CausationManager.d.ts +23 -0
- package/dist/Auditing/CausationManager.d.ts.map +1 -0
- package/dist/Auditing/CausationManager.js +45 -0
- package/dist/Auditing/CausationManager.js.map +1 -0
- package/dist/Auditing/CausationType.d.ts +30 -0
- package/dist/Auditing/CausationType.d.ts.map +1 -0
- package/dist/Auditing/CausationType.js +36 -0
- package/dist/Auditing/CausationType.js.map +1 -0
- package/dist/Auditing/ICausationManager.d.ts +24 -0
- package/dist/Auditing/ICausationManager.d.ts.map +1 -0
- package/dist/Auditing/ICausationManager.js +4 -0
- package/dist/Auditing/ICausationManager.js.map +1 -0
- package/dist/Auditing/index.d.ts +11 -0
- package/dist/Auditing/index.d.ts.map +1 -0
- package/dist/Auditing/index.js +12 -0
- package/dist/Auditing/index.js.map +1 -0
- package/dist/Correlation/CorrelationId.d.ts +23 -0
- package/dist/Correlation/CorrelationId.d.ts.map +1 -0
- package/dist/Correlation/CorrelationId.js +32 -0
- package/dist/Correlation/CorrelationId.js.map +1 -0
- package/dist/Correlation/CorrelationIdManager.d.ts +17 -0
- package/dist/Correlation/CorrelationIdManager.d.ts.map +1 -0
- package/dist/Correlation/CorrelationIdManager.js +24 -0
- package/dist/Correlation/CorrelationIdManager.js.map +1 -0
- package/dist/Correlation/ICorrelationIdAccessor.d.ts +12 -0
- package/dist/Correlation/ICorrelationIdAccessor.d.ts.map +1 -0
- package/dist/Correlation/ICorrelationIdAccessor.js +4 -0
- package/dist/Correlation/ICorrelationIdAccessor.js.map +1 -0
- package/dist/Correlation/ICorrelationIdSetter.d.ts +17 -0
- package/dist/Correlation/ICorrelationIdSetter.d.ts.map +1 -0
- package/dist/Correlation/ICorrelationIdSetter.js +4 -0
- package/dist/Correlation/ICorrelationIdSetter.js.map +1 -0
- package/dist/Correlation/index.d.ts +11 -0
- package/dist/Correlation/index.d.ts.map +1 -0
- package/dist/Correlation/index.js +11 -0
- package/dist/Correlation/index.js.map +1 -0
- package/dist/EventSequences/EventSequence.d.ts.map +1 -1
- package/dist/EventSequences/EventSequence.js +45 -46
- package/dist/EventSequences/EventSequence.js.map +1 -1
- package/dist/Identity/IIdentityProvider.d.ts +21 -0
- package/dist/Identity/IIdentityProvider.d.ts.map +1 -0
- package/dist/Identity/IIdentityProvider.js +4 -0
- package/dist/Identity/IIdentityProvider.js.map +1 -0
- package/dist/Identity/Identity.d.ts +37 -0
- package/dist/Identity/Identity.d.ts.map +1 -0
- package/dist/Identity/Identity.js +60 -0
- package/dist/Identity/Identity.js.map +1 -0
- package/dist/Identity/IdentityProvider.d.ts +15 -0
- package/dist/Identity/IdentityProvider.d.ts.map +1 -0
- package/dist/Identity/IdentityProvider.js +23 -0
- package/dist/Identity/IdentityProvider.js.map +1 -0
- package/dist/Identity/index.d.ts +10 -0
- package/dist/Identity/index.d.ts.map +1 -0
- package/dist/Identity/index.js +11 -0
- package/dist/Identity/index.js.map +1 -0
- package/dist/Projections/Projections.d.ts +9 -1
- package/dist/Projections/Projections.d.ts.map +1 -1
- package/dist/Projections/Projections.js +70 -19
- package/dist/Projections/Projections.js.map +1 -1
- package/dist/Projections/declarative/ProjectionBuilderFor.d.ts +6 -0
- package/dist/Projections/declarative/ProjectionBuilderFor.d.ts.map +1 -1
- package/dist/Projections/declarative/ProjectionBuilderFor.js +18 -2
- package/dist/Projections/declarative/ProjectionBuilderFor.js.map +1 -1
- package/dist/Projections/declarative/projection.d.ts +5 -1
- package/dist/Projections/declarative/projection.d.ts.map +1 -1
- package/dist/Projections/declarative/projection.js +3 -2
- package/dist/Projections/declarative/projection.js.map +1 -1
- package/dist/Projections/modelBound/index.d.ts +0 -2
- package/dist/Projections/modelBound/index.d.ts.map +1 -1
- package/dist/Projections/modelBound/index.js +0 -1
- package/dist/Projections/modelBound/index.js.map +1 -1
- package/dist/Projections/modelBound/setFromContext.d.ts +4 -1
- package/dist/Projections/modelBound/setFromContext.d.ts.map +1 -1
- package/dist/Projections/modelBound/setFromContext.js +12 -7
- package/dist/Projections/modelBound/setFromContext.js.map +1 -1
- package/dist/Reactors/Reactors.d.ts.map +1 -1
- package/dist/Reactors/Reactors.js +1 -0
- package/dist/Reactors/Reactors.js.map +1 -1
- package/dist/Reducers/Reducers.d.ts +2 -0
- package/dist/Reducers/Reducers.d.ts.map +1 -1
- package/dist/Reducers/Reducers.js +60 -2
- package/dist/Reducers/Reducers.js.map +1 -1
- package/dist/Schemas/JsonSchemaGenerator.d.ts.map +1 -1
- package/dist/Schemas/JsonSchemaGenerator.js +17 -3
- package/dist/Schemas/JsonSchemaGenerator.js.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts +0 -2
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.js +0 -4
- package/dist/artifacts/DefaultClientArtifactsProvider.js.map +1 -1
- package/dist/artifacts/IClientArtifactsProvider.d.ts +0 -2
- package/dist/artifacts/IClientArtifactsProvider.d.ts.map +1 -1
- package/dist/connection/Guid.d.ts +8 -1
- package/dist/connection/Guid.d.ts.map +1 -1
- package/dist/connection/Guid.js +24 -1
- package/dist/connection/Guid.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/sinks/WellKnownSinks.d.ts +15 -0
- package/dist/sinks/WellKnownSinks.d.ts.map +1 -0
- package/dist/sinks/WellKnownSinks.js +17 -0
- package/dist/sinks/WellKnownSinks.js.map +1 -0
- package/dist/sinks/index.d.ts +2 -0
- package/dist/sinks/index.d.ts.map +1 -0
- package/dist/sinks/index.js +4 -0
- package/dist/sinks/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/DecoratorType.d.ts +1 -3
- package/dist/types/DecoratorType.d.ts.map +1 -1
- package/dist/types/DecoratorType.js +0 -2
- package/dist/types/DecoratorType.js.map +1 -1
- package/index.ts +4 -0
- package/package.json +2 -2
- package/sinks/WellKnownSinks.ts +21 -0
- package/sinks/index.ts +4 -0
- package/types/DecoratorType.ts +1 -4
- package/Projections/modelBound/modelBound.ts +0 -59
- package/dist/Grpc.d.ts +0 -19
- package/dist/Grpc.d.ts.map +0 -1
- package/dist/Grpc.js +0 -33
- package/dist/Grpc.js.map +0 -1
- package/dist/Projections/modelBound/modelBound.d.ts +0 -31
- package/dist/Projections/modelBound/modelBound.d.ts.map +0 -1
- package/dist/Projections/modelBound/modelBound.js +0 -39
- package/dist/Projections/modelBound/modelBound.js.map +0 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { CausationType } from './CausationType';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a causation instance.
|
|
8
|
+
*/
|
|
9
|
+
export class Causation {
|
|
10
|
+
/**
|
|
11
|
+
* Creates an unknown causation instance.
|
|
12
|
+
* @returns A new {@link Causation} with the current time, type set to {@link CausationType.unknown}, and empty properties.
|
|
13
|
+
*/
|
|
14
|
+
static unknown(): Causation {
|
|
15
|
+
return new Causation(new Date(), CausationType.unknown, {});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Initializes a new instance of the {@link Causation} class.
|
|
20
|
+
* @param occurred - When it occurred.
|
|
21
|
+
* @param type - Type of causation.
|
|
22
|
+
* @param properties - Any properties associated with the causation.
|
|
23
|
+
*/
|
|
24
|
+
constructor(
|
|
25
|
+
readonly occurred: Date,
|
|
26
|
+
readonly type: CausationType,
|
|
27
|
+
readonly properties: Readonly<Record<string, string>>
|
|
28
|
+
) {}
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
|
+
import { Causation } from './Causation';
|
|
6
|
+
import { CausationType } from './CausationType';
|
|
7
|
+
import { ICausationManager } from './ICausationManager';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Implements {@link ICausationManager} using {@link AsyncLocalStorage} to scope the causation chain to the active async call context.
|
|
11
|
+
*/
|
|
12
|
+
export class CausationManager implements ICausationManager {
|
|
13
|
+
private readonly _storage = new AsyncLocalStorage<Causation[]>();
|
|
14
|
+
private _root: Causation = new Causation(new Date(), CausationType.root, {});
|
|
15
|
+
|
|
16
|
+
/** @inheritdoc */
|
|
17
|
+
get root(): Causation {
|
|
18
|
+
return this._root;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @inheritdoc */
|
|
22
|
+
getCurrentChain(): ReadonlyArray<Causation> {
|
|
23
|
+
const chain = this._getOrInitChain();
|
|
24
|
+
return chain;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @inheritdoc */
|
|
28
|
+
add(type: CausationType, properties: Record<string, string>): void {
|
|
29
|
+
const chain = this._getOrInitChain();
|
|
30
|
+
chain.push(new Causation(new Date(), type, properties));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Defines the root causation for the current process.
|
|
35
|
+
* @param properties - Properties associated with the root causation.
|
|
36
|
+
*/
|
|
37
|
+
defineRoot(properties: Record<string, string>): void {
|
|
38
|
+
this._root = new Causation(new Date(), CausationType.root, properties);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private _getOrInitChain(): Causation[] {
|
|
42
|
+
let chain = this._storage.getStore();
|
|
43
|
+
if (chain === undefined) {
|
|
44
|
+
chain = [this._root];
|
|
45
|
+
this._storage.enterWith(chain);
|
|
46
|
+
} else if (chain.length === 0) {
|
|
47
|
+
chain.push(this._root);
|
|
48
|
+
}
|
|
49
|
+
return chain;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents a type of causation.
|
|
6
|
+
*/
|
|
7
|
+
export class CausationType {
|
|
8
|
+
/**
|
|
9
|
+
* Represents the root causation type.
|
|
10
|
+
*/
|
|
11
|
+
static readonly root = new CausationType('Root');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Represents the unknown causation type.
|
|
15
|
+
*/
|
|
16
|
+
static readonly unknown = new CausationType('Unknown');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Represents the causation type for a single event append via the TypeScript client.
|
|
20
|
+
*/
|
|
21
|
+
static readonly appendEvent = new CausationType('TypeScriptClient.Append');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Represents the causation type for a batch event append via the TypeScript client.
|
|
25
|
+
*/
|
|
26
|
+
static readonly appendManyEvents = new CausationType('TypeScriptClient.AppendMany');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initializes a new instance of the {@link CausationType} class.
|
|
30
|
+
* @param name - The name of the causation type.
|
|
31
|
+
*/
|
|
32
|
+
constructor(readonly name: string) {}
|
|
33
|
+
|
|
34
|
+
/** @inheritdoc */
|
|
35
|
+
toString(): string {
|
|
36
|
+
return this.name;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { Causation } from './Causation';
|
|
5
|
+
import { CausationType } from './CausationType';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Defines a system that manages causation for the active call context.
|
|
9
|
+
*/
|
|
10
|
+
export interface ICausationManager {
|
|
11
|
+
/**
|
|
12
|
+
* Gets the root causation.
|
|
13
|
+
*/
|
|
14
|
+
readonly root: Causation;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Gets the full causation chain for the current call context.
|
|
18
|
+
* The chain always starts with {@link root} if no other causation has been added.
|
|
19
|
+
* @returns An array of {@link Causation} representing the current chain.
|
|
20
|
+
*/
|
|
21
|
+
getCurrentChain(): ReadonlyArray<Causation>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Adds a causation entry to the current chain.
|
|
25
|
+
* @param type - The type of causation to add.
|
|
26
|
+
* @param properties - Properties associated with the causation.
|
|
27
|
+
*/
|
|
28
|
+
add(type: CausationType, properties: Record<string, string>): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
export { Causation } from './Causation';
|
|
5
|
+
export { CausationType } from './CausationType';
|
|
6
|
+
export type { ICausationManager } from './ICausationManager';
|
|
7
|
+
export { CausationManager } from './CausationManager';
|
|
8
|
+
|
|
9
|
+
import { CausationManager } from './CausationManager';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The default singleton {@link CausationManager} for the process.
|
|
13
|
+
* Use this to manage the causation chain for the current async call context.
|
|
14
|
+
*/
|
|
15
|
+
export const causationManager = new CausationManager();
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { Guid } from '@cratis/fundamentals';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a correlation identifier used to track operations across call boundaries.
|
|
8
|
+
*/
|
|
9
|
+
export class CorrelationId {
|
|
10
|
+
/**
|
|
11
|
+
* A well-known {@link CorrelationId} representing an unset/empty value.
|
|
12
|
+
*/
|
|
13
|
+
static readonly notSet = new CorrelationId('00000000-0000-0000-0000-000000000000');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a new unique {@link CorrelationId}.
|
|
17
|
+
* @returns A new {@link CorrelationId} backed by a freshly generated GUID.
|
|
18
|
+
*/
|
|
19
|
+
static create(): CorrelationId {
|
|
20
|
+
return new CorrelationId(Guid.create().toString());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initializes a new instance of the {@link CorrelationId} class.
|
|
25
|
+
* @param value - The string value of the correlation identifier.
|
|
26
|
+
*/
|
|
27
|
+
constructor(readonly value: string) {}
|
|
28
|
+
|
|
29
|
+
/** @inheritdoc */
|
|
30
|
+
toString(): string {
|
|
31
|
+
return this.value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
|
+
import { CorrelationId } from './CorrelationId';
|
|
6
|
+
import { ICorrelationIdAccessor } from './ICorrelationIdAccessor';
|
|
7
|
+
import { ICorrelationIdSetter } from './ICorrelationIdSetter';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Implements both {@link ICorrelationIdAccessor} and {@link ICorrelationIdSetter},
|
|
11
|
+
* using {@link AsyncLocalStorage} to scope the correlation identifier to the active async call context.
|
|
12
|
+
*/
|
|
13
|
+
export class CorrelationIdManager implements ICorrelationIdAccessor, ICorrelationIdSetter {
|
|
14
|
+
private readonly _storage = new AsyncLocalStorage<CorrelationId>();
|
|
15
|
+
|
|
16
|
+
/** @inheritdoc */
|
|
17
|
+
get current(): CorrelationId {
|
|
18
|
+
return this._storage.getStore() ?? CorrelationId.create();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** @inheritdoc */
|
|
22
|
+
setCurrent(correlationId: CorrelationId): void {
|
|
23
|
+
this._storage.enterWith(correlationId);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @inheritdoc */
|
|
27
|
+
clear(): void {
|
|
28
|
+
this._storage.enterWith(CorrelationId.create());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { CorrelationId } from './CorrelationId';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Defines the read side of a correlation identifier provider scoped to the active call context.
|
|
8
|
+
*/
|
|
9
|
+
export interface ICorrelationIdAccessor {
|
|
10
|
+
/**
|
|
11
|
+
* Gets the current correlation identifier for the active call context.
|
|
12
|
+
* @returns The current {@link CorrelationId}.
|
|
13
|
+
*/
|
|
14
|
+
readonly current: CorrelationId;
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { CorrelationId } from './CorrelationId';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Defines the write side of a correlation identifier provider scoped to the active call context.
|
|
8
|
+
*/
|
|
9
|
+
export interface ICorrelationIdSetter {
|
|
10
|
+
/**
|
|
11
|
+
* Sets the current correlation identifier for the active call context.
|
|
12
|
+
* @param correlationId - The {@link CorrelationId} to set.
|
|
13
|
+
*/
|
|
14
|
+
setCurrent(correlationId: CorrelationId): void;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Clears the current correlation identifier for the active call context,
|
|
18
|
+
* causing the next access to generate a new unique identifier.
|
|
19
|
+
*/
|
|
20
|
+
clear(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
export { CorrelationId } from './CorrelationId';
|
|
5
|
+
export type { ICorrelationIdAccessor } from './ICorrelationIdAccessor';
|
|
6
|
+
export type { ICorrelationIdSetter } from './ICorrelationIdSetter';
|
|
7
|
+
export { CorrelationIdManager } from './CorrelationIdManager';
|
|
8
|
+
|
|
9
|
+
import { CorrelationIdManager } from './CorrelationIdManager';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The default singleton {@link CorrelationIdManager} for the process.
|
|
13
|
+
* Use this to get and set the correlation identifier for the current async call context.
|
|
14
|
+
*/
|
|
15
|
+
export const correlationIdManager = new CorrelationIdManager();
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Cratis. All rights reserved.
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
ChronicleConnection,
|
|
6
|
-
Guid as ContractsGuid
|
|
7
|
-
} from '../connection';
|
|
4
|
+
import { ChronicleConnection } from '../connection';
|
|
8
5
|
import { SpanStatusCode } from '@opentelemetry/api';
|
|
9
6
|
import { Guid } from '@cratis/fundamentals';
|
|
10
7
|
import { getEventTypeFor } from '../Events/eventTypeDecorator';
|
|
@@ -16,6 +13,10 @@ import { EventSequenceId } from './EventSequenceId';
|
|
|
16
13
|
import { EventSequenceNumber } from './EventSequenceNumber';
|
|
17
14
|
import { ChronicleTracer } from '../Tracing';
|
|
18
15
|
import { ChronicleMetrics } from '../Metrics';
|
|
16
|
+
import { identityProvider, Identity } from '../Identity';
|
|
17
|
+
import { causationManager, CausationType } from '../Auditing';
|
|
18
|
+
import { correlationIdManager } from '../Correlation';
|
|
19
|
+
import { toContractsGuid } from '../connection/Guid';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Implements {@link IEventSequence} by communicating with the Chronicle Kernel
|
|
@@ -33,10 +34,14 @@ export class EventSequence implements IEventSequence {
|
|
|
33
34
|
async append(eventSourceId: string, event: object, options?: AppendOptions): Promise<AppendResult> {
|
|
34
35
|
const eventType = getEventTypeFor(event.constructor as Function);
|
|
35
36
|
const correlationId = options?.correlationId === undefined
|
|
36
|
-
? Guid.
|
|
37
|
+
? Guid.as(correlationIdManager.current.value)
|
|
37
38
|
: Guid.as(options.correlationId);
|
|
38
39
|
const content = JSON.stringify(event);
|
|
39
40
|
|
|
41
|
+
causationManager.add(CausationType.appendEvent, { eventType: eventType.id.value });
|
|
42
|
+
const causationChain = causationManager.getCurrentChain();
|
|
43
|
+
const identity = identityProvider.getCurrent();
|
|
44
|
+
|
|
40
45
|
const metricAttributes = {
|
|
41
46
|
'chronicle.event_store': this._eventStoreName,
|
|
42
47
|
'chronicle.namespace': this._namespace,
|
|
@@ -68,17 +73,12 @@ export class EventSequence implements IEventSequence {
|
|
|
68
73
|
Tombstone: eventType.tombstone
|
|
69
74
|
},
|
|
70
75
|
Content: content,
|
|
71
|
-
Causation:
|
|
72
|
-
Occurred: { Value:
|
|
73
|
-
Type:
|
|
74
|
-
Properties: {}
|
|
75
|
-
}
|
|
76
|
-
CausedBy:
|
|
77
|
-
Subject: '5d032c92-9d5e-41eb-947a-ee5314ed0032',
|
|
78
|
-
Name: '[System]',
|
|
79
|
-
UserName: '[System]',
|
|
80
|
-
OnBehalfOf: undefined
|
|
81
|
-
},
|
|
76
|
+
Causation: causationChain.map(c => ({
|
|
77
|
+
Occurred: { Value: c.occurred.toISOString() },
|
|
78
|
+
Type: c.type.name,
|
|
79
|
+
Properties: { ...c.properties }
|
|
80
|
+
})),
|
|
81
|
+
CausedBy: toContractsCausedBy(identity),
|
|
82
82
|
ConcurrencyScope: {
|
|
83
83
|
// ulong.MaxValue sent as BigInt so the server recognises it as ConcurrencyScope.None (no validation)
|
|
84
84
|
SequenceNumber: 18446744073709551615n as unknown as number,
|
|
@@ -137,9 +137,13 @@ export class EventSequence implements IEventSequence {
|
|
|
137
137
|
/** @inheritdoc */
|
|
138
138
|
async appendMany(eventSourceId: string, events: object[], options?: AppendOptions): Promise<AppendResult[]> {
|
|
139
139
|
const correlationId = options?.correlationId === undefined
|
|
140
|
-
? Guid.
|
|
140
|
+
? Guid.as(correlationIdManager.current.value)
|
|
141
141
|
: Guid.as(options.correlationId);
|
|
142
142
|
|
|
143
|
+
causationManager.add(CausationType.appendManyEvents, { count: String(events.length) });
|
|
144
|
+
const batchCausationChain = causationManager.getCurrentChain();
|
|
145
|
+
const identity = identityProvider.getCurrent();
|
|
146
|
+
|
|
143
147
|
const eventsToAppend = events.map(event => {
|
|
144
148
|
const eventType = getEventTypeFor(event.constructor as Function);
|
|
145
149
|
return {
|
|
@@ -153,17 +157,12 @@ export class EventSequence implements IEventSequence {
|
|
|
153
157
|
Tombstone: eventType.tombstone
|
|
154
158
|
},
|
|
155
159
|
Content: JSON.stringify(event),
|
|
156
|
-
Causation:
|
|
157
|
-
Occurred: { Value:
|
|
158
|
-
Type:
|
|
159
|
-
Properties: {}
|
|
160
|
-
}
|
|
161
|
-
CausedBy:
|
|
162
|
-
Subject: '5d032c92-9d5e-41eb-947a-ee5314ed0032',
|
|
163
|
-
Name: '[System]',
|
|
164
|
-
UserName: '[System]',
|
|
165
|
-
OnBehalfOf: undefined
|
|
166
|
-
},
|
|
160
|
+
Causation: batchCausationChain.map(c => ({
|
|
161
|
+
Occurred: { Value: c.occurred.toISOString() },
|
|
162
|
+
Type: c.type.name,
|
|
163
|
+
Properties: { ...c.properties }
|
|
164
|
+
})),
|
|
165
|
+
CausedBy: toContractsCausedBy(identity),
|
|
167
166
|
ConcurrencyScope: {
|
|
168
167
|
SequenceNumber: 18446744073709551615n as unknown as number,
|
|
169
168
|
EventSourceId: false,
|
|
@@ -199,17 +198,12 @@ export class EventSequence implements IEventSequence {
|
|
|
199
198
|
EventSequenceId: this.id.value,
|
|
200
199
|
CorrelationId: toContractsGuid(correlationId),
|
|
201
200
|
Events: eventsToAppend,
|
|
202
|
-
Causation:
|
|
203
|
-
Occurred: { Value:
|
|
204
|
-
Type:
|
|
205
|
-
Properties: {}
|
|
206
|
-
}
|
|
207
|
-
CausedBy:
|
|
208
|
-
Subject: '5d032c92-9d5e-41eb-947a-ee5314ed0032',
|
|
209
|
-
Name: '[System]',
|
|
210
|
-
UserName: '[System]',
|
|
211
|
-
OnBehalfOf: undefined
|
|
212
|
-
},
|
|
201
|
+
Causation: batchCausationChain.map(c => ({
|
|
202
|
+
Occurred: { Value: c.occurred.toISOString() },
|
|
203
|
+
Type: c.type.name,
|
|
204
|
+
Properties: { ...c.properties }
|
|
205
|
+
})),
|
|
206
|
+
CausedBy: toContractsCausedBy(identity),
|
|
213
207
|
ConcurrencyScopes: {}
|
|
214
208
|
});
|
|
215
209
|
|
|
@@ -355,18 +349,22 @@ export class EventSequence implements IEventSequence {
|
|
|
355
349
|
* @param guid - The Guid to convert.
|
|
356
350
|
* @returns The converted protobuf Guid with fixed64-safe hi/lo values.
|
|
357
351
|
*/
|
|
358
|
-
function toContractsGuid(guid: Guid): ContractsGuid {
|
|
359
|
-
const hex = guid.toString().replace(/-/g, '');
|
|
360
|
-
const hi = BigInt(`0x${hex.substring(0, 16)}`);
|
|
361
|
-
const lo = BigInt(`0x${hex.substring(16, 32)}`);
|
|
362
352
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Converts an {@link Identity} into the CausedBy shape used by Chronicle contracts.
|
|
355
|
+
* @param identity - The identity to convert.
|
|
356
|
+
* @returns The contracts CausedBy object.
|
|
357
|
+
*/
|
|
358
|
+
function toContractsCausedBy(identity: Identity): object {
|
|
359
|
+
const result: Record<string, unknown> = {
|
|
360
|
+
Subject: identity.subject,
|
|
361
|
+
Name: identity.name,
|
|
362
|
+
UserName: identity.userName,
|
|
363
|
+
OnBehalfOf: undefined
|
|
370
364
|
};
|
|
365
|
+
if (identity.onBehalfOf !== undefined) {
|
|
366
|
+
result.OnBehalfOf = toContractsCausedBy(identity.onBehalfOf);
|
|
367
|
+
}
|
|
368
|
+
return result;
|
|
371
369
|
}
|
|
372
370
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { Identity } from './Identity';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Defines a system that can provide and manage the current {@link Identity} for the active call context.
|
|
8
|
+
*/
|
|
9
|
+
export interface IIdentityProvider {
|
|
10
|
+
/**
|
|
11
|
+
* Gets the current identity for the active call context.
|
|
12
|
+
* @returns The current {@link Identity}, or {@link Identity.system} if none has been set.
|
|
13
|
+
*/
|
|
14
|
+
getCurrent(): Identity;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Sets the current identity for the active call context.
|
|
18
|
+
* @param identity - The {@link Identity} to set.
|
|
19
|
+
*/
|
|
20
|
+
setCurrentIdentity(identity: Identity): void;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Clears the current identity for the active call context, resetting it to {@link Identity.system}.
|
|
24
|
+
*/
|
|
25
|
+
clearCurrentIdentity(): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents an identity of something that is responsible for causing a state change.
|
|
6
|
+
* An identity can be a user, a system, a service or anything else that can be identified.
|
|
7
|
+
*/
|
|
8
|
+
export class Identity {
|
|
9
|
+
/**
|
|
10
|
+
* The identity used when not set.
|
|
11
|
+
*/
|
|
12
|
+
static readonly notSet = new Identity('1efc9b81-0612-4466-962c-86acc4e9a028', '[Not Set]', '[Not Set]');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The identity used when the identity is not known.
|
|
16
|
+
*/
|
|
17
|
+
static readonly unknown = new Identity('3321cf62-db16-425e-8173-99fcfefe11dd', '[Unknown]', '[Unknown]');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The identity used when the system is the cause.
|
|
21
|
+
*/
|
|
22
|
+
static readonly system = new Identity('5d032c92-9d5e-41eb-947a-ee5314ed0032', '[System]', '[System]');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Initializes a new instance of the {@link Identity} class.
|
|
26
|
+
* @param subject - The identifier of the identity, referred to as subject.
|
|
27
|
+
* @param name - Name of the identity.
|
|
28
|
+
* @param userName - Optional username, defaults to empty string.
|
|
29
|
+
* @param onBehalfOf - Optional behalf of {@link Identity}.
|
|
30
|
+
*/
|
|
31
|
+
constructor(
|
|
32
|
+
readonly subject: string,
|
|
33
|
+
readonly name: string,
|
|
34
|
+
readonly userName: string = '',
|
|
35
|
+
readonly onBehalfOf?: Identity
|
|
36
|
+
) {}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns a new {@link Identity} chain with duplicate subjects removed.
|
|
40
|
+
* The first occurrence of each subject is kept.
|
|
41
|
+
* @returns A new {@link Identity} with duplicates removed from the chain.
|
|
42
|
+
*/
|
|
43
|
+
withoutDuplicates(): Identity {
|
|
44
|
+
const seen = new Set<string>();
|
|
45
|
+
const chain: Identity[] = [];
|
|
46
|
+
let current: Identity | undefined = this;
|
|
47
|
+
while (current !== undefined) {
|
|
48
|
+
if (!seen.has(current.subject)) {
|
|
49
|
+
seen.add(current.subject);
|
|
50
|
+
chain.push(current);
|
|
51
|
+
}
|
|
52
|
+
current = current.onBehalfOf;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let result: Identity | undefined;
|
|
56
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
57
|
+
result = new Identity(chain[i].subject, chain[i].name, chain[i].userName, result);
|
|
58
|
+
}
|
|
59
|
+
return result!;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
|
+
import { Identity } from './Identity';
|
|
6
|
+
import { IIdentityProvider } from './IIdentityProvider';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Implements {@link IIdentityProvider} using {@link AsyncLocalStorage} to scope the identity to the active async call context.
|
|
10
|
+
*/
|
|
11
|
+
export class IdentityProvider implements IIdentityProvider {
|
|
12
|
+
private readonly _storage = new AsyncLocalStorage<Identity>();
|
|
13
|
+
|
|
14
|
+
/** @inheritdoc */
|
|
15
|
+
getCurrent(): Identity {
|
|
16
|
+
return this._storage.getStore() ?? Identity.system;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** @inheritdoc */
|
|
20
|
+
setCurrentIdentity(identity: Identity): void {
|
|
21
|
+
this._storage.enterWith(identity);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** @inheritdoc */
|
|
25
|
+
clearCurrentIdentity(): void {
|
|
26
|
+
this._storage.enterWith(Identity.system);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
export { Identity } from './Identity';
|
|
5
|
+
export type { IIdentityProvider } from './IIdentityProvider';
|
|
6
|
+
export { IdentityProvider } from './IdentityProvider';
|
|
7
|
+
|
|
8
|
+
import { IdentityProvider } from './IdentityProvider';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The default singleton {@link IdentityProvider} for the process.
|
|
12
|
+
* Use this to get and set the identity for the current async call context.
|
|
13
|
+
*/
|
|
14
|
+
export const identityProvider = new IdentityProvider();
|