Skip to content

Commit ed6d0d9

Browse files
committed
feat(export): new infrastructure for multi-service export
1 parent 3024e25 commit ed6d0d9

File tree

9 files changed

+191
-7
lines changed

9 files changed

+191
-7
lines changed

.docker/aws-resources/account-data-deleter.sh

+2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ set -x
33

44
SQS=(
55
pocket-account-data-delete-queue
6+
pocket-export-request-queue
67
pocket-list-export-queue
8+
pocket-annotations-export-queue
79
pocket-list-import-batch-queue
810
pocket-list-import-file-queue
911
)

.docker/aws-resources/shareable-lists-api.sh

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
SQS=(
2+
pocket-shareablelist-export-queue
3+
)
4+
5+
for sqs_queue in "${SQS[@]}"; do
6+
awslocal sqs create-queue --queue-name "${sqs_queue}"
7+
done
8+
19
#!/bin/bash
210
set -x
311
bash "$(dirname "${BASH_SOURCE[0]}")/eventbus.sh"

infrastructure/account-data-deleter/src/config/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ export const config = {
3737
databasePort: '3306',
3838
sqsBatchDeleteQueueName: `${prefix}-Sqs-Batch-Delete-Consumer-Queue`,
3939
listExportQueueName: `${prefix}-List-Export`,
40+
exportRequestQueueName: `${prefix}-Export-Request`,
41+
annotationsExportQueueName: `${prefix}-Annotations-Export`,
4042
listImportFileQueue: `${prefix}-List-Import-Files`,
4143
listImportBatchQueue: `${prefix}-List-Import-Batches`,
4244
databaseTz: 'US/Central',
4345
eventBusName: `PocketEventBridge-${environment}-Shared-Event-Bus`,
46+
shareListSecretName: `ShareableListsApi-Prod/shareablelistsapi-prod20230207160218618400000003`,
4447
},
4548
isDev,
4649
isProd,

infrastructure/account-data-deleter/src/dataDeleterApp.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
dataAwsRegion,
88
sqsQueue,
99
dataAwsSnsTopic,
10+
dynamodbTable,
1011
} from '@cdktf/provider-aws';
1112
import { S3Bucket } from '@cdktf/provider-aws/lib/s3-bucket';
1213

@@ -20,10 +21,13 @@ export type DataDeleterAppConfig = {
2021
secretsManagerKmsAlias: dataAwsKmsAlias.DataAwsKmsAlias;
2122
snsTopic: dataAwsSnsTopic.DataAwsSnsTopic;
2223
batchDeleteQueue: sqsQueue.SqsQueue;
24+
exportRequestQueue: sqsQueue.SqsQueue;
25+
annotationsExportQueue: sqsQueue.SqsQueue;
2326
listExportQueue: sqsQueue.SqsQueue;
2427
listExportBucket: S3Bucket;
2528
listExportPartsPrefix: string;
2629
listExportArchivesPrefix: string;
30+
exportStateDb: dynamodbTable.DynamodbTable;
2731
importFileQueue: sqsQueue.SqsQueue;
2832
importBatchQueue: sqsQueue.SqsQueue;
2933
listImportBucket: S3Bucket;
@@ -114,10 +118,18 @@ export class DataDeleterApp extends Construct {
114118
name: 'SQS_BATCH_DELETE_QUEUE_URL',
115119
value: `https://sqs.${region.name}.amazonaws.com/${caller.accountId}/${config.envVars.sqsBatchDeleteQueueName}`,
116120
},
121+
{
122+
name: 'EXPORT_REQUEST_QUEUE_URL',
123+
value: `https://sqs.${region.name}.amazonaws.com/${caller.accountId}/${config.envVars.exportRequestQueueName}`,
124+
},
117125
{
118126
name: 'SQS_LIST_EXPORT_QUEUE_URL',
119127
value: `https://sqs.${region.name}.amazonaws.com/${caller.accountId}/${config.envVars.listExportQueueName}`,
120128
},
129+
{
130+
name: 'SQS_ANNOTATIONS_EXPORT_QUEUE_URL',
131+
value: `https://sqs.${region.name}.amazonaws.com/${caller.accountId}/${config.envVars.annotationsExportQueueName}`,
132+
},
121133
{
122134
name: 'SQS_IMPORT_BATCH_QUEUE_URL',
123135
value: this.config.importBatchQueue.url,
@@ -276,8 +288,10 @@ export class DataDeleterApp extends Construct {
276288
],
277289
resources: [
278290
this.config.batchDeleteQueue.arn,
279-
this.config.listExportQueue.arn,
280291
this.config.importFileQueue.arn,
292+
this.config.listExportQueue.arn,
293+
this.config.exportRequestQueue.arn,
294+
this.config.annotationsExportQueue.arn,
281295
],
282296
effect: 'Allow',
283297
},

infrastructure/account-data-deleter/src/main.ts

+60-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import {
2323
ApplicationSQSQueue,
2424
ApplicationSqsSnsTopicSubscription,
2525
PocketVPC,
26+
ApplicationDynamoDBTable,
27+
ApplicationDynamoDBTableCapacityMode,
2628
} from '@pocket-tools/terraform-modules';
2729

2830
import { App, S3Backend, TerraformStack, Token } from 'cdktf';
@@ -67,6 +69,46 @@ class AccountDataDeleter extends TerraformStack {
6769
},
6870
);
6971

72+
const exportStateDb = new ApplicationDynamoDBTable(
73+
this,
74+
'export-request-state',
75+
{
76+
tags: config.tags,
77+
prefix: `${config.shortName}-${config.environment}-Export-Request-State`,
78+
capacityMode: ApplicationDynamoDBTableCapacityMode.ON_DEMAND,
79+
preventDestroyTable: true,
80+
tableConfig: {
81+
pointInTimeRecovery: {
82+
enabled: true,
83+
},
84+
ttl: {
85+
enabled: true,
86+
attributeName: 'expiresAt',
87+
},
88+
hashKey: 'requestId',
89+
attribute: [
90+
{
91+
name: 'requestId',
92+
type: 'S',
93+
},
94+
],
95+
},
96+
},
97+
);
98+
99+
const exportRequestQueue = new ApplicationSQSQueue(
100+
this,
101+
'export-request-consumer-queue',
102+
{
103+
name: config.envVars.exportRequestQueueName,
104+
tags: config.tags,
105+
visibilityTimeoutSeconds: 1800,
106+
messageRetentionSeconds: 1209600, //14 days
107+
//need to set maxReceiveCount to enable DLQ
108+
maxReceiveCount: 3,
109+
},
110+
);
111+
70112
const listExportQueue = new ApplicationSQSQueue(
71113
this,
72114
'list-export-consumer-queue',
@@ -80,13 +122,26 @@ class AccountDataDeleter extends TerraformStack {
80122
},
81123
);
82124

125+
const annotationsExportQueue = new ApplicationSQSQueue(
126+
this,
127+
'annotations-export-consumer-queue',
128+
{
129+
name: config.envVars.annotationsExportQueueName,
130+
tags: config.tags,
131+
visibilityTimeoutSeconds: 1800,
132+
messageRetentionSeconds: 1209600, //14 days
133+
//need to set maxReceiveCount to enable DLQ
134+
maxReceiveCount: 3,
135+
},
136+
);
137+
83138
new ApplicationSqsSnsTopicSubscription(
84139
this,
85140
'list-events-sns-subscription',
86141
{
87-
name: `${config.envVars.listExportQueueName}-SNS`,
142+
name: `${config.envVars.exportRequestQueueName}-SNS`,
88143
snsTopicArn: `arn:aws:sns:${pocketVpc.region}:${pocketVpc.accountId}:${config.lambda.snsTopicName.listEvents}`,
89-
sqsQueue: listExportQueue.sqsQueue,
144+
sqsQueue: exportRequestQueue.sqsQueue,
90145
filterPolicyScope: 'MessageBody',
91146
filterPolicy: JSON.stringify({
92147
'detail-type': ['list-export-requested'],
@@ -193,6 +248,9 @@ class AccountDataDeleter extends TerraformStack {
193248
snsTopic: this.getCodeDeploySnsTopic(),
194249
batchDeleteQueue: batchDeleteQueue.sqsQueue,
195250
listExportQueue: listExportQueue.sqsQueue,
251+
exportRequestQueue: exportRequestQueue.sqsQueue,
252+
annotationsExportQueue: annotationsExportQueue.sqsQueue,
253+
exportStateDb: exportStateDb.dynamodb,
196254
listExportBucket: exportBucket,
197255
listExportPartsPrefix: partsPrefix,
198256
listExportArchivesPrefix: archivesPrefix,

infrastructure/shareable-lists-api/src/config/index.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ const eventBusName = `PocketEventBridge-${environment}-Shared-Event-Bus`;
1515
const releaseSha = process.env.CIRCLE_SHA1;
1616

1717
const s3LogsBucket = isDev ? 'pocket-data-items-dev' : 'pocket-data-items';
18+
const prefix = `${name}-${environment}`;
1819

1920
export const config = {
2021
name,
2122
isDev,
2223
isProd,
23-
prefix: `${name}-${environment}`,
24+
prefix,
2425
circleCIPrefix: `/${name}/CircleCI/${environment}`,
2526
shortName: 'SLAPI',
2627
releaseSha,
@@ -39,6 +40,10 @@ export const config = {
3940
component_code: `pocket-${name.toLowerCase()}`,
4041
env_code: isDev ? 'dev' : 'prod',
4142
},
43+
export: {
44+
queue: `${prefix}-SharedList-Export`,
45+
requestTopic: `PocketEventBridge-${environment}-ListEvents`,
46+
},
4247
eventBusName,
4348
lambda: {
4449
snsTopicName: {

infrastructure/shareable-lists-api/src/main.ts

+57-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { provider as archiveProvider } from '@cdktf/provider-archive';
1414
import { provider as nullProvider } from '@cdktf/provider-null';
1515
import {
1616
ApplicationRDSCluster,
17+
ApplicationSQSQueue,
1718
ApplicationSqsSnsTopicSubscription,
1819
PocketALBApplication,
1920
PocketAwsSyntheticChecks,
@@ -75,12 +76,43 @@ class ShareableListsAPI extends TerraformStack {
7576
},
7677
);
7778

79+
// Export work queue
80+
const exportQueue = new ApplicationSQSQueue(
81+
this,
82+
'sharelists-export-consumer-queue',
83+
{
84+
name: config.export.queue,
85+
tags: config.tags,
86+
visibilityTimeoutSeconds: 1800,
87+
messageRetentionSeconds: 1209600, //14 days
88+
//need to set maxReceiveCount to enable DLQ
89+
maxReceiveCount: 3,
90+
},
91+
);
92+
93+
// Subscription to list export topic
94+
new ApplicationSqsSnsTopicSubscription(
95+
this,
96+
'list-events-sns-subscription',
97+
{
98+
name: `${config.export.queue}-SNS`,
99+
snsTopicArn: `arn:aws:sns:${pocketVpc.region}:${pocketVpc.accountId}:${config.export.requestTopic}`,
100+
sqsQueue: exportQueue.sqsQueue,
101+
filterPolicyScope: 'MessageBody',
102+
filterPolicy: JSON.stringify({
103+
'detail-type': ['list-export-requested'],
104+
}),
105+
tags: config.tags,
106+
},
107+
);
108+
78109
const alarmSnsTopic = this.getCodeDeploySnsTopic();
79110

80111
this.createPocketAlbApplication({
81112
rds: this.createRds(pocketVpc),
82113
secretsManagerKmsAlias: this.getSecretsManagerKmsAlias(),
83114
snsTopic: alarmSnsTopic,
115+
exportSqs: exportQueue.sqsQueue,
84116
region,
85117
caller,
86118
cache,
@@ -217,10 +249,18 @@ class ShareableListsAPI extends TerraformStack {
217249
caller: dataAwsCallerIdentity.DataAwsCallerIdentity;
218250
secretsManagerKmsAlias: dataAwsKmsAlias.DataAwsKmsAlias;
219251
snsTopic: dataAwsSnsTopic.DataAwsSnsTopic;
252+
exportSqs: sqsQueue.SqsQueue;
220253
cache: { primaryEndpoint: string; readerEndpoint: string };
221254
}): PocketALBApplication {
222-
const { rds, region, caller, secretsManagerKmsAlias, snsTopic, cache } =
223-
dependencies;
255+
const {
256+
rds,
257+
region,
258+
caller,
259+
secretsManagerKmsAlias,
260+
snsTopic,
261+
cache,
262+
exportSqs,
263+
} = dependencies;
224264

225265
return new PocketALBApplication(this, 'application', {
226266
internal: true,
@@ -280,6 +320,10 @@ class ShareableListsAPI extends TerraformStack {
280320
name: 'REDIS_IS_TLS',
281321
value: 'true',
282322
},
323+
{
324+
name: 'EXPORT_QUEUE_URL',
325+
value: `https://sqs.${region.name}.amazonaws.com/${caller.accountId}/${config.export.queue}`,
326+
},
283327
],
284328
logGroup: this.createCustomLogGroup('app'),
285329
logMultilinePattern: '^\\S.+',
@@ -370,6 +414,17 @@ class ShareableListsAPI extends TerraformStack {
370414
resources: ['*'],
371415
effect: 'Allow',
372416
},
417+
{
418+
// export queue
419+
actions: [
420+
'sqs:ReceiveMessage',
421+
'sqs:DeleteMessage',
422+
'sqs:SendMessage',
423+
'sqs:SendMessageBatch',
424+
],
425+
resources: [exportSqs.arn],
426+
effect: 'Allow',
427+
},
373428
{
374429
actions: ['events:PutEvents'],
375430
resources: [

servers/account-data-deleter/src/config/index.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,33 @@ export const config = {
4141
messageRetentionSeconds: 1209600, //14 days
4242
batchSize: 1, // TODO(?): Must be 1
4343
},
44-
exportQueue: {
44+
exportRequestQueue: {
45+
name: 'export-request',
46+
url:
47+
process.env.EXPORT_REQUEST_QUEUE_URL ||
48+
'http://localhost:4566/000000000000/pocket-export-request-queue',
49+
visibilityTimeout: 1000,
50+
maxMessages: 1, // Must be 1
51+
waitTimeSeconds: 0,
52+
defaultPollIntervalSeconds: 60,
53+
afterMessagePollIntervalSeconds: 0.5,
54+
messageRetentionSeconds: 1209600, //14 days
55+
batchSize: 1, // Must be 1
56+
},
57+
anotationsExportQueue: {
58+
name: 'annotations-export',
59+
url:
60+
process.env.SQS_ANNOTATIONS_EXPORT_QUEUE_URL ||
61+
'http://localhost:4566/000000000000/pocket-annotations-export-queue',
62+
visibilityTimeout: 1000,
63+
maxMessages: 1, // Must be 1
64+
waitTimeSeconds: 0,
65+
defaultPollIntervalSeconds: 60,
66+
afterMessagePollIntervalSeconds: 0.5,
67+
messageRetentionSeconds: 1209600, //14 days
68+
batchSize: 1, // Must be 1
69+
},
70+
listExportQueue: {
4571
name: 'list-export',
4672
url:
4773
process.env.SQS_LIST_EXPORT_QUEUE_URL ||

servers/shareable-lists-api/src/config/index.ts

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ export default {
1818
},
1919
},
2020
region: process.env.AWS_DEFAULT_REGION || 'us-east-1',
21+
exportQueue: {
22+
name: 'shareablelist-export',
23+
url:
24+
process.env.SQS_EXPORT_QUEUE_URL ||
25+
'http://localhost:4566/000000000000/pocket-shareablelist-export-queue',
26+
visibilityTimeout: 1000,
27+
maxMessages: 1, // Must be 1
28+
waitTimeSeconds: 0,
29+
defaultPollIntervalSeconds: 60,
30+
afterMessagePollIntervalSeconds: 0.5,
31+
messageRetentionSeconds: 1209600, //14 days
32+
batchSize: 1, // Must be 1
33+
},
2134
},
2235
redis: {
2336
primaryEndpoint: process.env.REDIS_PRIMARY_ENDPOINT || 'localhost',

0 commit comments

Comments
 (0)