@othree.io/chisel-sdk 3.1.0 → 5.0.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/README.md +207 -1
- package/lib/cjs/aws/index.d.ts.map +1 -0
- package/lib/cjs/aws/index.js.map +1 -0
- package/lib/cjs/aws/read.d.ts +44 -0
- package/lib/cjs/aws/read.d.ts.map +1 -0
- package/lib/{aws → cjs/aws}/read.js +65 -48
- package/lib/cjs/aws/read.js.map +1 -0
- package/lib/cjs/aws/write.d.ts +23 -0
- package/lib/cjs/aws/write.d.ts.map +1 -0
- package/lib/{aws → cjs/aws}/write.js +56 -34
- package/lib/cjs/aws/write.js.map +1 -0
- package/lib/cjs/iac/index.d.ts +28 -0
- package/lib/cjs/iac/index.d.ts.map +1 -0
- package/lib/{iac → cjs/iac}/index.js +23 -8
- package/lib/cjs/iac/index.js.map +1 -0
- package/lib/cjs/iac/read.d.ts +50 -0
- package/lib/cjs/iac/read.d.ts.map +1 -0
- package/lib/{iac → cjs/iac}/read.js +60 -33
- package/lib/cjs/iac/read.js.map +1 -0
- package/lib/cjs/iac/shared.d.ts +14 -0
- package/lib/cjs/iac/shared.d.ts.map +1 -0
- package/lib/{iac → cjs/iac}/shared.js +12 -8
- package/lib/cjs/iac/shared.js.map +1 -0
- package/lib/cjs/iac/types.d.ts +28 -0
- package/lib/cjs/iac/types.d.ts.map +1 -0
- package/lib/cjs/iac/types.js +26 -0
- package/lib/cjs/iac/types.js.map +1 -0
- package/lib/cjs/iac/write.d.ts +32 -0
- package/lib/cjs/iac/write.d.ts.map +1 -0
- package/lib/{iac → cjs/iac}/write.js +40 -17
- package/lib/cjs/iac/write.js.map +1 -0
- package/lib/cjs/index.d.ts.map +1 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/esm/aws/index.js +3 -0
- package/lib/esm/aws/index.js.map +1 -0
- package/lib/esm/aws/read.js +119 -0
- package/lib/esm/aws/read.js.map +1 -0
- package/lib/esm/aws/write.js +99 -0
- package/lib/esm/aws/write.js.map +1 -0
- package/lib/esm/iac/index.js +66 -0
- package/lib/esm/iac/index.js.map +1 -0
- package/lib/esm/iac/read.js +168 -0
- package/lib/esm/iac/read.js.map +1 -0
- package/lib/esm/iac/shared.js +32 -0
- package/lib/esm/iac/shared.js.map +1 -0
- package/lib/esm/iac/types.js +23 -0
- package/lib/esm/iac/types.js.map +1 -0
- package/lib/esm/iac/write.js +92 -0
- package/lib/esm/iac/write.js.map +1 -0
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -0
- package/package.json +50 -21
- package/.gitlab-ci.yml +0 -29
- package/lib/aws/index.d.ts.map +0 -1
- package/lib/aws/index.js.map +0 -1
- package/lib/aws/read.d.ts +0 -35
- package/lib/aws/read.d.ts.map +0 -1
- package/lib/aws/read.js.map +0 -1
- package/lib/aws/write.d.ts +0 -24
- package/lib/aws/write.d.ts.map +0 -1
- package/lib/aws/write.js.map +0 -1
- package/lib/iac/index.d.ts +0 -24
- package/lib/iac/index.d.ts.map +0 -1
- package/lib/iac/index.js.map +0 -1
- package/lib/iac/read.d.ts +0 -47
- package/lib/iac/read.d.ts.map +0 -1
- package/lib/iac/read.js.map +0 -1
- package/lib/iac/shared.d.ts +0 -12
- package/lib/iac/shared.d.ts.map +0 -1
- package/lib/iac/shared.js.map +0 -1
- package/lib/iac/types.d.ts +0 -13
- package/lib/iac/types.d.ts.map +0 -1
- package/lib/iac/types.js +0 -14
- package/lib/iac/types.js.map +0 -1
- package/lib/iac/write.d.ts +0 -29
- package/lib/iac/write.d.ts.map +0 -1
- package/lib/iac/write.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/release.config.js +0 -4
- /package/lib/{aws → cjs/aws}/index.d.ts +0 -0
- /package/lib/{aws → cjs/aws}/index.js +0 -0
- /package/lib/{index.d.ts → cjs/index.d.ts} +0 -0
- /package/lib/{index.js → cjs/index.js} +0 -0
|
@@ -1,46 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createWriteServicesStack = exports.createWritePersistenceStack = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
4
5
|
const cdk_1 = require("@othree.io/cdk");
|
|
5
|
-
const core_1 = require("@othree.io/cdk/lib/core");
|
|
6
6
|
const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
|
|
7
7
|
const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
|
|
8
8
|
const aws_sns_1 = require("aws-cdk-lib/aws-sns");
|
|
9
9
|
const optional_1 = require("@othree.io/optional");
|
|
10
10
|
const createWritePersistenceStack = (app, context, input) => {
|
|
11
|
-
const withId = cdk_1.core.id(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const withId = cdk_1.core.id({
|
|
12
|
+
version: input.version,
|
|
13
|
+
input: {
|
|
14
|
+
prefix: (0, optional_1.Optional)(context.project.naming).map(_ => _.prefix).orElse(undefined),
|
|
15
|
+
suffix: context.project.env,
|
|
16
|
+
},
|
|
14
17
|
});
|
|
15
|
-
const
|
|
18
|
+
const defaultConfiguration = cdk_1.stack.withDefaultConfiguration(input.projectMetadata, 'WritePersistenceStack');
|
|
19
|
+
const writePersistenceStack = cdk_1.stack.withStack({ defaultConfiguration, app })({
|
|
16
20
|
id: withId(`${input.boundedContext}-WritePersistence`),
|
|
17
21
|
});
|
|
18
22
|
const tableName = withId(`${input.boundedContext}-Events`);
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
cdk_1.dynamo.withTable({
|
|
24
|
+
defaultConfiguration: { billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST },
|
|
25
|
+
stack: writePersistenceStack,
|
|
26
|
+
})({
|
|
27
|
+
id: tableName,
|
|
28
|
+
partitionKey: { name: 'contextId', type: aws_dynamodb_1.AttributeType.STRING },
|
|
29
|
+
sortKey: { name: 'eventId', type: aws_dynamodb_1.AttributeType.STRING },
|
|
30
|
+
});
|
|
31
|
+
const account = cdk_1.core.getStackAccountFromEnv();
|
|
21
32
|
return Object.freeze({
|
|
22
33
|
stack: writePersistenceStack,
|
|
23
34
|
eventsTable: `arn:aws:dynamodb:${account.region}:${account.accountId}:table/${tableName}`,
|
|
24
35
|
});
|
|
25
36
|
};
|
|
26
37
|
exports.createWritePersistenceStack = createWritePersistenceStack;
|
|
38
|
+
const defaultLambdaConfiguration = {
|
|
39
|
+
runtime: aws_lambda_1.Runtime.NODEJS_20_X,
|
|
40
|
+
tracing: aws_lambda_1.Tracing.ACTIVE,
|
|
41
|
+
timeout: aws_cdk_lib_1.Duration.seconds(30),
|
|
42
|
+
memorySize: 256,
|
|
43
|
+
architecture: aws_lambda_1.Architecture.ARM_64,
|
|
44
|
+
};
|
|
27
45
|
const createWriteServicesStack = (app, context, input) => {
|
|
28
|
-
const withId = cdk_1.core.id(
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
const withId = cdk_1.core.id({
|
|
47
|
+
version: input.version,
|
|
48
|
+
input: {
|
|
49
|
+
prefix: (0, optional_1.Optional)(context.project.naming).map(_ => _.prefix).orElse(undefined),
|
|
50
|
+
suffix: context.project.env,
|
|
51
|
+
},
|
|
31
52
|
});
|
|
32
|
-
const
|
|
53
|
+
const defaultConfiguration = cdk_1.stack.withDefaultConfiguration(input.projectMetadata, 'WriteServicesStack');
|
|
54
|
+
const writeServicesStack = cdk_1.stack.withStack({ defaultConfiguration, app })({
|
|
33
55
|
id: withId(`${input.boundedContext}-WriteServices`),
|
|
34
56
|
});
|
|
35
|
-
const
|
|
36
|
-
const withLambdaConfiguration = cdk_1.lambda.withLambdaConfiguration(app)(cdk_1.lambda.withDefaultConfiguration);
|
|
37
|
-
const createLambda = cdk_1.lambda.withLambda(writeServicesStack)(withScalingConfiguration)(withLambdaConfiguration);
|
|
57
|
+
const createLambda = cdk_1.lambda.withLambda({ stack: writeServicesStack, aliasName: 'live' });
|
|
38
58
|
const eventsTable = aws_dynamodb_1.Table.fromTableArn(writeServicesStack, 'EventsTable', input.eventsTable);
|
|
39
59
|
const commandHandlerName = withId(`${input.boundedContext}-Service-CommandHandler`);
|
|
40
60
|
const commandHandler = createLambda({
|
|
41
61
|
functionName: commandHandlerName,
|
|
42
|
-
|
|
62
|
+
codePath: input.writeSide.codePath,
|
|
43
63
|
handler: 'entrypoint.actor.handleCommand',
|
|
64
|
+
lambdaConfiguration: defaultLambdaConfiguration,
|
|
44
65
|
environment: {
|
|
45
66
|
EVENTS_TABLE: eventsTable.tableName,
|
|
46
67
|
EVENTS_TOPICS: input.topics.join(','),
|
|
@@ -55,15 +76,17 @@ const createWriteServicesStack = (app, context, input) => {
|
|
|
55
76
|
const getStateHandlerName = withId(`${input.boundedContext}-Service-GetState`);
|
|
56
77
|
const getStateHandler = createLambda({
|
|
57
78
|
functionName: getStateHandlerName,
|
|
58
|
-
|
|
79
|
+
codePath: '../codebase/write/dist',
|
|
59
80
|
handler: 'entrypoint.actor.getState',
|
|
81
|
+
lambdaConfiguration: defaultLambdaConfiguration,
|
|
60
82
|
environment: {
|
|
61
83
|
BOUNDED_CONTEXT: input.boundedContext,
|
|
62
84
|
EVENTS_TABLE: eventsTable.tableName,
|
|
63
85
|
},
|
|
64
86
|
});
|
|
65
87
|
eventsTable.grantReadWriteData(getStateHandler);
|
|
66
|
-
const
|
|
88
|
+
const account = cdk_1.core.getStackAccountFromEnv();
|
|
89
|
+
const getLambdaArn = cdk_1.lambda.functionArnFromNameAndAlias({ account, aliasName: 'live' });
|
|
67
90
|
return Object.freeze({
|
|
68
91
|
stack: writeServicesStack,
|
|
69
92
|
handleCommandArn: getLambdaArn(commandHandlerName),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/iac/write.ts"],"names":[],"mappings":"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","sourcesContent":["import {App, Duration, Stack} from 'aws-cdk-lib'\nimport {core, dynamo, lambda, stack} from '@othree.io/cdk'\nimport {AttributeType, BillingMode, Table} from 'aws-cdk-lib/aws-dynamodb'\nimport {Architecture, Runtime, Tracing} from 'aws-cdk-lib/aws-lambda'\nimport {Topic} from 'aws-cdk-lib/aws-sns'\nimport {ChiselServiceContext} from './types'\nimport {Optional} from '@othree.io/optional'\nexport type WriteSideInput = Readonly<{\n codePath: string\n}>\n\nexport type WritePersistenceStackInput = Readonly<{\n boundedContext: string\n version: string\n writeSide: WriteSideInput\n projectMetadata: stack.ProjectMetadata\n}>\n\nexport type WritePersistenceStackOutput = Readonly<{\n stack: Stack\n eventsTable: string\n}>\n\nexport const createWritePersistenceStack = (app: App, context: ChiselServiceContext, input: WritePersistenceStackInput): WritePersistenceStackOutput => {\n const withId = core.id({\n version: input.version,\n input: {\n prefix: Optional(context.project.naming).map(_ => _.prefix).orElse(undefined!),\n suffix: context.project.env,\n },\n })\n\n const defaultConfiguration = stack.withDefaultConfiguration(input.projectMetadata, 'WritePersistenceStack')\n\n const writePersistenceStack = stack.withStack({ defaultConfiguration, app })({\n id: withId(`${input.boundedContext}-WritePersistence`),\n })\n\n const tableName = withId(`${input.boundedContext}-Events`)\n dynamo.withTable({\n defaultConfiguration: { billingMode: BillingMode.PAY_PER_REQUEST },\n stack: writePersistenceStack,\n })({\n id: tableName,\n partitionKey: { name: 'contextId', type: AttributeType.STRING },\n sortKey: { name: 'eventId', type: AttributeType.STRING },\n })\n\n const account = core.getStackAccountFromEnv()\n\n return Object.freeze({\n stack: writePersistenceStack,\n eventsTable: `arn:aws:dynamodb:${account.region}:${account.accountId}:table/${tableName}`,\n })\n}\n\nexport type WriteServicesInput = Readonly<{\n boundedContext: string\n version: string\n writeSide: WriteSideInput\n topics: Array<string>\n eventsTable: string\n projectMetadata: stack.ProjectMetadata\n}>\n\nexport type WriteServicesStackOutput = Readonly<{\n stack: Stack\n handleCommandArn: string\n getStateArn: string\n}>\n\nconst defaultLambdaConfiguration: lambda.LambdaConfiguration = {\n runtime: Runtime.NODEJS_20_X,\n tracing: Tracing.ACTIVE,\n timeout: Duration.seconds(30),\n memorySize: 256,\n architecture: Architecture.ARM_64,\n}\n\nexport const createWriteServicesStack = (app: App, context: ChiselServiceContext, input: WriteServicesInput): WriteServicesStackOutput => {\n const withId = core.id({\n version: input.version,\n input: {\n prefix: Optional(context.project.naming).map(_ => _.prefix).orElse(undefined!),\n suffix: context.project.env,\n },\n })\n\n const defaultConfiguration = stack.withDefaultConfiguration(input.projectMetadata, 'WriteServicesStack')\n\n const writeServicesStack = stack.withStack({ defaultConfiguration, app })({\n id: withId(`${input.boundedContext}-WriteServices`),\n })\n\n const createLambda = lambda.withLambda({ stack: writeServicesStack, aliasName: 'live' })\n\n const eventsTable = Table.fromTableArn(writeServicesStack, 'EventsTable', input.eventsTable)\n\n const commandHandlerName = withId(`${input.boundedContext}-Service-CommandHandler`)\n const commandHandler = createLambda({\n functionName: commandHandlerName,\n codePath: input.writeSide.codePath,\n handler: 'entrypoint.actor.handleCommand',\n lambdaConfiguration: defaultLambdaConfiguration,\n environment: {\n EVENTS_TABLE: eventsTable.tableName,\n EVENTS_TOPICS: input.topics.join(','),\n BOUNDED_CONTEXT: input.boundedContext,\n },\n })\n\n eventsTable.grantReadWriteData(commandHandler)\n input.topics.forEach((topic, idx) => {\n Topic.fromTopicArn(writeServicesStack, `CommandHandlerTopic-${idx}`, topic)\n .grantPublish(commandHandler)\n })\n\n const getStateHandlerName = withId(`${input.boundedContext}-Service-GetState`)\n const getStateHandler = createLambda({\n functionName: getStateHandlerName,\n codePath: '../codebase/write/dist',\n handler: 'entrypoint.actor.getState',\n lambdaConfiguration: defaultLambdaConfiguration,\n environment: {\n BOUNDED_CONTEXT: input.boundedContext,\n EVENTS_TABLE: eventsTable.tableName,\n },\n })\n eventsTable.grantReadWriteData(getStateHandler)\n\n const account = core.getStackAccountFromEnv()\n const getLambdaArn = lambda.functionArnFromNameAndAlias({ account, aliasName: 'live' })\n\n return Object.freeze({\n stack: writeServicesStack,\n handleCommandArn: getLambdaArn(commandHandlerName),\n getStateArn: getLambdaArn(getStateHandlerName),\n })\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAA;AAC5B,OAAO,KAAK,GAAG,MAAM,OAAO,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6CAA4B;AAC5B,6CAA4B","sourcesContent":["export * as aws from './aws'\nexport * as iac from './iac'\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/aws/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,SAAS,CAAA","sourcesContent":["export * from './read'\nexport * from './write'"]}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { processSqs } from '@othree.io/stethoscope';
|
|
2
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
import { SQSClient } from '@aws-sdk/client-sqs';
|
|
4
|
+
import { logIOAsync, createDefaultWinstonLogger } from '@othree.io/journal';
|
|
5
|
+
import { dynamo } from '@othree.io/awsome';
|
|
6
|
+
import { Optional, TryAsync } from '@othree.io/optional';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { zodValidate, NonEmptyString } from '@othree.io/auditor';
|
|
9
|
+
import { NotFoundError } from '@othree.io/excuses';
|
|
10
|
+
const ProjectionConstraints = z.object({
|
|
11
|
+
projectionTable: NonEmptyString,
|
|
12
|
+
projectionDLQ: NonEmptyString,
|
|
13
|
+
projectionPk: NonEmptyString,
|
|
14
|
+
deleteOnEvents: z.array(NonEmptyString)
|
|
15
|
+
});
|
|
16
|
+
export const getProcessInput = async (input) => {
|
|
17
|
+
return TryAsync(async () => {
|
|
18
|
+
const { body } = input;
|
|
19
|
+
const sqsEvent = JSON.parse(body);
|
|
20
|
+
const eventMessage = JSON.parse(sqsEvent.Message);
|
|
21
|
+
return {
|
|
22
|
+
state: eventMessage.state,
|
|
23
|
+
event: eventMessage.event
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
export const processEvent = (configuration) => (deleteByFn) => (upsertFn) => async (eventState) => {
|
|
28
|
+
if (configuration.deleteOnEvents.includes(eventState.event.type)) {
|
|
29
|
+
return deleteByFn({
|
|
30
|
+
[configuration.projectionPk]: eventState.event.contextId
|
|
31
|
+
}).then(maybeSuccess => maybeSuccess.map(_ => eventState.state));
|
|
32
|
+
}
|
|
33
|
+
return upsertFn(eventState.state);
|
|
34
|
+
};
|
|
35
|
+
export const getProjectionById = (boundedContext, configuration) => (getByFn) => async (input) => {
|
|
36
|
+
return (await getByFn({
|
|
37
|
+
[configuration.projectionPk]: input.id
|
|
38
|
+
})).map(offers => {
|
|
39
|
+
if (offers.length > 0) {
|
|
40
|
+
return offers[0];
|
|
41
|
+
}
|
|
42
|
+
throw new NotFoundError(input.id, boundedContext);
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
export const getProjectionServiceHandler = (getProjection) => async (event) => {
|
|
46
|
+
return getProjection(event.query).then(_ => _.get());
|
|
47
|
+
};
|
|
48
|
+
/* v8 ignore start: wiring — covered by integration tests */
|
|
49
|
+
export const getConfiguration = () => {
|
|
50
|
+
const envVars = zodValidate({ constraints: ProjectionConstraints })({
|
|
51
|
+
projectionTable: Optional(process.env.PROJECTION_TABLE).map(String).orElse(''),
|
|
52
|
+
projectionDLQ: Optional(process.env.PROJECTION_DLQ).map(String).orElse(''),
|
|
53
|
+
projectionPk: Optional(process.env.PROJECTION_PK).map(String).orElse(''),
|
|
54
|
+
deleteOnEvents: Optional(process.env.DELETE_ON_EVENTS).map(_ => _.split(',')).orElse([])
|
|
55
|
+
}).get();
|
|
56
|
+
return envVars;
|
|
57
|
+
};
|
|
58
|
+
export const getProjectionServices = (input) => {
|
|
59
|
+
const logLevel = Optional(process.env.LOG_LEVEL)
|
|
60
|
+
.orElse('info');
|
|
61
|
+
const configuration = Optional(input.getConfiguration)
|
|
62
|
+
.map(_ => _())
|
|
63
|
+
.orElse(getConfiguration());
|
|
64
|
+
const logger = createDefaultWinstonLogger(console)(input.boundedContext, logLevel);
|
|
65
|
+
const logDebug = logIOAsync({
|
|
66
|
+
now: input.now,
|
|
67
|
+
log: logger.debug.bind(logger),
|
|
68
|
+
logError: logger.error.bind(logger),
|
|
69
|
+
});
|
|
70
|
+
const logInfo = logIOAsync({
|
|
71
|
+
now: input.now,
|
|
72
|
+
log: logger.info.bind(logger),
|
|
73
|
+
logError: logger.error.bind(logger),
|
|
74
|
+
});
|
|
75
|
+
const dynamoDbClient = new DynamoDBClient({});
|
|
76
|
+
const sqsClient = new SQSClient({});
|
|
77
|
+
const dynamoConfig = {
|
|
78
|
+
TableName: configuration.projectionTable
|
|
79
|
+
};
|
|
80
|
+
const upsertProjection = logDebug(dynamo.upsert({
|
|
81
|
+
dynamoDb: dynamoDbClient,
|
|
82
|
+
configuration: dynamoConfig,
|
|
83
|
+
}))(`upsert${input.boundedContext}`);
|
|
84
|
+
const deleteProjectionBy = logDebug(dynamo.deleteBy({
|
|
85
|
+
dynamoDb: dynamoDbClient,
|
|
86
|
+
configuration: dynamoConfig,
|
|
87
|
+
}))(`delete${input.boundedContext}`);
|
|
88
|
+
const queryProjection = dynamo.query({
|
|
89
|
+
dynamoDb: dynamoDbClient,
|
|
90
|
+
configuration: dynamoConfig,
|
|
91
|
+
});
|
|
92
|
+
const getProjectionBy = logDebug(dynamo.getBy({
|
|
93
|
+
query: queryProjection,
|
|
94
|
+
}))(`get${input.boundedContext}`);
|
|
95
|
+
const getById = logDebug(getProjectionById(input.boundedContext, configuration)(getProjectionBy))(`get${input.boundedContext}ById`);
|
|
96
|
+
const processEventFn = logDebug(processEvent(configuration)(deleteProjectionBy)(upsertProjection))(`process${input.boundedContext}Event`);
|
|
97
|
+
const processSqsFn = processSqs({
|
|
98
|
+
log: logInfo,
|
|
99
|
+
sqsClient,
|
|
100
|
+
configuration: {
|
|
101
|
+
dlqUrl: configuration.projectionDLQ,
|
|
102
|
+
exponentialTimeouts: [5, 10, 30],
|
|
103
|
+
},
|
|
104
|
+
didItFail: (_) => false,
|
|
105
|
+
runProcess: processEventFn,
|
|
106
|
+
getProcessInput: (getProcessInput),
|
|
107
|
+
});
|
|
108
|
+
const getByIdHandlerFn = logInfo(getProjectionServiceHandler(getById))(`get${input.boundedContext}ByIdHandler`);
|
|
109
|
+
return {
|
|
110
|
+
sqs: {
|
|
111
|
+
updateProjection: processSqsFn
|
|
112
|
+
},
|
|
113
|
+
services: {
|
|
114
|
+
getById: getByIdHandlerFn
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
/* v8 ignore stop */
|
|
119
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/aws/read.ts"],"names":[],"mappings":"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","sourcesContent":["import {processSqs} from '@othree.io/stethoscope'\nimport {DynamoDBClient} from '@aws-sdk/client-dynamodb'\nimport {SQSClient} from '@aws-sdk/client-sqs'\nimport {logIOAsync, createDefaultWinstonLogger} from '@othree.io/journal'\nimport {dynamo} from '@othree.io/awsome'\nimport {Optional, TryAsync} from '@othree.io/optional'\nimport {ChiselEvent, TriggeredEvent} from '@othree.io/chisel'\nimport {z} from 'zod'\nimport {zodValidate, NonEmptyString} from '@othree.io/auditor'\nimport {SQSRecord} from 'aws-lambda'\nimport {NotFoundError} from '@othree.io/excuses'\n\nexport type ProjectionConfiguration = Readonly<{\n projectionTable: string\n projectionDLQ: string\n projectionPk: string\n deleteOnEvents: Array<string>\n}>\n\ntype CreateProjectionInput = Readonly<{\n boundedContext: string\n now: () => number\n getConfiguration?: () => ProjectionConfiguration\n}>\n\nconst ProjectionConstraints: z.ZodType<ProjectionConfiguration> = z.object({\n projectionTable: NonEmptyString,\n projectionDLQ: NonEmptyString,\n projectionPk: NonEmptyString,\n deleteOnEvents: z.array(NonEmptyString)\n})\n\ntype EventState<AggregateRoot, EventType extends ChiselEvent> = Readonly<{\n state: AggregateRoot,\n event: TriggeredEvent<EventType>\n}>\n\nexport const getProcessInput = async <AggregateRoot, EventType extends ChiselEvent>(input: SQSRecord): Promise<Optional<EventState<AggregateRoot, EventType>>> => {\n return TryAsync(async () => {\n const {body} = input\n const sqsEvent = JSON.parse(body)\n const eventMessage = JSON.parse(sqsEvent.Message)\n\n return {\n state: eventMessage.state as AggregateRoot,\n event: eventMessage.event as TriggeredEvent<EventType>\n }\n })\n}\n\nexport const processEvent = <AggregateRoot, EventType extends ChiselEvent>(configuration: ProjectionConfiguration) =>\n (deleteByFn: (keys: dynamo.Keys) => Promise<Optional<boolean>>) =>\n (upsertFn: (entity: AggregateRoot) => Promise<Optional<AggregateRoot>>) =>\n async (eventState: EventState<AggregateRoot, EventType>) => {\n if (configuration.deleteOnEvents.includes(eventState.event.type)) {\n return deleteByFn({\n [configuration.projectionPk]: eventState.event.contextId\n }).then(maybeSuccess => maybeSuccess.map(_ => eventState.state))\n }\n\n return upsertFn(eventState.state)\n }\n\nexport const getProjectionById = (boundedContext: string, configuration: ProjectionConfiguration) =>\n <AggregateRoot>(getByFn: (keys: dynamo.Keys) => Promise<Optional<Array<AggregateRoot>>>) =>\n async (input: GetByIdQuery): Promise<Optional<AggregateRoot>> => {\n return (await getByFn({\n [configuration.projectionPk]: input.id\n })).map(offers => {\n if (offers.length > 0) {\n return offers[0]\n }\n\n throw new NotFoundError(input.id, boundedContext)\n })\n }\n\nexport type ServiceQuery<T> = Readonly<{\n query: T\n}>\n\nexport type GetByIdQuery = Readonly<{\n id: string\n}>\n\nexport const getProjectionServiceHandler = <QueryType, ProjectionType>(getProjection: (query: QueryType) => Promise<Optional<ProjectionType>>) =>\n async (event: ServiceQuery<QueryType>): Promise<ProjectionType> => {\n return getProjection(event.query).then(_ => _.get() as ProjectionType)\n }\n\n/* v8 ignore start: wiring — covered by integration tests */\nexport const getConfiguration = (): ProjectionConfiguration => {\n const envVars = zodValidate({ constraints: ProjectionConstraints })({\n projectionTable: Optional(process.env.PROJECTION_TABLE).map(String).orElse(''),\n projectionDLQ: Optional(process.env.PROJECTION_DLQ).map(String).orElse(''),\n projectionPk: Optional(process.env.PROJECTION_PK).map(String).orElse(''),\n deleteOnEvents: Optional(process.env.DELETE_ON_EVENTS).map(_ => _.split(',')).orElse([])\n }).get()\n\n return envVars\n}\n\nexport const getProjectionServices = <AggregateRoot, EventType extends ChiselEvent>(input: CreateProjectionInput) => {\n const logLevel = Optional(process.env.LOG_LEVEL)\n .orElse('info')\n\n const configuration = Optional(input.getConfiguration)\n .map(_ => _())\n .orElse(getConfiguration())\n\n const logger = createDefaultWinstonLogger(console)(input.boundedContext, logLevel)\n\n const logDebug = logIOAsync({\n now: input.now,\n log: logger.debug.bind(logger),\n logError: logger.error.bind(logger),\n })\n const logInfo = logIOAsync({\n now: input.now,\n log: logger.info.bind(logger),\n logError: logger.error.bind(logger),\n })\n\n const dynamoDbClient = new DynamoDBClient({})\n const sqsClient = new SQSClient({})\n\n const dynamoConfig: dynamo.DynamoConfiguration = {\n TableName: configuration.projectionTable\n }\n\n const upsertProjection: (entity: AggregateRoot) => Promise<Optional<AggregateRoot>> = logDebug(dynamo.upsert<AggregateRoot>({\n dynamoDb: dynamoDbClient,\n configuration: dynamoConfig,\n }))(`upsert${input.boundedContext}`)\n\n const deleteProjectionBy: (keys: dynamo.Keys) => Promise<Optional<boolean>> = logDebug(dynamo.deleteBy<AggregateRoot>({\n dynamoDb: dynamoDbClient,\n configuration: dynamoConfig,\n }))(`delete${input.boundedContext}`)\n\n const queryProjection = dynamo.query<AggregateRoot>({\n dynamoDb: dynamoDbClient,\n configuration: dynamoConfig,\n })\n\n const getProjectionBy: (keys: dynamo.Keys) => Promise<Optional<Array<AggregateRoot>>> = logDebug(dynamo.getBy<AggregateRoot>({\n query: queryProjection,\n }))(`get${input.boundedContext}`)\n\n const getById: (input: GetByIdQuery) => Promise<Optional<AggregateRoot>> = logDebug(getProjectionById(input.boundedContext, configuration)(getProjectionBy))(`get${input.boundedContext}ById`)\n\n const processEventFn: (eventState: EventState<AggregateRoot, EventType>) => Promise<Optional<AggregateRoot>> = logDebug(processEvent<AggregateRoot, EventType>(configuration)(deleteProjectionBy)(upsertProjection))(`process${input.boundedContext}Event`)\n\n const processSqsFn = processSqs<EventState<AggregateRoot, EventType>, AggregateRoot>({\n log: logInfo,\n sqsClient,\n configuration: {\n dlqUrl: configuration.projectionDLQ,\n exponentialTimeouts: [5, 10, 30],\n },\n didItFail: (_: Error) => false,\n runProcess: processEventFn,\n getProcessInput: getProcessInput<AggregateRoot, EventType>,\n })\n\n const getByIdHandlerFn = logInfo(getProjectionServiceHandler<GetByIdQuery, AggregateRoot>(getById))(`get${input.boundedContext}ByIdHandler`)\n\n return {\n sqs: {\n updateProjection: processSqsFn\n },\n services: {\n getById: getByIdHandlerFn\n }\n }\n}\n/* v8 ignore stop */\n"]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { handlers } from '@othree.io/chisel-aws';
|
|
2
|
+
import { actor, eventSource } from '@othree.io/chisel';
|
|
3
|
+
import { lambda } from '@othree.io/awsome';
|
|
4
|
+
import { logIOAsync, createDefaultWinstonLogger } from '@othree.io/journal';
|
|
5
|
+
import { Optional } from '@othree.io/optional';
|
|
6
|
+
import { match } from '@othree.io/cerillo';
|
|
7
|
+
import { awsActor, awsEventSource, } from '@othree.io/chisel-aws';
|
|
8
|
+
import { zodValidate, NonEmptyString } from '@othree.io/auditor';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { v7 as newId } from 'uuid';
|
|
11
|
+
import * as AWSXRay from 'aws-xray-sdk-core';
|
|
12
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
13
|
+
import { SNSClient } from '@aws-sdk/client-sns';
|
|
14
|
+
const ChiselActorConstraints = z.object({
|
|
15
|
+
eventsTable: NonEmptyString,
|
|
16
|
+
eventsTopics: z.array(NonEmptyString),
|
|
17
|
+
});
|
|
18
|
+
const getConfiguration = (input) => {
|
|
19
|
+
const envVars = zodValidate({ constraints: ChiselActorConstraints })({
|
|
20
|
+
eventsTable: Optional(process.env.EVENTS_TABLE).map(String).orElse(''),
|
|
21
|
+
eventsTopics: Optional(process.env.EVENTS_TOPICS).map(_ => String(_).split(',')).orElse([]),
|
|
22
|
+
}).get();
|
|
23
|
+
return {
|
|
24
|
+
BoundedContext: input.boundedContext,
|
|
25
|
+
IsFifo: true,
|
|
26
|
+
SnapshotFrequency: 100,
|
|
27
|
+
TableName: envVars.eventsTable,
|
|
28
|
+
TopicsArn: envVars.eventsTopics,
|
|
29
|
+
SnapshotEventType: '$SNAPSHOT$',
|
|
30
|
+
GetMessageGroupId: (event, _state) => event.contextId,
|
|
31
|
+
IncludeState: true,
|
|
32
|
+
SnapshotSerializer: {
|
|
33
|
+
serialize: (state) => JSON.stringify(state),
|
|
34
|
+
deserialize: (state) => JSON.parse(state)
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const getStateHandler = (loadState) => async (event) => {
|
|
39
|
+
return loadState(Optional(event.query.contextId))
|
|
40
|
+
.then(_ => _.map(state => state.state).get());
|
|
41
|
+
};
|
|
42
|
+
export const createActor = (input) => {
|
|
43
|
+
const logLevel = Optional(process.env.LOG_LEVEL)
|
|
44
|
+
.orElse('info');
|
|
45
|
+
const logger = createDefaultWinstonLogger(console)(input.boundedContext, logLevel);
|
|
46
|
+
const logDebug = logIOAsync({
|
|
47
|
+
now: input.now,
|
|
48
|
+
log: logger.debug.bind(logger),
|
|
49
|
+
logError: logger.error.bind(logger),
|
|
50
|
+
});
|
|
51
|
+
const configuration = Optional(input.getConfiguration)
|
|
52
|
+
.map(_ => _())
|
|
53
|
+
.orElse(getConfiguration(input));
|
|
54
|
+
const dynamoDbClient = AWSXRay.captureAWSv3Client(new DynamoDBClient({}));
|
|
55
|
+
const snsClient = AWSXRay.captureAWSv3Client(new SNSClient({}));
|
|
56
|
+
const getEvents = logDebug(awsEventSource.getEvents({
|
|
57
|
+
dynamoDb: dynamoDbClient,
|
|
58
|
+
configuration,
|
|
59
|
+
}))('getEvents');
|
|
60
|
+
const persistEvent = logDebug(awsEventSource.persist({
|
|
61
|
+
dynamoDb: dynamoDbClient,
|
|
62
|
+
configuration,
|
|
63
|
+
}))('persistEvent');
|
|
64
|
+
const publishEvent = logDebug(awsActor.publishShardedEvent({
|
|
65
|
+
hashCode: awsActor.hashCode,
|
|
66
|
+
snsClient,
|
|
67
|
+
configuration,
|
|
68
|
+
}))('publishEvent');
|
|
69
|
+
const loadState = logDebug(eventSource.loadState({
|
|
70
|
+
configuration,
|
|
71
|
+
getEvents: getEvents,
|
|
72
|
+
getInitialState: input.getInitialState,
|
|
73
|
+
reduce: input.reduceEvent,
|
|
74
|
+
match,
|
|
75
|
+
}))('loadState');
|
|
76
|
+
const calculateNewState = logDebug(eventSource.calculateNewState({
|
|
77
|
+
configuration,
|
|
78
|
+
newId,
|
|
79
|
+
now: input.now,
|
|
80
|
+
persistEvent: persistEvent,
|
|
81
|
+
reduce: input.reduceEvent,
|
|
82
|
+
}))('calculateNewState');
|
|
83
|
+
const getStateHandlerFn = logDebug(getStateHandler(loadState))('getStateHandler');
|
|
84
|
+
const actorHandler = logDebug(actor.handle({
|
|
85
|
+
loadState,
|
|
86
|
+
handleCommand: input.handleCommand,
|
|
87
|
+
calculateNewState,
|
|
88
|
+
publishEvent,
|
|
89
|
+
match,
|
|
90
|
+
}))('chiselHandleCommand');
|
|
91
|
+
const handleCommand = logDebug(handlers.handleLambdaCommand({
|
|
92
|
+
handle: actorHandler,
|
|
93
|
+
}))('handleLambdaCommand');
|
|
94
|
+
return Object.freeze({
|
|
95
|
+
handleCommand: lambda.unwrap(handleCommand),
|
|
96
|
+
getState: lambda.unwrap(getStateHandlerFn),
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/aws/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAC,KAAK,EAA8B,WAAW,EAA2B,MAAM,mBAAmB,CAAA;AAC1G,OAAO,EAAC,MAAM,EAAC,MAAM,mBAAmB,CAAA;AACxC,OAAO,EAAC,UAAU,EAAE,0BAA0B,EAAC,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAA;AACxC,OAAO,EACH,QAAQ,EACR,cAAc,GAGjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,WAAW,EAAE,cAAc,EAAC,MAAM,oBAAoB,CAAA;AAC9D,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,EAAE,IAAI,KAAK,EAAE,MAAM,MAAM,CAAA;AAClC,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAA;AAgB7C,MAAM,sBAAsB,GAA+C,CAAC,CAAC,MAAM,CAAC;IAChF,WAAW,EAAE,cAAc;IAC3B,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;CACxC,CAAC,CAAA;AAEF,MAAM,gBAAgB,GAAG,CAA2C,KAAmD,EAAsH,EAAE;IAC3O,MAAM,OAAO,GAAG,WAAW,CAAC,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACjE,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACtE,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KAC9F,CAAC,CAAC,GAAG,EAAE,CAAA;IAER,OAAO;QACH,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,MAAM,EAAE,IAAI;QACZ,iBAAiB,EAAE,GAAG;QACtB,SAAS,EAAE,OAAO,CAAC,WAAW;QAC9B,SAAS,EAAE,OAAO,CAAC,YAAY;QAC/B,iBAAiB,EAAE,YAAY;QAC/B,iBAAiB,EAAE,CAAC,KAAkB,EAAE,MAAqB,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS;QACjF,YAAY,EAAE,IAAI;QAClB,kBAAkB,EAAE;YAChB,SAAS,EAAE,CAAC,KAAoB,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC1D,WAAW,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;SACrE;KACJ,CAAA;AACL,CAAC,CAAA;AAWD,MAAM,eAAe,GAAG,CAAgB,SAA+C,EAAE,EAAE,CACvF,KAAK,EAAE,KAAkC,EAA0B,EAAE;IACjE,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;SAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAmB,CAAC,CAAA;AACtE,CAAC,CAAA;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,CAA2C,KAAmD,EAA8B,EAAE;IACrJ,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;SAC3C,MAAM,CAAC,MAAM,CAAC,CAAA;IAEnB,MAAM,MAAM,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;IAElF,MAAM,QAAQ,GAAG,UAAU,CAAC;QACxB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;KACtC,CAAC,CAAA;IAEF,MAAM,aAAa,GAAuH,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC;SACrK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;SACb,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAA;IAEpC,MAAM,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC,CAAA;IACzE,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,CAAA;IAE/D,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC;QAChD,QAAQ,EAAE,cAAc;QACxB,aAAa;KAChB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IAEhB,MAAM,YAAY,GAA6B,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC;QAC3E,QAAQ,EAAE,cAAc;QACxB,aAAa;KAChB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAA;IAEnB,MAAM,YAAY,GAAsC,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAgB;QACzG,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,SAAS;QACT,aAAa;KAChB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAA;IAEnB,MAAM,SAAS,GAAyC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAuB;QACzG,aAAa;QACb,SAAS,EAAE,SAAS;QACpB,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,MAAM,EAAE,KAAK,CAAC,WAAW;QACzB,KAAK;KACR,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IAEhB,MAAM,iBAAiB,GAAiD,QAAQ,CAAC,WAAW,CAAC,iBAAiB,CAAuB;QACjI,aAAa;QACb,KAAK;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,YAAY,EAAE,YAAY;QAC1B,MAAM,EAAE,KAAK,CAAC,WAAW;KAC5B,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAA;IAExB,MAAM,iBAAiB,GAAG,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAA;IAEjF,MAAM,YAAY,GAAgC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAgB;QACnF,SAAS;QACT,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,iBAAiB;QACjB,YAAY;QACZ,KAAK;KACR,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAA;IAE1B,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAgB;QACvE,MAAM,EAAE,YAAY;KACvB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAA;IAE1B,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3C,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;KAC7C,CAAC,CAAA;AACN,CAAC,CAAA","sourcesContent":["import {handlers} from '@othree.io/chisel-aws'\nimport {actor, ChiselEvent, CommandResult, eventSource, EventSourceConfiguration} from '@othree.io/chisel'\nimport {lambda} from '@othree.io/awsome'\nimport {logIOAsync, createDefaultWinstonLogger} from '@othree.io/journal'\nimport {Optional} from '@othree.io/optional'\nimport {match} from '@othree.io/cerillo'\nimport {\n awsActor,\n awsEventSource,\n ChiselDynamoConfiguration,\n ChiselShardedSnsConfiguration,\n} from '@othree.io/chisel-aws'\nimport {zodValidate, NonEmptyString} from '@othree.io/auditor'\nimport {z} from 'zod'\nimport { v7 as newId } from 'uuid'\nimport * as AWSXRay from 'aws-xray-sdk-core'\nimport {DynamoDBClient} from '@aws-sdk/client-dynamodb'\nimport {SNSClient} from '@aws-sdk/client-sns'\n\ntype GetStateQuery = Readonly<{\n contextId: string\n}>\n\nexport type LambdaActor<AggregateRoot> = Readonly<{\n handleCommand: (event: handlers.LambdaCommand) => Promise<lambda.InvocationResult<CommandResult<AggregateRoot>>>\n getState: (event: lambda.Query<GetStateQuery>) => Promise<lambda.InvocationResult<AggregateRoot>>\n}>\n\ntype ChiselActorEnvironmentVariables = Readonly<{\n eventsTable: string\n eventsTopics: Array<string>\n}>\n\nconst ChiselActorConstraints: z.ZodType<ChiselActorEnvironmentVariables> = z.object({\n eventsTable: NonEmptyString,\n eventsTopics: z.array(NonEmptyString),\n})\n\nconst getConfiguration = <AggregateRoot, Event extends ChiselEvent>(input: CreateLambdaActorInput<AggregateRoot, Event>): ChiselDynamoConfiguration & ChiselShardedSnsConfiguration<AggregateRoot> & EventSourceConfiguration<AggregateRoot> => {\n const envVars = zodValidate({ constraints: ChiselActorConstraints })({\n eventsTable: Optional(process.env.EVENTS_TABLE).map(String).orElse(''),\n eventsTopics: Optional(process.env.EVENTS_TOPICS).map(_ => String(_).split(',')).orElse([]),\n }).get()\n\n return {\n BoundedContext: input.boundedContext,\n IsFifo: true,\n SnapshotFrequency: 100,\n TableName: envVars.eventsTable,\n TopicsArn: envVars.eventsTopics,\n SnapshotEventType: '$SNAPSHOT$',\n GetMessageGroupId: (event: ChiselEvent, _state: AggregateRoot) => event.contextId,\n IncludeState: true,\n SnapshotSerializer: {\n serialize: (state: AggregateRoot) => JSON.stringify(state),\n deserialize: (state: string) => JSON.parse(state) as AggregateRoot\n }\n }\n}\n\ntype CreateLambdaActorInput<AggregateRoot, Event extends ChiselEvent> = Readonly<{\n boundedContext: string\n now: () => number\n getInitialState: (contextId: Optional<string>) => Promise<Optional<AggregateRoot>>\n handleCommand: actor.HandleCommand<AggregateRoot>\n reduceEvent: eventSource.Reduce<AggregateRoot, Event>\n getConfiguration?: () => ChiselDynamoConfiguration & ChiselShardedSnsConfiguration<AggregateRoot> & EventSourceConfiguration<AggregateRoot>\n}>\n\nconst getStateHandler = <AggregateRoot>(loadState: eventSource.LoadState<AggregateRoot>) =>\n async (event: lambda.Query<GetStateQuery>): Promise<AggregateRoot> => {\n return loadState(Optional(event.query.contextId))\n .then(_ => _.map(state => state.state).get() as AggregateRoot)\n }\n\nexport const createActor = <AggregateRoot, Event extends ChiselEvent>(input: CreateLambdaActorInput<AggregateRoot, Event>): LambdaActor<AggregateRoot> => {\n const logLevel = Optional(process.env.LOG_LEVEL)\n .orElse('info')\n\n const logger = createDefaultWinstonLogger(console)(input.boundedContext, logLevel)\n\n const logDebug = logIOAsync({\n now: input.now,\n log: logger.debug.bind(logger),\n logError: logger.error.bind(logger),\n })\n\n const configuration: EventSourceConfiguration<AggregateRoot> & ChiselDynamoConfiguration & ChiselShardedSnsConfiguration<AggregateRoot> = Optional(input.getConfiguration)\n .map(_ => _())\n .orElse(getConfiguration(input))\n\n const dynamoDbClient = AWSXRay.captureAWSv3Client(new DynamoDBClient({}))\n const snsClient = AWSXRay.captureAWSv3Client(new SNSClient({}))\n\n const getEvents = logDebug(awsEventSource.getEvents({\n dynamoDb: dynamoDbClient,\n configuration,\n }))('getEvents')\n\n const persistEvent: eventSource.PersistEvent = logDebug(awsEventSource.persist({\n dynamoDb: dynamoDbClient,\n configuration,\n }))('persistEvent')\n\n const publishEvent: actor.PublishEvent<AggregateRoot> = logDebug(awsActor.publishShardedEvent<AggregateRoot>({\n hashCode: awsActor.hashCode,\n snsClient,\n configuration,\n }))('publishEvent')\n\n const loadState: eventSource.LoadState<AggregateRoot> = logDebug(eventSource.loadState<AggregateRoot, Event>({\n configuration,\n getEvents: getEvents,\n getInitialState: input.getInitialState,\n reduce: input.reduceEvent,\n match,\n }))('loadState')\n\n const calculateNewState: eventSource.CalculateNewState<AggregateRoot> = logDebug(eventSource.calculateNewState<AggregateRoot, Event>({\n configuration,\n newId,\n now: input.now,\n persistEvent: persistEvent,\n reduce: input.reduceEvent,\n }))('calculateNewState')\n\n const getStateHandlerFn = logDebug(getStateHandler(loadState))('getStateHandler')\n\n const actorHandler: actor.Handle<AggregateRoot> = logDebug(actor.handle<AggregateRoot>({\n loadState,\n handleCommand: input.handleCommand,\n calculateNewState,\n publishEvent,\n match,\n }))('chiselHandleCommand')\n\n const handleCommand = logDebug(handlers.handleLambdaCommand<AggregateRoot>({\n handle: actorHandler,\n }))('handleLambdaCommand')\n\n return Object.freeze({\n handleCommand: lambda.unwrap(handleCommand),\n getState: lambda.unwrap(getStateHandlerFn),\n })\n}\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Optional } from '@othree.io/optional';
|
|
2
|
+
import { ChiselServiceContextConstraints } from './types';
|
|
3
|
+
import { zodValidate } from '@othree.io/auditor';
|
|
4
|
+
import { createTopicsStack } from './shared';
|
|
5
|
+
import { createWritePersistenceStack, createWriteServicesStack } from './write';
|
|
6
|
+
import { createReadPersistenceStack, createReadServicesStack, createTopicSubscribersStack } from './read';
|
|
7
|
+
export const createChiselStacks = (app, input) => {
|
|
8
|
+
const context = zodValidate({ constraints: ChiselServiceContextConstraints })(input.context).get();
|
|
9
|
+
const topicsStack = createTopicsStack(app, context, {
|
|
10
|
+
boundedContext: input.boundedContext,
|
|
11
|
+
version: input.version,
|
|
12
|
+
projectMetadata: input.projectMetadata,
|
|
13
|
+
});
|
|
14
|
+
const writePersistenceStack = createWritePersistenceStack(app, context, {
|
|
15
|
+
boundedContext: input.boundedContext,
|
|
16
|
+
version: input.version,
|
|
17
|
+
writeSide: input.writeSide,
|
|
18
|
+
projectMetadata: input.projectMetadata,
|
|
19
|
+
});
|
|
20
|
+
const writeServicesStack = createWriteServicesStack(app, context, {
|
|
21
|
+
boundedContext: input.boundedContext,
|
|
22
|
+
version: input.version,
|
|
23
|
+
writeSide: input.writeSide,
|
|
24
|
+
eventsTable: writePersistenceStack.eventsTable,
|
|
25
|
+
topics: topicsStack.topics,
|
|
26
|
+
projectMetadata: input.projectMetadata,
|
|
27
|
+
});
|
|
28
|
+
const readSideStacks = Optional(input.readSide).map(readSide => {
|
|
29
|
+
const subscribersStack = createTopicSubscribersStack(app, context, {
|
|
30
|
+
boundedContext: input.boundedContext,
|
|
31
|
+
version: input.version,
|
|
32
|
+
readSide: readSide,
|
|
33
|
+
topics: topicsStack.topics,
|
|
34
|
+
projectMetadata: input.projectMetadata,
|
|
35
|
+
});
|
|
36
|
+
const persistenceStack = createReadPersistenceStack(app, context, {
|
|
37
|
+
boundedContext: input.boundedContext,
|
|
38
|
+
version: input.version,
|
|
39
|
+
readSide: readSide,
|
|
40
|
+
projectMetadata: input.projectMetadata,
|
|
41
|
+
});
|
|
42
|
+
const servicesStack = createReadServicesStack(app, context, {
|
|
43
|
+
boundedContext: input.boundedContext,
|
|
44
|
+
version: input.version,
|
|
45
|
+
readSide: readSide,
|
|
46
|
+
dlq: subscribersStack.dlq,
|
|
47
|
+
eventQueues: subscribersStack.eventQueues,
|
|
48
|
+
projectionTable: persistenceStack.projectionTable,
|
|
49
|
+
projectMetadata: input.projectMetadata,
|
|
50
|
+
});
|
|
51
|
+
return Object.freeze({
|
|
52
|
+
subscribers: subscribersStack,
|
|
53
|
+
persistence: persistenceStack,
|
|
54
|
+
servicesStack: servicesStack
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
topics: topicsStack,
|
|
59
|
+
writeSide: Object.freeze({
|
|
60
|
+
persistence: writePersistenceStack,
|
|
61
|
+
services: writeServicesStack,
|
|
62
|
+
}),
|
|
63
|
+
readSide: readSideStacks.orElse(undefined)
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/iac/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {App} from 'aws-cdk-lib'\nimport {stack} from '@othree.io/cdk'\nimport {Optional} from '@othree.io/optional'\nimport {ChiselServiceContext, ChiselServiceContextConstraints} from './types'\nimport {zodValidate} from '@othree.io/auditor'\nimport {createTopicsStack, TopicsStackOutput} from './shared'\nimport {\n createWritePersistenceStack, createWriteServicesStack,\n WritePersistenceStackOutput,\n WriteServicesStackOutput,\n WriteSideInput\n} from './write'\nimport {\n createReadPersistenceStack, createReadServicesStack,\n createTopicSubscribersStack,\n QueueSubscribersStackOutput,\n ReadPersistenceStackOutput,\n ReadServicesStackOutput,\n ReadSideInput\n} from './read'\n\n\nexport type StacksInput = Readonly<{\n boundedContext: string\n version: string\n projectMetadata: stack.ProjectMetadata\n context: ChiselServiceContext\n writeSide: WriteSideInput\n readSide?: ReadSideInput\n}>\n\nexport type ChiselStacks = Readonly<{\n topics: TopicsStackOutput\n writeSide: Readonly<{\n persistence: WritePersistenceStackOutput\n services: WriteServicesStackOutput\n }>\n readSide?: Readonly<{\n subscribers: QueueSubscribersStackOutput\n persistence: ReadPersistenceStackOutput\n servicesStack: ReadServicesStackOutput\n }>\n}>\n\nexport const createChiselStacks = (app: App, input: StacksInput): ChiselStacks => {\n const context = zodValidate({ constraints: ChiselServiceContextConstraints })(input.context).get()\n\n const topicsStack = createTopicsStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n projectMetadata: input.projectMetadata,\n })\n const writePersistenceStack = createWritePersistenceStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n writeSide: input.writeSide,\n projectMetadata: input.projectMetadata,\n })\n const writeServicesStack = createWriteServicesStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n writeSide: input.writeSide,\n eventsTable: writePersistenceStack.eventsTable,\n topics: topicsStack.topics,\n projectMetadata: input.projectMetadata,\n })\n\n const readSideStacks = Optional(input.readSide).map(readSide => {\n const subscribersStack = createTopicSubscribersStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n readSide: readSide,\n topics: topicsStack.topics,\n projectMetadata: input.projectMetadata,\n })\n\n const persistenceStack = createReadPersistenceStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n readSide: readSide,\n projectMetadata: input.projectMetadata,\n })\n\n const servicesStack = createReadServicesStack(app, context, {\n boundedContext: input.boundedContext,\n version: input.version,\n readSide: readSide,\n dlq: subscribersStack.dlq,\n eventQueues: subscribersStack.eventQueues,\n projectionTable: persistenceStack.projectionTable,\n projectMetadata: input.projectMetadata,\n })\n\n return Object.freeze({\n subscribers: subscribersStack,\n persistence: persistenceStack,\n servicesStack: servicesStack\n })\n })\n\n return Object.freeze({\n topics: topicsStack,\n writeSide: Object.freeze({\n persistence: writePersistenceStack,\n services: writeServicesStack,\n }),\n readSide: readSideStacks.orElse(undefined!)\n })\n}\n"]}
|