in cdk/lib/single-contribution-salesforce-writes.ts [17:106]
constructor(scope: App, id: string, props: GuStackProps) {
super(scope, id, props);
const deadLetterQueue = new Queue(this, `dead-letters-${APP_NAME}-queue`, {
queueName: `dead-letters-${APP_NAME}-queue-${props.stage}`,
retentionPeriod: Duration.days(14),
});
const queue = new Queue(this, `${APP_NAME}-queue`, {
queueName: `${APP_NAME}-queue-${props.stage}`,
deadLetterQueue: {
queue: deadLetterQueue,
maxReceiveCount: 3,
},
});
const acquisitionBusName = `acquisitions-bus-${props.stage}`;
const acquisitionBus = EventBus.fromEventBusArn(
this,
'AcquisitionBus',
`arn:aws:events:${this.region}:${this.account}:event-bus/${acquisitionBusName}`,
);
const rule = new Rule(
this,
'AcquisitionBusToSingleContributionSalesforceWritesQueueRule',
{
description:
'Send payment api events to the single-contribution-salesforce-writes-queue',
eventPattern: {
region: [this.region],
account: [this.account],
source: Match.prefix('payment-api'),
},
eventBus: acquisitionBus,
targets: [new SqsQueue(queue)],
},
);
const sendMessagePolicyStatement = new PolicyStatement({
sid: 'Allow acquisition bus to send messages to the single-contribution-salesforce-writes-queue',
principals: [new ServicePrincipal('events.amazonaws.com')],
effect: Effect.ALLOW,
resources: [queue.queueArn],
actions: ['sqs:SendMessage'],
conditions: {
ArnEquals: {
'aws:SourceArn': rule.ruleArn,
},
},
});
queue.addToResourcePolicy(sendMessagePolicyStatement);
const lambda = new GuLambdaFunction(this, `${APP_NAME}-lambda`, {
app: APP_NAME,
runtime: Runtime.JAVA_11,
fileName: `${APP_NAME}.jar`,
functionName: `${APP_NAME}-${props.stage}`,
handler:
'com.gu.singleContributionSalesforceWrites.handlers.CreateSalesforceSingleContributionRecordHandler::handleRequest',
events: [new SqsEventSource(queue)],
});
const getSecretValuePolicyStatement = new PolicyStatement({
effect: Effect.ALLOW,
resources: [
`arn:aws:secretsmanager:${this.region}:${this.account}:secret:${props.stage}/Salesforce/User/SingleContributionSalesforceWrites-*`,
`arn:aws:secretsmanager:${this.region}:${this.account}:secret:${props.stage}/Salesforce/ConnectedApp/SingleContributionSalesforceWrites-*`,
],
actions: ['secretsmanager:GetSecretValue'],
});
lambda.addToRolePolicy(getSecretValuePolicyStatement);
new GuAlarm(this, `${APP_NAME}-alarm`, {
app: APP_NAME,
snsTopicName: `alarms-handler-topic-${this.stage}`,
alarmName: `${this.stage}: Failed to sync single contribution to Salesforce`,
alarmDescription: `Impact: A Single Contribution record has not been added to Salesforce. Fix: check logs for lambda ${lambda.functionName} and redrive from dead letter queue or, if Salesforce is preventing record creation due to a data quality issue, fix and add record manually to Salesforce`,
metric: deadLetterQueue
.metric('ApproximateNumberOfMessagesVisible')
.with({ statistic: 'Sum', period: Duration.hours(1) }),
comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
threshold: 0,
evaluationPeriods: 24,
actionsEnabled: this.stage === 'PROD',
});
}