The goal of the email service is to enable the decoupling of triggering email notifications from the work of transmitting email to a third party service and receiving callbacks from the services.
The service polls an Amazon SQS queue looking for messages. The SQS messages
are expected to have a JSON body containing an email_id key. The email_id
is used to look up the email information in a database.
The email_id from the queue message is used to look up a record in an Amazon
DynamoDB table. The keys and values in the DynamoDB row are mapped to a
structure representing the data a third party email sending service needs to
transmit the message.
No third party email sending service(s) are implemented yet.
AWS credentials are read from the environment by default. The email service
relies on rusoto to access AWS. Rusoto provides a credential
crate which is used to determine how AWS resources will be
accessed. The ChainProvider currently defines
how AWS credentials are read.
Other necessary configuration is provided by command line switches to the
email_broker program.
--regiondefines the AWS region where the SQS queue and DynamoDB table are located. Specify "localstack" to use a "localhost" endpoint, otherwise rusotoRegionis used to parse the region.--queue-urldefines the SQS queue polled for messages.--table-namedefines the name of the DynamoDB from which email messae data to send will be read.--dry-runwhen given the queue will only be polled a single time and no email information will be transmitted to the email sending service(s).
This has been developed on MacOS using Rust v1.41.0. See Rust install docs for more detailed setup information.
cargo build will download and install the dependencies specified in
Cargo.toml. In order to successfully test the application it
will need access to an SQS queue and if the queue contains any messages it will
attempt to access the DynamoDB table to retrieve records it is necessary to
have:
- An Amazon SQS queue URL
- A DynamoDB table name
- AWS credentials in the environment that can access both
An emulation of the DynamoDB and SQS resources can be created with Docker and
the localstack image.
docker-compose.yml is configured to start localstack
with these services but starting the image does not configure DynamoDB tables
or SQS queues.
# Create an SQS queue called emails_local
aws --endpoint-url=http://localhost:4566 \
sqs create-queue \
--queue-name=emails_local
# Create a DynamoDB table called emails_local
aws --endpoint-url=http://localhost:4566 \
dynamodb create-table \
--attribute-definitions=AttributeName=EmailId,AttributeType=S \
--table-name=emails_local \
--key-schema=AttributeName=EmailId,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5cargo testcargo run --bin email_broker -- \
--dry-run \
--region="<region>" \
--queue-url="https://sqs.<region>.amazonaws.com/<account_id>/<queue_name>" \
--table-name="<table_name>"cargo build --releasemake email_lambda.zip
# Create a lambda
aws lambda create-function --function-name <function_name> \
--handler doesnt.matter \
--zip-file fileb://./email_lambda.zip \
--runtime provided \
--role arn:aws:iam::<account_number>:role/<role_name> \
--environment Variables={RUST_BACKTRACE=1} \
--tracing-config Mode=Active
# Update the lambda
aws lambda update-function-code --function-name <function_name> \
--zip-file fileb://./email_lambda.zipmake target/lambda/runnable/fn/bootstrap
echo '{"Records":[]}' \
| docker run \
-i \
-e DOCKER_LAMBDA_USE_STDIN=1 \
-e DYNAMO_TABLE="emails_local" \
-e QUEUE_URL="http://localhost:4566/000000000000/emails_local" \
--rm \
-v "${PWD}/target/lambda/runnable/fn":/var/task \
lambci/lambda:providedList the stacks available for deployment
yarn workspace @email_service/cdk cdk listDeploy as specific stack from the list
yarn workspace @email_service/cdk cdk deploy <stack name>-
Put an item into dynamodb
-
Send a message
aws sqs send-message --queue-url="<QueueUrl>" --message-body='{"email_id":"test-1"}'
This experiment is released under the MIT License. Feel free to fork, and modify!
Copyright © 2020 Bryan J Swift