@glicogh/healthcare-cdk 0.1.87 → 0.1.89

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/.env.example CHANGED
@@ -13,6 +13,10 @@ EC2_MYSQL_INSTANCE_TYPE=t4g.nano
13
13
  EC2_MYSQL_INSTANCE_STORAGE_SIZE=10
14
14
  EC2_MYSQL_INSTANCE_STORAGE_TYPE=gp3
15
15
 
16
+ EC2_CLICKHOUSE_INSTANCE_TYPE=t4g.nano
17
+ EC2_CLICKHOUSE_INSTANCE_STORAGE_SIZE=50
18
+ EC2_CLICKHOUSE_INSTANCE_STORAGE_TYPE=gp3
19
+
16
20
  EC2_API_GATEWAY_INSTANCE_TYPE=t4g.nano
17
21
  EC2_API_GATEWAY_INSTANCE_STORAGE_SIZE=
18
22
  EC2_API_GATEWAY_INSTANCE_STORAGE_TYPE=gp3
package/README.md CHANGED
@@ -77,6 +77,7 @@ The output looks like this
77
77
  MicroserviceNetwork
78
78
  MicroserviceRedis
79
79
  MicroserviceMySQL
80
+ MicroserviceClickHouse
80
81
  ```
81
82
 
82
83
  ## Running the CDK
@@ -89,13 +90,69 @@ The following stack are meant to be deployed once and shared across the microser
89
90
  - MicroserviceInfraAuth
90
91
  - MicroserviceRedis
91
92
  - MicroserviceMySQL
93
+ - MicroserviceClickHouse
94
+ - MicroserviceMigration
92
95
 
93
- The only required option for these stack is `env`. For example, to deploy `MicroserviceNetwork` in the UAT environment, you would run the command
96
+ The only required option for these stacks is `env`. To deploy a single shared stack, pass its `service` value:
97
+
98
+ | Stack | `service` |
99
+ | ---------------------- | ------------ |
100
+ | MicroserviceNetwork | `network` |
101
+ | MicroserviceInfraAuth | `infra-auth` |
102
+ | MicroserviceRedis | `redis` |
103
+ | MicroserviceMySQL | `mysql` |
104
+ | MicroserviceClickHouse | `clickhouse` |
105
+ | MicroserviceMigration | `migration` |
106
+
107
+ For example, to deploy `MicroserviceNetwork` in the UAT environment, you would run the command
108
+
109
+ ```
110
+ cdk --profile glicogh-uat --context env=uat --context service=network deploy
111
+ ```
112
+
113
+ Only the selected stack is synthesized, so unrelated stacks (and their code assets, such as the migration Lambdas) are not bundled. Omitting `service` synthesizes and deploys all shared stacks. Alternatively, when deploying by stack name (`cdk --context env=uat deploy MicroserviceNetwork`), pass `--exclusively` to `synth`/`deploy`/`diff` to skip bundling unrelated stacks.
114
+
115
+ ### Migration orchestrator (MicroserviceMigration)
116
+
117
+ `MicroserviceMigration` bundles the migration producer/consumer Lambdas (from the sibling `migration/lambdas` directory), the `migration-queue.fifo` queue, a `migration-verifier` Lambda, an S3 artifacts bucket, a one-shot ECS Fargate scripts runner, and the `migration-orchestrator` Step Function (`cdk/constructs/migration-state-machine.ts`). Invoking the state machine runs the migration runbook end-to-end:
118
+
119
+ - **Scripts (runbook Steps 1–4)** run as one-shot ECS Fargate tasks from the migration repo's `Dockerfile` (entrypoint dispatches `restore` / `migrations` / `diseases` / `claim-batches` / `reset`). The restore task syncs the legacy dump from S3 first; no 15-minute Lambda cap.
120
+ - **Migratables (Steps 5–16)** loop the producer Lambda until the response reports `endReached: true`, then wait for the SQS queue to drain (`ApproximateNumberOfMessages` + `NotVisible` = 0) before the next dependency step. Tier 0 (users, providers, insured, tpa, plans) runs as a `Parallel`.
121
+ - **Every resource gets a retry pass** (`fromStart: true, skipMigrated: true`) after the first pass + drain, recovering records dropped by transient service failures.
122
+ - **Verification** invokes the verifier Lambda, which writes `runs/<execution-name>/summary.json` (migrated counts, source counts, API totals) to the artifacts bucket.
123
+
124
+ **Prerequisites**: deploy the shared stacks (the migration stack alone with `cdk --profile glicogh-uat --context env=uat --context service=migration deploy`); upload the legacy dump to the artifacts bucket (`glicogh-healthcare-migration-<env>-<account>`):
94
125
 
95
126
  ```
96
- cdk --profile glicogh-uat --context env=uat deploy MicroserviceNetwork
127
+ aws s3 sync data/legacy-backup s3://glicogh-healthcare-migration-uat-825765383017/backups/<runId>/
97
128
  ```
98
129
 
130
+ **Start an execution** (all input fields are required; `fromStep` uses the step ids below, `""` = full run):
131
+
132
+ ```json
133
+ {
134
+ "backupS3Uri": "s3://glicogh-healthcare-migration-uat-825765383017/backups/<runId>/",
135
+ "fresh": false,
136
+ "skipPhotos": false,
137
+ "fromStep": ""
138
+ }
139
+ ```
140
+
141
+ ```
142
+ aws stepfunctions start-execution \
143
+ --state-machine-arn <state-machine-arn> \
144
+ --name <runId> \
145
+ --input file://input.json
146
+ ```
147
+
148
+ Step ids for `fromStep`: `fresh-reset`, `restore`, `migrations`, `diseases`, `claim-batches`, `product-sources`, `product-categories`, `products`, `categories`, `coverage-groups`, `tier0`, `product-pricing`, `policies`, `benefits`, `plans-rewire`, `beneficiaries-principals`, `beneficiaries-dependants`, `beneficiary-photos`, `claims`.
149
+
150
+ **Pause/resume**: every step is idempotent and cursor-backed — stop the execution and re-invoke later (optionally with `fromStep`). Completed resources no-op on the first producer invocation (`endReached` immediately). Guards fail the execution instead of looping forever: 2,000 producer invocations per pass, 600 drain checks (5-minute interval). Execution timeout 7 days.
151
+
152
+ **Monitoring**: Step Functions execution history; state-machine logs at `/aws/vendedlogs/states/migration-orchestrator`; ECS task logs under `/aws/ecs/migration-scripts`; the verifier summary in S3.
153
+
154
+ **Notes**: the consumer's reserved concurrency is set to `max(50, MIGRATION_QUEUE_SHARDS)` so claims FIFO shards run in parallel. `fresh: true` truncates `migrated`/`disease_lookup`/`claim_batches` and clears the `glico_healthcare_migration:*` Redis cursors before restoring; the restore task re-imports all tables per run (container-local tracking). Secure envs (`DB_PASSWORD`, `MIGRATION_API_KEY`) are injected into the ECS task from SSM.
155
+
99
156
  ### Pipeline-based stack
100
157
 
101
158
  The following stack on the other hand, are meant to deploy a new set of resources on each CDK deployment. These can also be thought of as the stack that have a GIT repository.
@@ -16,7 +16,7 @@ export type BuildConfig = {
16
16
  };
17
17
  };
18
18
  export type Microservice = 'account' | 'plan' | 'policy' | 'claims' | 'notification' | 'reporting';
19
- export type OtherCDKService = 'network' | 'api-gateway' | 'redis' | 'mysql' | 'portal' | 'migration';
19
+ export type OtherCDKService = 'network' | 'infra-auth' | 'api-gateway' | 'redis' | 'mysql' | 'clickhouse' | 'portal' | 'migration';
20
20
  export declare const MicroserviceEnum: Record<Microservice, Microservice>;
21
21
  export declare const MicroserviceList: Microservice[];
22
22
  export declare const LaravelBasedServiceList: ("account" | "plan" | "policy" | "claims" | "reporting")[];
@@ -13,11 +13,13 @@ exports.MicroserviceList = Object.values(exports.MicroserviceEnum);
13
13
  exports.LaravelBasedServiceList = exports.MicroserviceList.filter((i) => i !== 'notification');
14
14
  exports.OtherCDKServiceEnum = {
15
15
  network: 'network',
16
+ 'infra-auth': 'infra-auth',
16
17
  'api-gateway': 'api-gateway',
17
18
  redis: 'redis',
18
19
  mysql: 'mysql',
20
+ clickhouse: 'clickhouse',
19
21
  portal: 'portal',
20
22
  migration: 'migration',
21
23
  };
22
24
  exports.OtherCDKServiceList = Object.values(exports.OtherCDKServiceEnum);
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vQHR5cGVzL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFxQmEsUUFBQSxnQkFBZ0IsR0FBdUM7SUFDbEUsT0FBTyxFQUFFLFNBQVM7SUFDbEIsSUFBSSxFQUFFLE1BQU07SUFDWixNQUFNLEVBQUUsUUFBUTtJQUNoQixZQUFZLEVBQUUsY0FBYztJQUM1QixTQUFTLEVBQUUsV0FBVztJQUN0QixNQUFNLEVBQUUsUUFBUTtDQUNqQixDQUFDO0FBRVcsUUFBQSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUFnQixDQUFDLENBQUM7QUFFbkQsUUFBQSx1QkFBdUIsR0FBRyx3QkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQztBQUUvRSxRQUFBLG1CQUFtQixHQUE2QztJQUMzRSxPQUFPLEVBQUUsU0FBUztJQUNsQixhQUFhLEVBQUUsYUFBYTtJQUM1QixLQUFLLEVBQUUsT0FBTztJQUNkLEtBQUssRUFBRSxPQUFPO0lBQ2QsTUFBTSxFQUFFLFFBQVE7SUFDaEIsU0FBUyxFQUFFLFdBQVc7Q0FDdkIsQ0FBQztBQUVXLFFBQUEsbUJBQW1CLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQywyQkFBbUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgRW52TmFtZSA9ICd1YXQnIHwgJ3Byb2QnO1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaCA9ICdtYXN0ZXInIHwgJ3JlbGVhc2UnO1xuZXhwb3J0IHR5cGUgQnVpbGRDb25maWcgPSB7XG4gIGFwcE5hbWU6IHN0cmluZztcbiAgYXBwVmVyc2lvbjogc3RyaW5nO1xuICBidWlsZElkOiBzdHJpbmc7XG4gIGZvcm1hdHRlZEJ1aWxkSWQ6IHN0cmluZztcbiAgZW52TmFtZTogRW52TmFtZTtcbiAgZW52UGF0aDogc3RyaW5nO1xuICBzZXJ2aWNlTmFtZTogTWljcm9zZXJ2aWNlIHwgT3RoZXJDREtTZXJ2aWNlO1xuICBicmFuY2g/OiBzdHJpbmc7XG4gIGNvbXBhbnlOYW1lOiBzdHJpbmc7XG4gIGF3czoge1xuICAgIGFjY291bnQ6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgfTtcbn07XG5leHBvcnQgdHlwZSBNaWNyb3NlcnZpY2UgPSAnYWNjb3VudCcgfCAncGxhbicgfCAncG9saWN5JyB8ICdjbGFpbXMnIHwgJ25vdGlmaWNhdGlvbicgfCAncmVwb3J0aW5nJztcblxuZXhwb3J0IHR5cGUgT3RoZXJDREtTZXJ2aWNlID0gJ25ldHdvcmsnIHwgJ2FwaS1nYXRld2F5JyB8ICdyZWRpcycgfCAnbXlzcWwnIHwgJ3BvcnRhbCcgfCAnbWlncmF0aW9uJztcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUVudW06IFJlY29yZDxNaWNyb3NlcnZpY2UsIE1pY3Jvc2VydmljZT4gPSB7XG4gIGFjY291bnQ6ICdhY2NvdW50JyxcbiAgcGxhbjogJ3BsYW4nLFxuICBwb2xpY3k6ICdwb2xpY3knLFxuICBub3RpZmljYXRpb246ICdub3RpZmljYXRpb24nLFxuICByZXBvcnRpbmc6ICdyZXBvcnRpbmcnLFxuICBjbGFpbXM6ICdjbGFpbXMnLFxufTtcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUxpc3QgPSBPYmplY3QudmFsdWVzKE1pY3Jvc2VydmljZUVudW0pO1xuXG5leHBvcnQgY29uc3QgTGFyYXZlbEJhc2VkU2VydmljZUxpc3QgPSBNaWNyb3NlcnZpY2VMaXN0LmZpbHRlcigoaSkgPT4gaSAhPT0gJ25vdGlmaWNhdGlvbicpO1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlRW51bTogUmVjb3JkPE90aGVyQ0RLU2VydmljZSwgT3RoZXJDREtTZXJ2aWNlPiA9IHtcbiAgbmV0d29yazogJ25ldHdvcmsnLFxuICAnYXBpLWdhdGV3YXknOiAnYXBpLWdhdGV3YXknLFxuICByZWRpczogJ3JlZGlzJyxcbiAgbXlzcWw6ICdteXNxbCcsXG4gIHBvcnRhbDogJ3BvcnRhbCcsXG4gIG1pZ3JhdGlvbjogJ21pZ3JhdGlvbicsXG59O1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlTGlzdCA9IE9iamVjdC52YWx1ZXMoT3RoZXJDREtTZXJ2aWNlRW51bSk7XG5cbmV4cG9ydCB0eXBlIFJlcG9VcmxzID0geyBba2V5IGluIEJ1aWxkQ29uZmlnWydzZXJ2aWNlTmFtZSddXT86IHN0cmluZyB9O1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaGVzID0geyBba2V5IGluIEVudk5hbWVdOiBSZXBvQnJhbmNoIH07XG4iXX0=
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vQHR5cGVzL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFxQmEsUUFBQSxnQkFBZ0IsR0FBdUM7SUFDbEUsT0FBTyxFQUFFLFNBQVM7SUFDbEIsSUFBSSxFQUFFLE1BQU07SUFDWixNQUFNLEVBQUUsUUFBUTtJQUNoQixZQUFZLEVBQUUsY0FBYztJQUM1QixTQUFTLEVBQUUsV0FBVztJQUN0QixNQUFNLEVBQUUsUUFBUTtDQUNqQixDQUFDO0FBRVcsUUFBQSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUFnQixDQUFDLENBQUM7QUFFbkQsUUFBQSx1QkFBdUIsR0FBRyx3QkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQztBQUUvRSxRQUFBLG1CQUFtQixHQUE2QztJQUMzRSxPQUFPLEVBQUUsU0FBUztJQUNsQixZQUFZLEVBQUUsWUFBWTtJQUMxQixhQUFhLEVBQUUsYUFBYTtJQUM1QixLQUFLLEVBQUUsT0FBTztJQUNkLEtBQUssRUFBRSxPQUFPO0lBQ2QsVUFBVSxFQUFFLFlBQVk7SUFDeEIsTUFBTSxFQUFFLFFBQVE7SUFDaEIsU0FBUyxFQUFFLFdBQVc7Q0FDdkIsQ0FBQztBQUVXLFFBQUEsbUJBQW1CLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQywyQkFBbUIsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgRW52TmFtZSA9ICd1YXQnIHwgJ3Byb2QnO1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaCA9ICdtYXN0ZXInIHwgJ3JlbGVhc2UnO1xuZXhwb3J0IHR5cGUgQnVpbGRDb25maWcgPSB7XG4gIGFwcE5hbWU6IHN0cmluZztcbiAgYXBwVmVyc2lvbjogc3RyaW5nO1xuICBidWlsZElkOiBzdHJpbmc7XG4gIGZvcm1hdHRlZEJ1aWxkSWQ6IHN0cmluZztcbiAgZW52TmFtZTogRW52TmFtZTtcbiAgZW52UGF0aDogc3RyaW5nO1xuICBzZXJ2aWNlTmFtZTogTWljcm9zZXJ2aWNlIHwgT3RoZXJDREtTZXJ2aWNlO1xuICBicmFuY2g/OiBzdHJpbmc7XG4gIGNvbXBhbnlOYW1lOiBzdHJpbmc7XG4gIGF3czoge1xuICAgIGFjY291bnQ6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgfTtcbn07XG5leHBvcnQgdHlwZSBNaWNyb3NlcnZpY2UgPSAnYWNjb3VudCcgfCAncGxhbicgfCAncG9saWN5JyB8ICdjbGFpbXMnIHwgJ25vdGlmaWNhdGlvbicgfCAncmVwb3J0aW5nJztcblxuZXhwb3J0IHR5cGUgT3RoZXJDREtTZXJ2aWNlID0gJ25ldHdvcmsnIHwgJ2luZnJhLWF1dGgnIHwgJ2FwaS1nYXRld2F5JyB8ICdyZWRpcycgfCAnbXlzcWwnIHwgJ2NsaWNraG91c2UnIHwgJ3BvcnRhbCcgfCAnbWlncmF0aW9uJztcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUVudW06IFJlY29yZDxNaWNyb3NlcnZpY2UsIE1pY3Jvc2VydmljZT4gPSB7XG4gIGFjY291bnQ6ICdhY2NvdW50JyxcbiAgcGxhbjogJ3BsYW4nLFxuICBwb2xpY3k6ICdwb2xpY3knLFxuICBub3RpZmljYXRpb246ICdub3RpZmljYXRpb24nLFxuICByZXBvcnRpbmc6ICdyZXBvcnRpbmcnLFxuICBjbGFpbXM6ICdjbGFpbXMnLFxufTtcblxuZXhwb3J0IGNvbnN0IE1pY3Jvc2VydmljZUxpc3QgPSBPYmplY3QudmFsdWVzKE1pY3Jvc2VydmljZUVudW0pO1xuXG5leHBvcnQgY29uc3QgTGFyYXZlbEJhc2VkU2VydmljZUxpc3QgPSBNaWNyb3NlcnZpY2VMaXN0LmZpbHRlcigoaSkgPT4gaSAhPT0gJ25vdGlmaWNhdGlvbicpO1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlRW51bTogUmVjb3JkPE90aGVyQ0RLU2VydmljZSwgT3RoZXJDREtTZXJ2aWNlPiA9IHtcbiAgbmV0d29yazogJ25ldHdvcmsnLFxuICAnaW5mcmEtYXV0aCc6ICdpbmZyYS1hdXRoJyxcbiAgJ2FwaS1nYXRld2F5JzogJ2FwaS1nYXRld2F5JyxcbiAgcmVkaXM6ICdyZWRpcycsXG4gIG15c3FsOiAnbXlzcWwnLFxuICBjbGlja2hvdXNlOiAnY2xpY2tob3VzZScsXG4gIHBvcnRhbDogJ3BvcnRhbCcsXG4gIG1pZ3JhdGlvbjogJ21pZ3JhdGlvbicsXG59O1xuXG5leHBvcnQgY29uc3QgT3RoZXJDREtTZXJ2aWNlTGlzdCA9IE9iamVjdC52YWx1ZXMoT3RoZXJDREtTZXJ2aWNlRW51bSk7XG5cbmV4cG9ydCB0eXBlIFJlcG9VcmxzID0geyBba2V5IGluIEJ1aWxkQ29uZmlnWydzZXJ2aWNlTmFtZSddXT86IHN0cmluZyB9O1xuZXhwb3J0IHR5cGUgUmVwb0JyYW5jaGVzID0geyBba2V5IGluIEVudk5hbWVdOiBSZXBvQnJhbmNoIH07XG4iXX0=
@@ -0,0 +1,19 @@
1
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
+ import * as ecs from 'aws-cdk-lib/aws-ecs';
3
+ import * as s3 from 'aws-cdk-lib/aws-s3';
4
+ import { Construct } from 'constructs';
5
+ export interface MigrationScriptsRunnerProps {
6
+ vpc: ec2.IVpc;
7
+ artifactsBucket: s3.IBucket;
8
+ backupPrefix?: string;
9
+ cpu?: number;
10
+ memoryLimitMiB?: number;
11
+ ephemeralStorageGiB?: number;
12
+ }
13
+ export declare class MigrationScriptsRunner extends Construct {
14
+ readonly cluster: ecs.Cluster;
15
+ readonly securityGroup: ec2.SecurityGroup;
16
+ readonly taskDefinition: ecs.FargateTaskDefinition;
17
+ readonly container: ecs.ContainerDefinition;
18
+ constructor(scope: Construct, id: string, props: MigrationScriptsRunnerProps);
19
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MigrationScriptsRunner = void 0;
4
+ const cdk = require("aws-cdk-lib");
5
+ const ec2 = require("aws-cdk-lib/aws-ec2");
6
+ const ecs = require("aws-cdk-lib/aws-ecs");
7
+ const logs = require("aws-cdk-lib/aws-logs");
8
+ const path = require("path");
9
+ const constructs_1 = require("constructs");
10
+ const migration_1 = require("../util/migration");
11
+ // One-shot Fargate tasks that run the migration scripts (restore, migrations,
12
+ // precompute-diseases, precompute-claim-batches, reset) unchanged. The state
13
+ // machine overrides the container command per step.
14
+ class MigrationScriptsRunner extends constructs_1.Construct {
15
+ constructor(scope, id, props) {
16
+ super(scope, id);
17
+ this.cluster = new ecs.Cluster(this, 'Cluster', {
18
+ vpc: props.vpc,
19
+ clusterName: 'migration-scripts',
20
+ });
21
+ this.securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
22
+ vpc: props.vpc,
23
+ securityGroupName: 'Migration-Scripts-SG',
24
+ description: 'Migration scripts ECS tasks',
25
+ allowAllOutbound: true,
26
+ });
27
+ this.taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {
28
+ family: 'migration-scripts',
29
+ cpu: props.cpu ?? 4096,
30
+ memoryLimitMiB: props.memoryLimitMiB ?? 8192,
31
+ ephemeralStorageGiB: props.ephemeralStorageGiB ?? 21,
32
+ runtimePlatform: {
33
+ cpuArchitecture: ecs.CpuArchitecture.X86_64,
34
+ operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
35
+ },
36
+ });
37
+ const { environment, secrets } = (0, migration_1.getEcsEnvs)(cdk.Stack.of(this));
38
+ this.container = this.taskDefinition.addContainer('scripts', {
39
+ containerName: 'scripts',
40
+ image: ecs.ContainerImage.fromAsset(path.resolve('../../migration'), { file: 'Dockerfile' }),
41
+ environment,
42
+ secrets,
43
+ logging: ecs.LogDrivers.awsLogs({
44
+ streamPrefix: 'migration-scripts',
45
+ logRetention: logs.RetentionDays.ONE_MONTH,
46
+ }),
47
+ });
48
+ props.artifactsBucket.grantRead(this.taskDefinition.taskRole, `${props.backupPrefix ?? 'backups'}/*`);
49
+ }
50
+ }
51
+ exports.MigrationScriptsRunner = MigrationScriptsRunner;
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLXNjcmlwdHMtcnVubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vY29uc3RydWN0cy9taWdyYXRpb24tc2NyaXB0cy1ydW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBQ25DLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsNkNBQTZDO0FBRTdDLDZCQUE2QjtBQUM3QiwyQ0FBdUM7QUFDdkMsaURBQStDO0FBVy9DLDhFQUE4RTtBQUM5RSw2RUFBNkU7QUFDN0Usb0RBQW9EO0FBQ3BELE1BQWEsc0JBQXVCLFNBQVEsc0JBQVM7SUFNbkQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUU7WUFDOUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO1lBQ2QsV0FBVyxFQUFFLG1CQUFtQjtTQUNqQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksR0FBRyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQ2hFLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRztZQUNkLGlCQUFpQixFQUFFLHNCQUFzQjtZQUN6QyxXQUFXLEVBQUUsNkJBQTZCO1lBQzFDLGdCQUFnQixFQUFFLElBQUk7U0FDdkIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDMUUsTUFBTSxFQUFFLG1CQUFtQjtZQUMzQixHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJO1lBQ3RCLGNBQWMsRUFBRSxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUk7WUFDNUMsbUJBQW1CLEVBQUUsS0FBSyxDQUFDLG1CQUFtQixJQUFJLEVBQUU7WUFDcEQsZUFBZSxFQUFFO2dCQUNmLGVBQWUsRUFBRSxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU07Z0JBQzNDLHFCQUFxQixFQUFFLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLO2FBQ3ZEO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFBLHNCQUFVLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUVoRSxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRTtZQUMzRCxhQUFhLEVBQUUsU0FBUztZQUN4QixLQUFLLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO1lBQzVGLFdBQVc7WUFDWCxPQUFPO1lBQ1AsT0FBTyxFQUFFLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUM5QixZQUFZLEVBQUUsbUJBQW1CO2dCQUNqQyxZQUFZLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTO2FBQzNDLENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCxLQUFLLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxHQUFHLEtBQUssQ0FBQyxZQUFZLElBQUksU0FBUyxJQUFJLENBQUMsQ0FBQztJQUN4RyxDQUFDO0NBQ0Y7QUEvQ0Qsd0RBK0NDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGVjcyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNzJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGdldEVjc0VudnMgfSBmcm9tICcuLi91dGlsL21pZ3JhdGlvbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0aW9uU2NyaXB0c1J1bm5lclByb3BzIHtcbiAgdnBjOiBlYzIuSVZwYztcbiAgYXJ0aWZhY3RzQnVja2V0OiBzMy5JQnVja2V0O1xuICBiYWNrdXBQcmVmaXg/OiBzdHJpbmc7XG4gIGNwdT86IG51bWJlcjtcbiAgbWVtb3J5TGltaXRNaUI/OiBudW1iZXI7XG4gIGVwaGVtZXJhbFN0b3JhZ2VHaUI/OiBudW1iZXI7XG59XG5cbi8vIE9uZS1zaG90IEZhcmdhdGUgdGFza3MgdGhhdCBydW4gdGhlIG1pZ3JhdGlvbiBzY3JpcHRzIChyZXN0b3JlLCBtaWdyYXRpb25zLFxuLy8gcHJlY29tcHV0ZS1kaXNlYXNlcywgcHJlY29tcHV0ZS1jbGFpbS1iYXRjaGVzLCByZXNldCkgdW5jaGFuZ2VkLiBUaGUgc3RhdGVcbi8vIG1hY2hpbmUgb3ZlcnJpZGVzIHRoZSBjb250YWluZXIgY29tbWFuZCBwZXIgc3RlcC5cbmV4cG9ydCBjbGFzcyBNaWdyYXRpb25TY3JpcHRzUnVubmVyIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IGNsdXN0ZXI6IGVjcy5DbHVzdGVyO1xuICBwdWJsaWMgcmVhZG9ubHkgc2VjdXJpdHlHcm91cDogZWMyLlNlY3VyaXR5R3JvdXA7XG4gIHB1YmxpYyByZWFkb25seSB0YXNrRGVmaW5pdGlvbjogZWNzLkZhcmdhdGVUYXNrRGVmaW5pdGlvbjtcbiAgcHVibGljIHJlYWRvbmx5IGNvbnRhaW5lcjogZWNzLkNvbnRhaW5lckRlZmluaXRpb247XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IE1pZ3JhdGlvblNjcmlwdHNSdW5uZXJQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLmNsdXN0ZXIgPSBuZXcgZWNzLkNsdXN0ZXIodGhpcywgJ0NsdXN0ZXInLCB7XG4gICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgIGNsdXN0ZXJOYW1lOiAnbWlncmF0aW9uLXNjcmlwdHMnLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZWN1cml0eUdyb3VwID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdTZWN1cml0eUdyb3VwJywge1xuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICBzZWN1cml0eUdyb3VwTmFtZTogJ01pZ3JhdGlvbi1TY3JpcHRzLVNHJyxcbiAgICAgIGRlc2NyaXB0aW9uOiAnTWlncmF0aW9uIHNjcmlwdHMgRUNTIHRhc2tzJyxcbiAgICAgIGFsbG93QWxsT3V0Ym91bmQ6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLnRhc2tEZWZpbml0aW9uID0gbmV3IGVjcy5GYXJnYXRlVGFza0RlZmluaXRpb24odGhpcywgJ1Rhc2tEZWZpbml0aW9uJywge1xuICAgICAgZmFtaWx5OiAnbWlncmF0aW9uLXNjcmlwdHMnLFxuICAgICAgY3B1OiBwcm9wcy5jcHUgPz8gNDA5NixcbiAgICAgIG1lbW9yeUxpbWl0TWlCOiBwcm9wcy5tZW1vcnlMaW1pdE1pQiA/PyA4MTkyLFxuICAgICAgZXBoZW1lcmFsU3RvcmFnZUdpQjogcHJvcHMuZXBoZW1lcmFsU3RvcmFnZUdpQiA/PyAyMSxcbiAgICAgIHJ1bnRpbWVQbGF0Zm9ybToge1xuICAgICAgICBjcHVBcmNoaXRlY3R1cmU6IGVjcy5DcHVBcmNoaXRlY3R1cmUuWDg2XzY0LFxuICAgICAgICBvcGVyYXRpbmdTeXN0ZW1GYW1pbHk6IGVjcy5PcGVyYXRpbmdTeXN0ZW1GYW1pbHkuTElOVVgsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyBlbnZpcm9ubWVudCwgc2VjcmV0cyB9ID0gZ2V0RWNzRW52cyhjZGsuU3RhY2sub2YodGhpcykpO1xuXG4gICAgdGhpcy5jb250YWluZXIgPSB0aGlzLnRhc2tEZWZpbml0aW9uLmFkZENvbnRhaW5lcignc2NyaXB0cycsIHtcbiAgICAgIGNvbnRhaW5lck5hbWU6ICdzY3JpcHRzJyxcbiAgICAgIGltYWdlOiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbUFzc2V0KHBhdGgucmVzb2x2ZSgnLi4vLi4vbWlncmF0aW9uJyksIHsgZmlsZTogJ0RvY2tlcmZpbGUnIH0pLFxuICAgICAgZW52aXJvbm1lbnQsXG4gICAgICBzZWNyZXRzLFxuICAgICAgbG9nZ2luZzogZWNzLkxvZ0RyaXZlcnMuYXdzTG9ncyh7XG4gICAgICAgIHN0cmVhbVByZWZpeDogJ21pZ3JhdGlvbi1zY3JpcHRzJyxcbiAgICAgICAgbG9nUmV0ZW50aW9uOiBsb2dzLlJldGVudGlvbkRheXMuT05FX01PTlRILFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBwcm9wcy5hcnRpZmFjdHNCdWNrZXQuZ3JhbnRSZWFkKHRoaXMudGFza0RlZmluaXRpb24udGFza1JvbGUsIGAke3Byb3BzLmJhY2t1cFByZWZpeCA/PyAnYmFja3Vwcyd9LypgKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,40 @@
1
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
+ import * as ecs from 'aws-cdk-lib/aws-ecs';
3
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
4
+ import * as s3 from 'aws-cdk-lib/aws-s3';
5
+ import * as sqs from 'aws-cdk-lib/aws-sqs';
6
+ import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
7
+ import { Construct } from 'constructs';
8
+ export interface MigrationStateMachineProps {
9
+ producer: lambda.IFunction;
10
+ verifier: lambda.IFunction;
11
+ queue: sqs.IQueue;
12
+ cluster: ecs.ICluster;
13
+ taskDefinition: ecs.TaskDefinition;
14
+ container: ecs.ContainerDefinition;
15
+ securityGroup: ec2.ISecurityGroup;
16
+ artifactsBucket: s3.IBucket;
17
+ maxInvocations?: number;
18
+ drainMaxChecks?: number;
19
+ loopWaitSeconds?: number;
20
+ drainWaitSeconds?: number;
21
+ }
22
+ export declare class MigrationStateMachine extends Construct {
23
+ readonly stateMachine: sfn.StateMachine;
24
+ private readonly producer;
25
+ private readonly verifier;
26
+ private readonly queue;
27
+ private readonly cluster;
28
+ private readonly taskDefinition;
29
+ private readonly container;
30
+ private readonly securityGroup;
31
+ private readonly artifactsBucket;
32
+ private readonly maxInvocations;
33
+ private readonly drainMaxChecks;
34
+ private readonly loopWaitSeconds;
35
+ private readonly drainWaitSeconds;
36
+ constructor(scope: Construct, id: string, props: MigrationStateMachineProps);
37
+ private producerPass;
38
+ private resourceStep;
39
+ private ecsStep;
40
+ }
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MigrationStateMachine = void 0;
4
+ const cdk = require("aws-cdk-lib");
5
+ const ec2 = require("aws-cdk-lib/aws-ec2");
6
+ const ecs = require("aws-cdk-lib/aws-ecs");
7
+ const logs = require("aws-cdk-lib/aws-logs");
8
+ const sfn = require("aws-cdk-lib/aws-stepfunctions");
9
+ const tasks = require("aws-cdk-lib/aws-stepfunctions-tasks");
10
+ const constructs_1 = require("constructs");
11
+ // Runs the runbook end-to-end: scripts as one-shot Fargate tasks, SQS
12
+ // migratables as producer loops (until endReached) followed by a queue drain
13
+ // and a skipMigrated retry pass, then the verifier summary.
14
+ class MigrationStateMachine extends constructs_1.Construct {
15
+ constructor(scope, id, props) {
16
+ super(scope, id);
17
+ this.producer = props.producer;
18
+ this.verifier = props.verifier;
19
+ this.queue = props.queue;
20
+ this.cluster = props.cluster;
21
+ this.taskDefinition = props.taskDefinition;
22
+ this.container = props.container;
23
+ this.securityGroup = props.securityGroup;
24
+ this.artifactsBucket = props.artifactsBucket;
25
+ this.maxInvocations = props.maxInvocations ?? 2000;
26
+ this.drainMaxChecks = props.drainMaxChecks ?? 600;
27
+ this.loopWaitSeconds = props.loopWaitSeconds ?? 10;
28
+ this.drainWaitSeconds = props.drainWaitSeconds ?? 300;
29
+ const entries = {};
30
+ const verify = new tasks.LambdaInvoke(this, 'Verify', {
31
+ lambdaFunction: this.verifier,
32
+ payload: sfn.TaskInput.fromObject({
33
+ runId: sfn.JsonPath.stringAt('$$.Execution.Name'),
34
+ bucket: this.artifactsBucket.bucketName,
35
+ key: sfn.JsonPath.format('runs/{}/summary.json', sfn.JsonPath.stringAt('$$.Execution.Name')),
36
+ }),
37
+ payloadResponseOnly: true,
38
+ resultPath: '$.verification',
39
+ });
40
+ const complete = new sfn.Succeed(this, 'Complete');
41
+ verify.next(complete);
42
+ let tail = verify;
43
+ entries['claims'] = this.resourceStep('s16-claims', { resource: 'claims' }, tail);
44
+ tail = entries['claims'];
45
+ const photos = this.resourceStep('s15-beneficiary-photos', { resource: 'beneficiary-photos' }, tail);
46
+ entries['beneficiary-photos'] = photos;
47
+ const photosChoice = new sfn.Choice(this, 'SkipPhotos').when(sfn.Condition.booleanEquals('$.skipPhotos', true), tail).otherwise(photos);
48
+ tail = photosChoice;
49
+ entries['beneficiaries-dependants'] = this.resourceStep('s14b-beneficiaries-dependants', { resource: 'beneficiaries', phase: 'dependants' }, tail);
50
+ tail = entries['beneficiaries-dependants'];
51
+ entries['beneficiaries-principals'] = this.resourceStep('s14a-beneficiaries-principals', { resource: 'beneficiaries', phase: 'principals' }, tail);
52
+ tail = entries['beneficiaries-principals'];
53
+ entries['plans-rewire'] = this.resourceStep('s13b-plans-rewire', { resource: 'plans' }, tail);
54
+ tail = entries['plans-rewire'];
55
+ entries['benefits'] = this.resourceStep('s12-benefits', { resource: 'benefits' }, tail);
56
+ tail = entries['benefits'];
57
+ entries['policies'] = this.resourceStep('s11-policies', { resource: 'policies' }, tail);
58
+ tail = entries['policies'];
59
+ entries['product-pricing'] = this.resourceStep('s10-product-pricing', { resource: 'product-pricing' }, tail);
60
+ tail = entries['product-pricing'];
61
+ const tier0 = new sfn.Parallel(this, 's9-tier0', { resultPath: '$.tier0' });
62
+ for (const resource of ['users', 'providers', 'insured', 'tpa', 'plans']) {
63
+ tier0.branch(sfn.Chain.start(this.resourceStep(`s9-${resource}`, { resource })));
64
+ }
65
+ tier0.next(tail);
66
+ entries['tier0'] = tier0;
67
+ tail = tier0;
68
+ entries['coverage-groups'] = this.resourceStep('s8-coverage-groups', { resource: 'coverage-groups' }, tail);
69
+ tail = entries['coverage-groups'];
70
+ entries['categories'] = this.resourceStep('s7-categories', { resource: 'categories' }, tail);
71
+ tail = entries['categories'];
72
+ entries['products'] = this.resourceStep('s6-products', { resource: 'products' }, tail);
73
+ tail = entries['products'];
74
+ entries['product-categories'] = this.resourceStep('s5b-product-categories', { resource: 'product-categories' }, tail);
75
+ tail = entries['product-categories'];
76
+ entries['product-sources'] = this.resourceStep('s5a-product-sources', { resource: 'product-sources' }, tail);
77
+ tail = entries['product-sources'];
78
+ entries['claim-batches'] = this.ecsStep('s4-claim-batches', 'claim-batches', [], cdk.Duration.hours(2), tail);
79
+ tail = entries['claim-batches'];
80
+ entries['diseases'] = this.ecsStep('s3-disease-lookups', 'diseases', [], cdk.Duration.hours(1), tail);
81
+ tail = entries['diseases'];
82
+ entries['migrations'] = this.ecsStep('s2-migrations', 'migrations', [], cdk.Duration.hours(1), tail);
83
+ tail = entries['migrations'];
84
+ const restore = this.ecsStep('s1-restore', 'restore', [{ name: 'BACKUP_S3_URI', value: sfn.JsonPath.stringAt('$.backupS3Uri') }], cdk.Duration.hours(3), tail);
85
+ entries['restore'] = restore;
86
+ tail = restore;
87
+ const reset = this.ecsStep('s0-fresh-reset', 'reset', [], cdk.Duration.minutes(30), restore);
88
+ entries['fresh-reset'] = reset;
89
+ const freshChoice = new sfn.Choice(this, 'FreshReset').when(sfn.Condition.booleanEquals('$.fresh', true), reset).otherwise(restore);
90
+ tail = freshChoice;
91
+ const fromStep = new sfn.Choice(this, 'FromStep');
92
+ for (const [stepId, entry] of Object.entries(entries)) {
93
+ fromStep.when(sfn.Condition.and(sfn.Condition.isPresent('$.fromStep'), sfn.Condition.stringEquals('$.fromStep', stepId)), entry);
94
+ }
95
+ fromStep.otherwise(freshChoice);
96
+ tail = fromStep;
97
+ const logGroup = new logs.LogGroup(this, 'Logs', {
98
+ logGroupName: '/aws/vendedlogs/states/migration-orchestrator',
99
+ retention: logs.RetentionDays.THREE_MONTHS,
100
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
101
+ });
102
+ this.stateMachine = new sfn.StateMachine(this, 'StateMachine', {
103
+ stateMachineName: 'migration-orchestrator',
104
+ definitionBody: sfn.DefinitionBody.fromChainable(tail),
105
+ timeout: cdk.Duration.days(7),
106
+ logs: {
107
+ destination: logGroup,
108
+ level: sfn.LogLevel.ALL,
109
+ includeExecutionData: true,
110
+ },
111
+ });
112
+ this.producer.grantInvoke(this.stateMachine);
113
+ this.verifier.grantInvoke(this.stateMachine);
114
+ this.queue.grant(this.stateMachine, 'sqs:GetQueueAttributes');
115
+ this.taskDefinition.grantRun(this.stateMachine);
116
+ }
117
+ // Producer loop (until endReached, guarded by maxInvocations) -> queue drain
118
+ // (Visible + NotVisible = 0, guarded by drainMaxChecks) -> next.
119
+ producerPass(id, payload, next) {
120
+ const failure = new sfn.Fail(this, `${id}-Failed`, {
121
+ error: 'MigrationStepFailed',
122
+ cause: `Step ${id} exceeded its iteration/drain guard, or an ECS script task failed.`,
123
+ });
124
+ const init = new sfn.Pass(this, `${id}-LoopInit`, {
125
+ parameters: { count: 0 },
126
+ resultPath: '$.loop',
127
+ });
128
+ const invoke = new tasks.LambdaInvoke(this, `${id}-Invoke`, {
129
+ lambdaFunction: this.producer,
130
+ payload: sfn.TaskInput.fromObject(payload),
131
+ payloadResponseOnly: true,
132
+ resultPath: '$.producer',
133
+ taskTimeout: sfn.Timeout.duration(cdk.Duration.minutes(15)),
134
+ });
135
+ invoke.addRetry({
136
+ errors: ['States.TaskFailed', 'Lambda.ServiceException', 'Lambda.AWSLambdaException', 'Lambda.SdkClientException'],
137
+ maxAttempts: 2,
138
+ interval: cdk.Duration.seconds(30),
139
+ backoffRate: 2,
140
+ });
141
+ const endReached = new sfn.Choice(this, `${id}-EndReached`);
142
+ const loopInc = new sfn.Pass(this, `${id}-LoopInc`, {
143
+ parameters: { count: sfn.JsonPath.mathAdd(sfn.JsonPath.numberAt('$.loop.count'), 1) },
144
+ resultPath: '$.loop',
145
+ });
146
+ const loopGuard = new sfn.Choice(this, `${id}-LoopGuard`).when(sfn.Condition.numberGreaterThan('$.loop.count', this.maxInvocations), failure);
147
+ const loopWait = new sfn.Wait(this, `${id}-LoopWait`, {
148
+ time: sfn.WaitTime.duration(cdk.Duration.seconds(this.loopWaitSeconds)),
149
+ });
150
+ const drainInit = new sfn.Pass(this, `${id}-DrainInit`, {
151
+ parameters: { count: 0 },
152
+ resultPath: '$.drain',
153
+ });
154
+ const drainGet = new tasks.CallAwsService(this, `${id}-QueueAttributes`, {
155
+ service: 'sqs',
156
+ action: 'getQueueAttributes',
157
+ parameters: {
158
+ QueueUrl: this.queue.queueUrl,
159
+ AttributeNames: ['ApproximateNumberOfMessages', 'ApproximateNumberOfMessagesNotVisible'],
160
+ },
161
+ iamResources: [this.queue.queueArn],
162
+ resultPath: '$.queue',
163
+ });
164
+ const drained = new sfn.Choice(this, `${id}-Drained`).when(sfn.Condition.and(sfn.Condition.stringEquals('$.queue.Attributes.ApproximateNumberOfMessages', '0'), sfn.Condition.stringEquals('$.queue.Attributes.ApproximateNumberOfMessagesNotVisible', '0')), next);
165
+ const drainInc = new sfn.Pass(this, `${id}-DrainInc`, {
166
+ parameters: { count: sfn.JsonPath.mathAdd(sfn.JsonPath.numberAt('$.drain.count'), 1) },
167
+ resultPath: '$.drain',
168
+ });
169
+ const drainGuard = new sfn.Choice(this, `${id}-DrainGuard`).when(sfn.Condition.numberGreaterThan('$.drain.count', this.drainMaxChecks), failure);
170
+ const drainWait = new sfn.Wait(this, `${id}-DrainWait`, {
171
+ time: sfn.WaitTime.duration(cdk.Duration.seconds(this.drainWaitSeconds)),
172
+ });
173
+ init.next(invoke);
174
+ invoke.next(endReached);
175
+ endReached.when(sfn.Condition.booleanEquals('$.producer.endReached', true), drainInit).otherwise(loopInc);
176
+ loopInc.next(loopGuard);
177
+ loopGuard.otherwise(loopWait);
178
+ loopWait.next(invoke);
179
+ drainInit.next(drainGet);
180
+ drainGet.next(drained);
181
+ drained.otherwise(drainInc);
182
+ drainInc.next(drainGuard);
183
+ drainGuard.otherwise(drainWait);
184
+ drainWait.next(drainGet);
185
+ return init;
186
+ }
187
+ // Main pass, then a skipMigrated retry pass (fromStart) that re-publishes
188
+ // only records without a migrated row.
189
+ resourceStep(id, payload, next) {
190
+ const terminal = next ?? new sfn.Succeed(this, `${id}-Done`);
191
+ const retry = this.producerPass(`${id}-Retry`, { ...payload, fromStart: true, skipMigrated: true }, terminal);
192
+ return this.producerPass(id, payload, retry);
193
+ }
194
+ ecsStep(id, command, environment, timeout, next) {
195
+ const run = new tasks.EcsRunTask(this, id, {
196
+ integrationPattern: sfn.IntegrationPattern.RUN_JOB,
197
+ cluster: this.cluster,
198
+ taskDefinition: this.taskDefinition,
199
+ launchTarget: new tasks.EcsFargateLaunchTarget({ platformVersion: ecs.FargatePlatformVersion.LATEST }),
200
+ containerOverrides: [
201
+ {
202
+ containerDefinition: this.container,
203
+ command: [command],
204
+ environment,
205
+ },
206
+ ],
207
+ subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
208
+ securityGroups: [this.securityGroup],
209
+ assignPublicIp: false,
210
+ taskTimeout: sfn.Timeout.duration(timeout),
211
+ });
212
+ run.addRetry({
213
+ errors: ['States.TaskFailed'],
214
+ maxAttempts: 1,
215
+ interval: cdk.Duration.minutes(1),
216
+ backoffRate: 2,
217
+ });
218
+ run.next(next);
219
+ return run;
220
+ }
221
+ }
222
+ exports.MigrationStateMachine = MigrationStateMachine;
223
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLXN0YXRlLW1hY2hpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9jb25zdHJ1Y3RzL21pZ3JhdGlvbi1zdGF0ZS1tYWNoaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLG1DQUFtQztBQUNuQywyQ0FBMkM7QUFDM0MsMkNBQTJDO0FBRTNDLDZDQUE2QztBQUc3QyxxREFBcUQ7QUFDckQsNkRBQTZEO0FBQzdELDJDQUF1QztBQW1CdkMsc0VBQXNFO0FBQ3RFLDZFQUE2RTtBQUM3RSw0REFBNEQ7QUFDNUQsTUFBYSxxQkFBc0IsU0FBUSxzQkFBUztJQWdCbEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFpQztRQUN6RSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQztRQUMvQixJQUFJLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7UUFDL0IsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztRQUM3QixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUM7UUFDM0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztRQUN6QyxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUM7UUFDN0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQztRQUNuRCxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxjQUFjLElBQUksR0FBRyxDQUFDO1FBQ2xELElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxD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QXNCLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEcsa0JBQWtCLEVBQUU7Z0JBQ2xCO29CQUNFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxTQUFTO29CQUNuQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUM7b0JBQ2xCLFdBQVc7aUJBQ1o7YUFDRjtZQUNELE9BQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFO1lBQzNELGNBQWMsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7WUFDcEMsY0FBYyxFQUFFLEtBQUs7WUFDckIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztTQUMzQyxDQUFDLENBQUM7UUFDSCxHQUFHLENBQUMsUUFBUSxDQUFDO1lBQ1gsTUFBTSxFQUFFLENBQUMsbUJBQW1CLENBQUM7WUFDN0IsV0FBVyxFQUFFLENBQUM7WUFDZCxRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLFdBQVcsRUFBRSxDQUFDO1NBQ2YsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNmLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztDQUNGO0FBL1FELHNEQStRQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBlY3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcyc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNxcyc7XG5pbXBvcnQgKiBhcyBzZm4gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0ICogYXMgdGFza3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWlncmF0aW9uU3RhdGVNYWNoaW5lUHJvcHMge1xuICBwcm9kdWNlcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgdmVyaWZpZXI6IGxhbWJkYS5JRnVuY3Rpb247XG4gIHF1ZXVlOiBzcXMuSVF1ZXVlO1xuICBjbHVzdGVyOiBlY3MuSUNsdXN0ZXI7XG4gIHRhc2tEZWZpbml0aW9uOiBlY3MuVGFza0RlZmluaXRpb247XG4gIGNvbnRhaW5lcjogZWNzLkNvbnRhaW5lckRlZmluaXRpb247XG4gIHNlY3VyaXR5R3JvdXA6IGVjMi5JU2VjdXJpdHlHcm91cDtcbiAgYXJ0aWZhY3RzQnVja2V0OiBzMy5JQnVja2V0O1xuICBtYXhJbnZvY2F0aW9ucz86IG51bWJlcjtcbiAgZHJhaW5NYXhDaGVja3M/OiBudW1iZXI7XG4gIGxvb3BXYWl0U2Vjb25kcz86IG51bWJlcjtcbiAgZHJhaW5XYWl0U2Vjb25kcz86IG51bWJlcjtcbn1cblxudHlwZSBQcm9kdWNlclBheWxvYWQgPSBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuLy8gUnVucyB0aGUgcnVuYm9vayBlbmQtdG8tZW5kOiBzY3JpcHRzIGFzIG9uZS1zaG90IEZhcmdhdGUgdGFza3MsIFNRU1xuLy8gbWlncmF0YWJsZXMgYXMgcHJvZHVjZXIgbG9vcHMgKHVudGlsIGVuZFJlYWNoZWQpIGZvbGxvd2VkIGJ5IGEgcXVldWUgZHJhaW5cbi8vIGFuZCBhIHNraXBNaWdyYXRlZCByZXRyeSBwYXNzLCB0aGVuIHRoZSB2ZXJpZmllciBzdW1tYXJ5LlxuZXhwb3J0IGNsYXNzIE1pZ3JhdGlvblN0YXRlTWFjaGluZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBzdGF0ZU1hY2hpbmU6IHNmbi5TdGF0ZU1hY2hpbmU7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwcm9kdWNlcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSB2ZXJpZmllcjogbGFtYmRhLklGdW5jdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSBxdWV1ZTogc3FzLklRdWV1ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBjbHVzdGVyOiBlY3MuSUNsdXN0ZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGFza0RlZmluaXRpb246IGVjcy5UYXNrRGVmaW5pdGlvbjtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXI6IGVjcy5Db250YWluZXJEZWZpbml0aW9uO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXA6IGVjMi5JU2VjdXJpdHlHcm91cDtcbiAgcHJpdmF0ZSByZWFkb25seSBhcnRpZmFjdHNCdWNrZXQ6IHMzLklCdWNrZXQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWF4SW52b2NhdGlvbnM6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBkcmFpbk1heENoZWNrczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvb3BXYWl0U2Vjb25kczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGRyYWluV2FpdFNlY29uZHM6IG51bWJlcjtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTWlncmF0aW9uU3RhdGVNYWNoaW5lUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5wcm9kdWNlciA9IHByb3BzLnByb2R1Y2VyO1xuICAgIHRoaXMudmVyaWZpZXIgPSBwcm9wcy52ZXJpZmllcjtcbiAgICB0aGlzLnF1ZXVlID0gcHJvcHMucXVldWU7XG4gICAgdGhpcy5jbHVzdGVyID0gcHJvcHMuY2x1c3RlcjtcbiAgICB0aGlzLnRhc2tEZWZpbml0aW9uID0gcHJvcHMudGFza0RlZmluaXRpb247XG4gICAgdGhpcy5jb250YWluZXIgPSBwcm9wcy5jb250YWluZXI7XG4gICAgdGhpcy5zZWN1cml0eUdyb3VwID0gcHJvcHMuc2VjdXJpdHlHcm91cDtcbiAgICB0aGlzLmFydGlmYWN0c0J1Y2tldCA9IHByb3BzLmFydGlmYWN0c0J1Y2tldDtcbiAgICB0aGlzLm1heEludm9jYXRpb25zID0gcHJvcHMubWF4SW52b2NhdGlvbnMgPz8gMjAwMDtcbiAgICB0aGlzLmRyYWluTWF4Q2hlY2tzID0gcHJvcHMuZHJhaW5NYXhDaGVja3MgPz8gNjAwO1xuICAgIHRoaXMubG9vcFdhaXRTZWNvbmRzID0gcHJvcHMubG9vcFdhaXRTZWNvbmRzID8/IDEwO1xuICAgIHRoaXMuZHJhaW5XYWl0U2Vjb25kcyA9IHByb3BzLmRyYWluV2FpdFNlY29uZHMgPz8gMzAwO1xuXG4gICAgY29uc3QgZW50cmllczogUmVjb3JkPHN0cmluZywgc2ZuLklDaGFpbmFibGU+ID0ge307XG5cbiAgICBjb25zdCB2ZXJpZnkgPSBuZXcgdGFza3MuTGFtYmRhSW52b2tlKHRoaXMsICdWZXJpZnknLCB7XG4gICAgICBsYW1iZGFGdW5jdGlvbjogdGhpcy52ZXJpZmllcixcbiAgICAgIHBheWxvYWQ6IHNmbi5UYXNrSW5wdXQuZnJvbU9iamVjdCh7XG4gICAgICAgIHJ1bklkOiBzZm4uSnNvblBhdGguc3RyaW5nQXQoJyQkLkV4ZWN1dGlvbi5OYW1lJyksXG4gICAgICAgIGJ1Y2tldDogdGhpcy5hcnRpZmFjdHNCdWNrZXQuYnVja2V0TmFtZSxcbiAgICAgICAga2V5OiBzZm4uSnNvblBhdGguZm9ybWF0KCdydW5zL3t9L3N1bW1hcnkuanNvbicsIHNmbi5Kc29uUGF0aC5zdHJpbmdBdCgnJCQuRXhlY3V0aW9uLk5hbWUnKSksXG4gICAgICB9KSxcbiAgICAgIHBheWxvYWRSZXNwb25zZU9ubHk6IHRydWUsXG4gICAgICByZXN1bHRQYXRoOiAnJC52ZXJpZmljYXRpb24nLFxuICAgIH0pO1xuICAgIGNvbnN0IGNvbXBsZXRlID0gbmV3IHNmbi5TdWNjZWVkKHRoaXMsICdDb21wbGV0ZScpO1xuICAgIHZlcmlmeS5uZXh0KGNvbXBsZXRlKTtcblxuICAgIGxldCB0YWlsOiBzZm4uSUNoYWluYWJsZSA9IHZlcmlmeTtcblxuICAgIGVudHJpZXNbJ2NsYWltcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3MxNi1jbGFpbXMnLCB7IHJlc291cmNlOiAnY2xhaW1zJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snY2xhaW1zJ107XG5cbiAgICBjb25zdCBwaG90b3MgPSB0aGlzLnJlc291cmNlU3RlcCgnczE1LWJlbmVmaWNpYXJ5LXBob3RvcycsIHsgcmVzb3VyY2U6ICdiZW5lZmljaWFyeS1waG90b3MnIH0sIHRhaWwpO1xuICAgIGVudHJpZXNbJ2JlbmVmaWNpYXJ5LXBob3RvcyddID0gcGhvdG9zO1xuICAgIGNvbnN0IHBob3Rvc0Nob2ljZSA9IG5ldyBzZm4uQ2hvaWNlKHRoaXMsICdTa2lwUGhvdG9zJykud2hlbihzZm4uQ29uZGl0aW9uLmJvb2xlYW5FcXVhbHMoJyQuc2tpcFBob3RvcycsIHRydWUpLCB0YWlsKS5vdGhlcndpc2UocGhvdG9zKTtcbiAgICB0YWlsID0gcGhvdG9zQ2hvaWNlO1xuXG4gICAgZW50cmllc1snYmVuZWZpY2lhcmllcy1kZXBlbmRhbnRzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczE0Yi1iZW5lZmljaWFyaWVzLWRlcGVuZGFudHMnLCB7IHJlc291cmNlOiAnYmVuZWZpY2lhcmllcycsIHBoYXNlOiAnZGVwZW5kYW50cycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2JlbmVmaWNpYXJpZXMtZGVwZW5kYW50cyddO1xuXG4gICAgZW50cmllc1snYmVuZWZpY2lhcmllcy1wcmluY2lwYWxzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczE0YS1iZW5lZmljaWFyaWVzLXByaW5jaXBhbHMnLCB7IHJlc291cmNlOiAnYmVuZWZpY2lhcmllcycsIHBoYXNlOiAncHJpbmNpcGFscycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2JlbmVmaWNpYXJpZXMtcHJpbmNpcGFscyddO1xuXG4gICAgZW50cmllc1sncGxhbnMtcmV3aXJlJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczEzYi1wbGFucy1yZXdpcmUnLCB7IHJlc291cmNlOiAncGxhbnMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwbGFucy1yZXdpcmUnXTtcblxuICAgIGVudHJpZXNbJ2JlbmVmaXRzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczEyLWJlbmVmaXRzJywgeyByZXNvdXJjZTogJ2JlbmVmaXRzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snYmVuZWZpdHMnXTtcblxuICAgIGVudHJpZXNbJ3BvbGljaWVzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczExLXBvbGljaWVzJywgeyByZXNvdXJjZTogJ3BvbGljaWVzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncG9saWNpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3QtcHJpY2luZyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3MxMC1wcm9kdWN0LXByaWNpbmcnLCB7IHJlc291cmNlOiAncHJvZHVjdC1wcmljaW5nJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncHJvZHVjdC1wcmljaW5nJ107XG5cbiAgICBjb25zdCB0aWVyMCA9IG5ldyBzZm4uUGFyYWxsZWwodGhpcywgJ3M5LXRpZXIwJywgeyByZXN1bHRQYXRoOiAnJC50aWVyMCcgfSk7XG4gICAgZm9yIChjb25zdCByZXNvdXJjZSBvZiBbJ3VzZXJzJywgJ3Byb3ZpZGVycycsICdpbnN1cmVkJywgJ3RwYScsICdwbGFucyddKSB7XG4gICAgICB0aWVyMC5icmFuY2goc2ZuLkNoYWluLnN0YXJ0KHRoaXMucmVzb3VyY2VTdGVwKGBzOS0ke3Jlc291cmNlfWAsIHsgcmVzb3VyY2UgfSkpKTtcbiAgICB9XG4gICAgdGllcjAubmV4dCh0YWlsKTtcbiAgICBlbnRyaWVzWyd0aWVyMCddID0gdGllcjA7XG4gICAgdGFpbCA9IHRpZXIwO1xuXG4gICAgZW50cmllc1snY292ZXJhZ2UtZ3JvdXBzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczgtY292ZXJhZ2UtZ3JvdXBzJywgeyByZXNvdXJjZTogJ2NvdmVyYWdlLWdyb3VwcycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2NvdmVyYWdlLWdyb3VwcyddO1xuXG4gICAgZW50cmllc1snY2F0ZWdvcmllcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3M3LWNhdGVnb3JpZXMnLCB7IHJlc291cmNlOiAnY2F0ZWdvcmllcycgfSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ2NhdGVnb3JpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3RzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczYtcHJvZHVjdHMnLCB7IHJlc291cmNlOiAncHJvZHVjdHMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwcm9kdWN0cyddO1xuXG4gICAgZW50cmllc1sncHJvZHVjdC1jYXRlZ29yaWVzJ10gPSB0aGlzLnJlc291cmNlU3RlcCgnczViLXByb2R1Y3QtY2F0ZWdvcmllcycsIHsgcmVzb3VyY2U6ICdwcm9kdWN0LWNhdGVnb3JpZXMnIH0sIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydwcm9kdWN0LWNhdGVnb3JpZXMnXTtcblxuICAgIGVudHJpZXNbJ3Byb2R1Y3Qtc291cmNlcyddID0gdGhpcy5yZXNvdXJjZVN0ZXAoJ3M1YS1wcm9kdWN0LXNvdXJjZXMnLCB7IHJlc291cmNlOiAncHJvZHVjdC1zb3VyY2VzJyB9LCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1sncHJvZHVjdC1zb3VyY2VzJ107XG5cbiAgICBlbnRyaWVzWydjbGFpbS1iYXRjaGVzJ10gPSB0aGlzLmVjc1N0ZXAoJ3M0LWNsYWltLWJhdGNoZXMnLCAnY2xhaW0tYmF0Y2hlcycsIFtdLCBjZGsuRHVyYXRpb24uaG91cnMoMiksIHRhaWwpO1xuICAgIHRhaWwgPSBlbnRyaWVzWydjbGFpbS1iYXRjaGVzJ107XG5cbiAgICBlbnRyaWVzWydkaXNlYXNlcyddID0gdGhpcy5lY3NTdGVwKCdzMy1kaXNlYXNlLWxvb2t1cHMnLCAnZGlzZWFzZXMnLCBbXSwgY2RrLkR1cmF0aW9uLmhvdXJzKDEpLCB0YWlsKTtcbiAgICB0YWlsID0gZW50cmllc1snZGlzZWFzZXMnXTtcblxuICAgIGVudHJpZXNbJ21pZ3JhdGlvbnMnXSA9IHRoaXMuZWNzU3RlcCgnczItbWlncmF0aW9ucycsICdtaWdyYXRpb25zJywgW10sIGNkay5EdXJhdGlvbi5ob3VycygxKSwgdGFpbCk7XG4gICAgdGFpbCA9IGVudHJpZXNbJ21pZ3JhdGlvbnMnXTtcblxuICAgIGNvbnN0IHJlc3RvcmUgPSB0aGlzLmVjc1N0ZXAoXG4gICAgICAnczEtcmVzdG9yZScsXG4gICAgICAncmVzdG9yZScsXG4gICAgICBbeyBuYW1lOiAnQkFDS1VQX1MzX1VSSScsIHZhbHVlOiBzZm4uSnNvblBhdGguc3RyaW5nQXQoJyQuYmFja3VwUzNVcmknKSB9XSxcbiAgICAgIGNkay5EdXJhdGlvbi5ob3VycygzKSxcbiAgICAgIHRhaWxcbiAgICApO1xuICAgIGVudHJpZXNbJ3Jlc3RvcmUnXSA9IHJlc3RvcmU7XG4gICAgdGFpbCA9IHJlc3RvcmU7XG5cbiAgICBjb25zdCByZXNldCA9IHRoaXMuZWNzU3RlcCgnczAtZnJlc2gtcmVzZXQnLCAncmVzZXQnLCBbXSwgY2RrLkR1cmF0aW9uLm1pbnV0ZXMoMzApLCByZXN0b3JlKTtcbiAgICBlbnRyaWVzWydmcmVzaC1yZXNldCddID0gcmVzZXQ7XG4gICAgY29uc3QgZnJlc2hDaG9pY2UgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCAnRnJlc2hSZXNldCcpLndoZW4oc2ZuLkNvbmRpdGlvbi5ib29sZWFuRXF1YWxzKCckLmZyZXNoJywgdHJ1ZSksIHJlc2V0KS5vdGhlcndpc2UocmVzdG9yZSk7XG4gICAgdGFpbCA9IGZyZXNoQ2hvaWNlO1xuXG4gICAgY29uc3QgZnJvbVN0ZXAgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCAnRnJvbVN0ZXAnKTtcbiAgICBmb3IgKGNvbnN0IFtzdGVwSWQsIGVudHJ5XSBvZiBPYmplY3QuZW50cmllcyhlbnRyaWVzKSkge1xuICAgICAgZnJvbVN0ZXAud2hlbihzZm4uQ29uZGl0aW9uLmFuZChzZm4uQ29uZGl0aW9uLmlzUHJlc2VudCgnJC5mcm9tU3RlcCcpLCBzZm4uQ29uZGl0aW9uLnN0cmluZ0VxdWFscygnJC5mcm9tU3RlcCcsIHN0ZXBJZCkpLCBlbnRyeSk7XG4gICAgfVxuICAgIGZyb21TdGVwLm90aGVyd2lzZShmcmVzaENob2ljZSk7XG4gICAgdGFpbCA9IGZyb21TdGVwO1xuXG4gICAgY29uc3QgbG9nR3JvdXAgPSBuZXcgbG9ncy5Mb2dHcm91cCh0aGlzLCAnTG9ncycsIHtcbiAgICAgIGxvZ0dyb3VwTmFtZTogJy9hd3MvdmVuZGVkbG9ncy9zdGF0ZXMvbWlncmF0aW9uLW9yY2hlc3RyYXRvcicsXG4gICAgICByZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5USFJFRV9NT05USFMsXG4gICAgICByZW1vdmFsUG9saWN5OiBjZGsuUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zdGF0ZU1hY2hpbmUgPSBuZXcgc2ZuLlN0YXRlTWFjaGluZSh0aGlzLCAnU3RhdGVNYWNoaW5lJywge1xuICAgICAgc3RhdGVNYWNoaW5lTmFtZTogJ21pZ3JhdGlvbi1vcmNoZXN0cmF0b3InLFxuICAgICAgZGVmaW5pdGlvbkJvZHk6IHNmbi5EZWZpbml0aW9uQm9keS5mcm9tQ2hhaW5hYmxlKHRhaWwpLFxuICAgICAgdGltZW91dDogY2RrLkR1cmF0aW9uLmRheXMoNyksXG4gICAgICBsb2dzOiB7XG4gICAgICAgIGRlc3RpbmF0aW9uOiBsb2dHcm91cCxcbiAgICAgICAgbGV2ZWw6IHNmbi5Mb2dMZXZlbC5BTEwsXG4gICAgICAgIGluY2x1ZGVFeGVjdXRpb25EYXRhOiB0cnVlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMucHJvZHVjZXIuZ3JhbnRJbnZva2UodGhpcy5zdGF0ZU1hY2hpbmUpO1xuICAgIHRoaXMudmVyaWZpZXIuZ3JhbnRJbnZva2UodGhpcy5zdGF0ZU1hY2hpbmUpO1xuICAgIHRoaXMucXVldWUuZ3JhbnQodGhpcy5zdGF0ZU1hY2hpbmUsICdzcXM6R2V0UXVldWVBdHRyaWJ1dGVzJyk7XG4gICAgdGhpcy50YXNrRGVmaW5pdGlvbi5ncmFudFJ1bih0aGlzLnN0YXRlTWFjaGluZSk7XG4gIH1cblxuICAvLyBQcm9kdWNlciBsb29wICh1bnRpbCBlbmRSZWFjaGVkLCBndWFyZGVkIGJ5IG1heEludm9jYXRpb25zKSAtPiBxdWV1ZSBkcmFpblxuICAvLyAoVmlzaWJsZSArIE5vdFZpc2libGUgPSAwLCBndWFyZGVkIGJ5IGRyYWluTWF4Q2hlY2tzKSAtPiBuZXh0LlxuICBwcml2YXRlIHByb2R1Y2VyUGFzcyhpZDogc3RyaW5nLCBwYXlsb2FkOiBQcm9kdWNlclBheWxvYWQsIG5leHQ6IHNmbi5JQ2hhaW5hYmxlKTogc2ZuLklDaGFpbmFibGUge1xuICAgIGNvbnN0IGZhaWx1cmUgPSBuZXcgc2ZuLkZhaWwodGhpcywgYCR7aWR9LUZhaWxlZGAsIHtcbiAgICAgIGVycm9yOiAnTWlncmF0aW9uU3RlcEZhaWxlZCcsXG4gICAgICBjYXVzZTogYFN0ZXAgJHtpZH0gZXhjZWVkZWQgaXRzIGl0ZXJhdGlvbi9kcmFpbiBndWFyZCwgb3IgYW4gRUNTIHNjcmlwdCB0YXNrIGZhaWxlZC5gLFxuICAgIH0pO1xuXG4gICAgY29uc3QgaW5pdCA9IG5ldyBzZm4uUGFzcyh0aGlzLCBgJHtpZH0tTG9vcEluaXRgLCB7XG4gICAgICBwYXJhbWV0ZXJzOiB7IGNvdW50OiAwIH0sXG4gICAgICByZXN1bHRQYXRoOiAnJC5sb29wJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGludm9rZSA9IG5ldyB0YXNrcy5MYW1iZGFJbnZva2UodGhpcywgYCR7aWR9LUludm9rZWAsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiB0aGlzLnByb2R1Y2VyLFxuICAgICAgcGF5bG9hZDogc2ZuLlRhc2tJbnB1dC5mcm9tT2JqZWN0KHBheWxvYWQpLFxuICAgICAgcGF5bG9hZFJlc3BvbnNlT25seTogdHJ1ZSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLnByb2R1Y2VyJyxcbiAgICAgIHRhc2tUaW1lb3V0OiBzZm4uVGltZW91dC5kdXJhdGlvbihjZGsuRHVyYXRpb24ubWludXRlcygxNSkpLFxuICAgIH0pO1xuICAgIGludm9rZS5hZGRSZXRyeSh7XG4gICAgICBlcnJvcnM6IFsnU3RhdGVzLlRhc2tGYWlsZWQnLCAnTGFtYmRhLlNlcnZpY2VFeGNlcHRpb24nLCAnTGFtYmRhLkFXU0xhbWJkYUV4Y2VwdGlvbicsICdMYW1iZGEuU2RrQ2xpZW50RXhjZXB0aW9uJ10sXG4gICAgICBtYXhBdHRlbXB0czogMixcbiAgICAgIGludGVydmFsOiBjZGsuRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgICBiYWNrb2ZmUmF0ZTogMixcbiAgICB9KTtcblxuICAgIGNvbnN0IGVuZFJlYWNoZWQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tRW5kUmVhY2hlZGApO1xuXG4gICAgY29uc3QgbG9vcEluYyA9IG5ldyBzZm4uUGFzcyh0aGlzLCBgJHtpZH0tTG9vcEluY2AsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IHNmbi5Kc29uUGF0aC5tYXRoQWRkKHNmbi5Kc29uUGF0aC5udW1iZXJBdCgnJC5sb29wLmNvdW50JyksIDEpIH0sXG4gICAgICByZXN1bHRQYXRoOiAnJC5sb29wJyxcbiAgICB9KTtcbiAgICBjb25zdCBsb29wR3VhcmQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tTG9vcEd1YXJkYCkud2hlbihzZm4uQ29uZGl0aW9uLm51bWJlckdyZWF0ZXJUaGFuKCckLmxvb3AuY291bnQnLCB0aGlzLm1heEludm9jYXRpb25zKSwgZmFpbHVyZSk7XG4gICAgY29uc3QgbG9vcFdhaXQgPSBuZXcgc2ZuLldhaXQodGhpcywgYCR7aWR9LUxvb3BXYWl0YCwge1xuICAgICAgdGltZTogc2ZuLldhaXRUaW1lLmR1cmF0aW9uKGNkay5EdXJhdGlvbi5zZWNvbmRzKHRoaXMubG9vcFdhaXRTZWNvbmRzKSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBkcmFpbkluaXQgPSBuZXcgc2ZuLlBhc3ModGhpcywgYCR7aWR9LURyYWluSW5pdGAsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IDAgfSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLmRyYWluJyxcbiAgICB9KTtcbiAgICBjb25zdCBkcmFpbkdldCA9IG5ldyB0YXNrcy5DYWxsQXdzU2VydmljZSh0aGlzLCBgJHtpZH0tUXVldWVBdHRyaWJ1dGVzYCwge1xuICAgICAgc2VydmljZTogJ3NxcycsXG4gICAgICBhY3Rpb246ICdnZXRRdWV1ZUF0dHJpYnV0ZXMnLFxuICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICBRdWV1ZVVybDogdGhpcy5xdWV1ZS5xdWV1ZVVybCxcbiAgICAgICAgQXR0cmlidXRlTmFtZXM6IFsnQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzJywgJ0FwcHJveGltYXRlTnVtYmVyT2ZNZXNzYWdlc05vdFZpc2libGUnXSxcbiAgICAgIH0sXG4gICAgICBpYW1SZXNvdXJjZXM6IFt0aGlzLnF1ZXVlLnF1ZXVlQXJuXSxcbiAgICAgIHJlc3VsdFBhdGg6ICckLnF1ZXVlJyxcbiAgICB9KTtcbiAgICBjb25zdCBkcmFpbmVkID0gbmV3IHNmbi5DaG9pY2UodGhpcywgYCR7aWR9LURyYWluZWRgKS53aGVuKFxuICAgICAgc2ZuLkNvbmRpdGlvbi5hbmQoXG4gICAgICAgIHNmbi5Db25kaXRpb24uc3RyaW5nRXF1YWxzKCckLnF1ZXVlLkF0dHJpYnV0ZXMuQXBwcm94aW1hdGVOdW1iZXJPZk1lc3NhZ2VzJywgJzAnKSxcbiAgICAgICAgc2ZuLkNvbmRpdGlvbi5zdHJpbmdFcXVhbHMoJyQucXVldWUuQXR0cmlidXRlcy5BcHByb3hpbWF0ZU51bWJlck9mTWVzc2FnZXNOb3RWaXNpYmxlJywgJzAnKVxuICAgICAgKSxcbiAgICAgIG5leHRcbiAgICApO1xuICAgIGNvbnN0IGRyYWluSW5jID0gbmV3IHNmbi5QYXNzKHRoaXMsIGAke2lkfS1EcmFpbkluY2AsIHtcbiAgICAgIHBhcmFtZXRlcnM6IHsgY291bnQ6IHNmbi5Kc29uUGF0aC5tYXRoQWRkKHNmbi5Kc29uUGF0aC5udW1iZXJBdCgnJC5kcmFpbi5jb3VudCcpLCAxKSB9LFxuICAgICAgcmVzdWx0UGF0aDogJyQuZHJhaW4nLFxuICAgIH0pO1xuICAgIGNvbnN0IGRyYWluR3VhcmQgPSBuZXcgc2ZuLkNob2ljZSh0aGlzLCBgJHtpZH0tRHJhaW5HdWFyZGApLndoZW4oc2ZuLkNvbmRpdGlvbi5udW1iZXJHcmVhdGVyVGhhbignJC5kcmFpbi5jb3VudCcsIHRoaXMuZHJhaW5NYXhDaGVja3MpLCBmYWlsdXJlKTtcbiAgICBjb25zdCBkcmFpbldhaXQgPSBuZXcgc2ZuLldhaXQodGhpcywgYCR7aWR9LURyYWluV2FpdGAsIHtcbiAgICAgIHRpbWU6IHNmbi5XYWl0VGltZS5kdXJhdGlvbihjZGsuRHVyYXRpb24uc2Vjb25kcyh0aGlzLmRyYWluV2FpdFNlY29uZHMpKSxcbiAgICB9KTtcblxuICAgIGluaXQubmV4dChpbnZva2UpO1xuICAgIGludm9rZS5uZXh0KGVuZFJlYWNoZWQpO1xuICAgIGVuZFJlYWNoZWQud2hlbihzZm4uQ29uZGl0aW9uLmJvb2xlYW5FcXVhbHMoJyQucHJvZHVjZXIuZW5kUmVhY2hlZCcsIHRydWUpLCBkcmFpbkluaXQpLm90aGVyd2lzZShsb29wSW5jKTtcbiAgICBsb29wSW5jLm5leHQobG9vcEd1YXJkKTtcbiAgICBsb29wR3VhcmQub3RoZXJ3aXNlKGxvb3BXYWl0KTtcbiAgICBsb29wV2FpdC5uZXh0KGludm9rZSk7XG4gICAgZHJhaW5Jbml0Lm5leHQoZHJhaW5HZXQpO1xuICAgIGRyYWluR2V0Lm5leHQoZHJhaW5lZCk7XG4gICAgZHJhaW5lZC5vdGhlcndpc2UoZHJhaW5JbmMpO1xuICAgIGRyYWluSW5jLm5leHQoZHJhaW5HdWFyZCk7XG4gICAgZHJhaW5HdWFyZC5vdGhlcndpc2UoZHJhaW5XYWl0KTtcbiAgICBkcmFpbldhaXQubmV4dChkcmFpbkdldCk7XG5cbiAgICByZXR1cm4gaW5pdDtcbiAgfVxuXG4gIC8vIE1haW4gcGFzcywgdGhlbiBhIHNraXBNaWdyYXRlZCByZXRyeSBwYXNzIChmcm9tU3RhcnQpIHRoYXQgcmUtcHVibGlzaGVzXG4gIC8vIG9ubHkgcmVjb3JkcyB3aXRob3V0IGEgbWlncmF0ZWQgcm93LlxuICBwcml2YXRlIHJlc291cmNlU3RlcChpZDogc3RyaW5nLCBwYXlsb2FkOiBQcm9kdWNlclBheWxvYWQsIG5leHQ/OiBzZm4uSUNoYWluYWJsZSk6IHNmbi5JQ2hhaW5hYmxlIHtcbiAgICBjb25zdCB0ZXJtaW5hbCA9IG5leHQgPz8gbmV3IHNmbi5TdWNjZWVkKHRoaXMsIGAke2lkfS1Eb25lYCk7XG4gICAgY29uc3QgcmV0cnkgPSB0aGlzLnByb2R1Y2VyUGFzcyhgJHtpZH0tUmV0cnlgLCB7IC4uLnBheWxvYWQsIGZyb21TdGFydDogdHJ1ZSwgc2tpcE1pZ3JhdGVkOiB0cnVlIH0sIHRlcm1pbmFsKTtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWNlclBhc3MoaWQsIHBheWxvYWQsIHJldHJ5KTtcbiAgfVxuXG4gIHByaXZhdGUgZWNzU3RlcChpZDogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcsIGVudmlyb25tZW50OiB7IG5hbWU6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9W10sIHRpbWVvdXQ6IGNkay5EdXJhdGlvbiwgbmV4dDogc2ZuLklDaGFpbmFibGUpOiBzZm4uSUNoYWluYWJsZSB7XG4gICAgY29uc3QgcnVuID0gbmV3IHRhc2tzLkVjc1J1blRhc2sodGhpcywgaWQsIHtcbiAgICAgIGludGVncmF0aW9uUGF0dGVybjogc2ZuLkludGVncmF0aW9uUGF0dGVybi5SVU5fSk9CLFxuICAgICAgY2x1c3RlcjogdGhpcy5jbHVzdGVyLFxuICAgICAgdGFza0RlZmluaXRpb246IHRoaXMudGFza0RlZmluaXRpb24sXG4gICAgICBsYXVuY2hUYXJnZXQ6IG5ldyB0YXNrcy5FY3NGYXJnYXRlTGF1bmNoVGFyZ2V0KHsgcGxhdGZvcm1WZXJzaW9uOiBlY3MuRmFyZ2F0ZVBsYXRmb3JtVmVyc2lvbi5MQVRFU1QgfSksXG4gICAgICBjb250YWluZXJPdmVycmlkZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGNvbnRhaW5lckRlZmluaXRpb246IHRoaXMuY29udGFpbmVyLFxuICAgICAgICAgIGNvbW1hbmQ6IFtjb21tYW5kXSxcbiAgICAgICAgICBlbnZpcm9ubWVudCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBzdWJuZXRzOiB7IHN1Ym5ldFR5cGU6IGVjMi5TdWJuZXRUeXBlLlBSSVZBVEVfV0lUSF9FR1JFU1MgfSxcbiAgICAgIHNlY3VyaXR5R3JvdXBzOiBbdGhpcy5zZWN1cml0eUdyb3VwXSxcbiAgICAgIGFzc2lnblB1YmxpY0lwOiBmYWxzZSxcbiAgICAgIHRhc2tUaW1lb3V0OiBzZm4uVGltZW91dC5kdXJhdGlvbih0aW1lb3V0KSxcbiAgICB9KTtcbiAgICBydW4uYWRkUmV0cnkoe1xuICAgICAgZXJyb3JzOiBbJ1N0YXRlcy5UYXNrRmFpbGVkJ10sXG4gICAgICBtYXhBdHRlbXB0czogMSxcbiAgICAgIGludGVydmFsOiBjZGsuRHVyYXRpb24ubWludXRlcygxKSxcbiAgICAgIGJhY2tvZmZSYXRlOiAyLFxuICAgIH0pO1xuICAgIHJ1bi5uZXh0KG5leHQpO1xuICAgIHJldHVybiBydW47XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,5 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import { Construct } from 'constructs';
3
+ export declare class MicroserviceClickHouse extends cdk.Stack {
4
+ constructor(scope: Construct, id: string, props?: cdk.StackProps);
5
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MicroserviceClickHouse = void 0;
4
+ const cdk = require("aws-cdk-lib");
5
+ const constants_1 = require("../util/constants");
6
+ const initBuildConfig_1 = require("../util/initBuildConfig");
7
+ const getInstanceType_1 = require("../util/getInstanceType");
8
+ const getEc2UserData_1 = require("../util/getEc2UserData");
9
+ const getInstanceStorage_1 = require("../util/getInstanceStorage");
10
+ class MicroserviceClickHouse extends cdk.Stack {
11
+ constructor(scope, id, props) {
12
+ super(scope, id, props);
13
+ if (!initBuildConfig_1.buildConfig) {
14
+ throw new Error('BuildConfig not set');
15
+ }
16
+ const vpc = cdk.aws_ec2.Vpc.fromLookup(this, 'VPCLookup', {
17
+ vpcName: (0, constants_1.getEnvConstant)('vpcId'),
18
+ });
19
+ const secGroup = cdk.aws_ec2.SecurityGroup.fromLookupByName(this, 'SecGroupLookup', (0, constants_1.getEnvConstant)('clickhouseSecurityGroupId'), vpc);
20
+ const instance = new cdk.aws_ec2.Instance(this, `ec2-clickhouse-${initBuildConfig_1.buildConfig.envName}`, {
21
+ vpc,
22
+ securityGroup: secGroup,
23
+ instanceType: new cdk.aws_ec2.InstanceType((0, getInstanceType_1.getInstanceType)('clickhouse')),
24
+ machineImage: cdk.aws_ec2.MachineImage.genericLinux({
25
+ [initBuildConfig_1.buildConfig.aws.region]: (0, constants_1.getConstant)('defaultImageAmi'),
26
+ }),
27
+ vpcSubnets: { subnetType: cdk.aws_ec2.SubnetType.PRIVATE_WITH_EGRESS },
28
+ associatePublicIpAddress: false,
29
+ userData: cdk.aws_ec2.UserData.custom((0, getEc2UserData_1.getEc2UserData)('clickhouse')),
30
+ role: cdk.aws_iam.Role.fromRoleName(this, 'BaseRoleLookup', (0, constants_1.getConstant)('baseRoleName')),
31
+ blockDevices: (0, getInstanceStorage_1.getInstanceStorage)('clickhouse'),
32
+ });
33
+ new cdk.CfnOutput(this, 'internal-domain', {
34
+ value: instance.instancePrivateDnsName,
35
+ });
36
+ new cdk.CfnOutput(this, 'internal-ip', {
37
+ value: instance.instancePrivateIp,
38
+ });
39
+ }
40
+ }
41
+ exports.MicroserviceClickHouse = MicroserviceClickHouse;
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWljcm9zZXJ2aWNlLWNsaWNraG91c2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvbWljcm9zZXJ2aWNlLWNsaWNraG91c2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBQW1DO0FBRW5DLGlEQUFnRTtBQUNoRSw2REFBc0Q7QUFDdEQsNkRBQTBEO0FBQzFELDJEQUF3RDtBQUN4RCxtRUFBZ0U7QUFFaEUsTUFBYSxzQkFBdUIsU0FBUSxHQUFHLENBQUMsS0FBSztJQUNuRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXhCLElBQUksQ0FBQyw2QkFBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3pDLENBQUM7UUFFRCxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRTtZQUN4RCxPQUFPLEVBQUUsSUFBQSwwQkFBYyxFQUFDLE9BQU8sQ0FBQztTQUNqQyxDQUFDLENBQUM7UUFFSCxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBQSwwQkFBYyxFQUFDLDJCQUEyQixDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFdEksTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLDZCQUFXLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDdkYsR0FBRztZQUNILGFBQWEsRUFBRSxRQUFRO1lBQ3ZCLFlBQVksRUFBRSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLElBQUEsaUNBQWUsRUFBQyxZQUFZLENBQUMsQ0FBQztZQUN6RSxZQUFZLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO2dCQUNsRCxDQUFDLDZCQUFXLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUEsdUJBQVcsRUFBQyxpQkFBaUIsQ0FBVzthQUNuRSxDQUFDO1lBQ0YsVUFBVSxFQUFFLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFO1lBQ3RFLHdCQUF3QixFQUFFLEtBQUs7WUFDL0IsUUFBUSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFBLCtCQUFjLEVBQUMsWUFBWSxDQUFDLENBQUM7WUFDbkUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBQSx1QkFBVyxFQUFDLGNBQWMsQ0FBVyxDQUFDO1lBQ2xHLFlBQVksRUFBRSxJQUFBLHVDQUFrQixFQUFDLFlBQVksQ0FBQztTQUMvQyxDQUFDLENBQUM7UUFFSCxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ3pDLEtBQUssRUFBRSxRQUFRLENBQUMsc0JBQXNCO1NBQ3ZDLENBQUMsQ0FBQztRQUVILElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO1lBQ3JDLEtBQUssRUFBRSxRQUFRLENBQUMsaUJBQWlCO1NBQ2xDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXBDRCx3REFvQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBnZXRDb25zdGFudCwgZ2V0RW52Q29uc3RhbnQgfSBmcm9tICcuLi91dGlsL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBidWlsZENvbmZpZyB9IGZyb20gJy4uL3V0aWwvaW5pdEJ1aWxkQ29uZmlnJztcbmltcG9ydCB7IGdldEluc3RhbmNlVHlwZSB9IGZyb20gJy4uL3V0aWwvZ2V0SW5zdGFuY2VUeXBlJztcbmltcG9ydCB7IGdldEVjMlVzZXJEYXRhIH0gZnJvbSAnLi4vdXRpbC9nZXRFYzJVc2VyRGF0YSc7XG5pbXBvcnQgeyBnZXRJbnN0YW5jZVN0b3JhZ2UgfSBmcm9tICcuLi91dGlsL2dldEluc3RhbmNlU3RvcmFnZSc7XG5cbmV4cG9ydCBjbGFzcyBNaWNyb3NlcnZpY2VDbGlja0hvdXNlIGV4dGVuZHMgY2RrLlN0YWNrIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM/OiBjZGsuU3RhY2tQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwgcHJvcHMpO1xuXG4gICAgaWYgKCFidWlsZENvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCdWlsZENvbmZpZyBub3Qgc2V0Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgdnBjID0gY2RrLmF3c19lYzIuVnBjLmZyb21Mb29rdXAodGhpcywgJ1ZQQ0xvb2t1cCcsIHtcbiAgICAgIHZwY05hbWU6IGdldEVudkNvbnN0YW50KCd2cGNJZCcpLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc2VjR3JvdXAgPSBjZGsuYXdzX2VjMi5TZWN1cml0eUdyb3VwLmZyb21Mb29rdXBCeU5hbWUodGhpcywgJ1NlY0dyb3VwTG9va3VwJywgZ2V0RW52Q29uc3RhbnQoJ2NsaWNraG91c2VTZWN1cml0eUdyb3VwSWQnKSwgdnBjKTtcblxuICAgIGNvbnN0IGluc3RhbmNlID0gbmV3IGNkay5hd3NfZWMyLkluc3RhbmNlKHRoaXMsIGBlYzItY2xpY2tob3VzZS0ke2J1aWxkQ29uZmlnLmVudk5hbWV9YCwge1xuICAgICAgdnBjLFxuICAgICAgc2VjdXJpdHlHcm91cDogc2VjR3JvdXAsXG4gICAgICBpbnN0YW5jZVR5cGU6IG5ldyBjZGsuYXdzX2VjMi5JbnN0YW5jZVR5cGUoZ2V0SW5zdGFuY2VUeXBlKCdjbGlja2hvdXNlJykpLFxuICAgICAgbWFjaGluZUltYWdlOiBjZGsuYXdzX2VjMi5NYWNoaW5lSW1hZ2UuZ2VuZXJpY0xpbnV4KHtcbiAgICAgICAgW2J1aWxkQ29uZmlnLmF3cy5yZWdpb25dOiBnZXRDb25zdGFudCgnZGVmYXVsdEltYWdlQW1pJykgYXMgc3RyaW5nLFxuICAgICAgfSksXG4gICAgICB2cGNTdWJuZXRzOiB7IHN1Ym5ldFR5cGU6IGNkay5hd3NfZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTUyB9LFxuICAgICAgYXNzb2NpYXRlUHVibGljSXBBZGRyZXNzOiBmYWxzZSxcbiAgICAgIHVzZXJEYXRhOiBjZGsuYXdzX2VjMi5Vc2VyRGF0YS5jdXN0b20oZ2V0RWMyVXNlckRhdGEoJ2NsaWNraG91c2UnKSksXG4gICAgICByb2xlOiBjZGsuYXdzX2lhbS5Sb2xlLmZyb21Sb2xlTmFtZSh0aGlzLCAnQmFzZVJvbGVMb29rdXAnLCBnZXRDb25zdGFudCgnYmFzZVJvbGVOYW1lJykgYXMgc3RyaW5nKSxcbiAgICAgIGJsb2NrRGV2aWNlczogZ2V0SW5zdGFuY2VTdG9yYWdlKCdjbGlja2hvdXNlJyksXG4gICAgfSk7XG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCAnaW50ZXJuYWwtZG9tYWluJywge1xuICAgICAgdmFsdWU6IGluc3RhbmNlLmluc3RhbmNlUHJpdmF0ZURuc05hbWUsXG4gICAgfSk7XG5cbiAgICBuZXcgY2RrLkNmbk91dHB1dCh0aGlzLCAnaW50ZXJuYWwtaXAnLCB7XG4gICAgICB2YWx1ZTogaW5zdGFuY2UuaW5zdGFuY2VQcml2YXRlSXAsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==