Scheduled eventbridge input transformer in serverless framework - cron

I have been trying to pass data with event using scheduled eventbridge. But the documentation for serverless framework is not very clear.
Objective: I want to create an email notification system with custom data. So users can turn on notification for lets say 1 week/2 week etc. And They will receive emails with their custom data as long as they keep notifications turned on. If they turn it off, I want to stop sending.
Please let me know if there is a better approach than scheduled eventbridge to reach my objective. And an example of the scheduled eventdrive in serverless.yml with lambda would be much appreciated.

Related

Routing messages: Topic to serverless to multi-queue (maybe) to serverless to multi rest

Sorry if this is long and/or open ended... there is just so many options in azure I'm struggling to choose which pieces to use where, so Im hoping someone can help point the way.
I am trying to build something as described in the image below. I am kind of "routing" messages from a multi-tenant service bus topic (top of diagram) to tenant specific REST endpoints (bottom of diagram).
The hardest part that I am facing for far is to have kind of a concept of a function with dynamic queue/event triggers that change over time, but I'm looking for advice on any parts of the solution.
I have 4 constraints to deal with:
Those messages HAVE to eventually reach the corresponding rest endpoint
Those REST endpoint nodes get added and removed dynamically, but I do know (via event grid message) when that happens.
Those REST endpoint nodes can also be taken offline anytime, or for long periods of time (days), and all messages should eventually be delivered
I have a mostly working solution for F1, but looking for better ideas, but really its F2 that I am struggling with.
F1
Currently what I have is:
1 queue per tenant server, created/deleted based on event grid message
An Azure Function that can return a queue name based on service bus message contents
A logic app (WIP) that will take messages off the topic subscription, use the function to determine the destination queue name, add the webhook URI to the message properties, and forward the message to that queue.
I think that F1 will eventually work correctly :D... but f2..
F2
This is the tricky part, now I have N queues, that come and go over time. I can't figure out how to listen to all the queues via 1 function, so im thinking of trying to maybe rollout 1 function again per queue. It would be responsible for pulling messages off the queue and sending to the REST webhook URI.
But then when the rest endpoint is down it should pause, and not drain the queue, also not sure how to do this efficiently, maybe another logic app with polling?
I'm thinking of maybe using event grid instead of queues, because I think they have more serverless support in general, but I'm not sure this will solve the problem either.
Appreciate any thoughts

Adding schedule job to nodejs microservicse best practice

We are using microservicse approach in our backend
We have a nodejs service which provide a REST endpoint that grap some data from mongodb and apply some business logic to it.
We would need to add a schedule job every 15 min to sync the mongodb data with some 3rd party data source.
The question here is - dose adding to this microservicse a schedule job that would do that, consider anti pattern?
I was thinking from the other point of having a service that just do the sync job will create some over engineering for simple thing, another repo, build cycle deployment etc hardware, complicated maintenance etc
Would love to hear more thoughts around it
You can use an AWS CloudWatch event rule to schedule CloudWatch to generate an event every 15 minutes. Make a Lambda function a target of the CloudWatch event so it executes every 15 minutes to sync your data. Be aware of the VPC/NAT issues if calling your 3rd party resources from Lambda if they are external to your VPC/account.
Ideally, if it is like an ETL job, you can offload it to a Lambda function (if you are using AWS) or a serverless function to do the same.
Also, look into MongoDB Stitch that can do something similar.

Notify Lambda on CloudFront Distribution Creation End

At the moment, we are calling cloudfront.listDistributions() every minute to identify a change in the status of the distribution we are deploying. This cause Lambda to timeout because CloudFront never deploys faster than 30 minutes (where Lambda timeouts after 15 min).
I would like to notify a Lambda function after a CloudFront Distribution is successfully created. This would allow us to execute the post-creation actions while saving valuable Lambda exec time.
Creating a Rule on CloudWatch does not offer the option to chose CloudFront. Nevertheless, it seems to accept creating a Custom Event Pattern with the source aws.cloudformation.
Considering options:
Trigger a lambda every 5 minutes to list distributions and compare states with previous states stored in DynamoDB.
Anybody with an idea to overcome this lack of feature from AWS?
If you want and have time, there's a trickier and a bit more complex solution for doing that leveraging CloudTrail.
Disclaimer
CloudTrail is not a real-time log system, but ensure that all API calls will be reported on the console within 15 minutes (as stated here under the CloudTrail FAQs). Due to this, what's following makes sense only for long-running tasks like creating a CloudFront distribution, taking up an Aurora DB ans so on.
You can create a CloudWatch event based rule (let's call it CW-r1)
on specific pattern like CreateDistribution or
UpdateDistribution.
CW-r1 triggers a Lambda (LM-1) which enables another CloudWatch
event base rule (CW-r2).
CW-r2 on a scheduled base, triggers a Lambda (LM-2) which via API
request the state of specific distribution. Once distribution is
"Deployed", LM-2 can send a notification via SNS for example (you can
send EMAIL, SMS, Push Notification whatever is supported on SNS).
Once everything is finished, LM-2 can disable the CW-r2 rule in order
to stop processing information.
In this way you can have an automatic notification system based on which API call you desire.

Schedule a task to run at some point in the future (architecture)

So we have a Python flask app running making use of Celery and AWS SQS for our async task needs.
One tricky problem that we've been facing recently is creating a task to run in x days, or in 3 hours for example. We've had several needs for something like this.
For now we create events in the database with timestamps that store the time that they should be triggered. Then, we make use of celery beat to run a scheduled task every second to check if there are any events to process (based on the trigger timestamp) and then process them. However, this is querying the database every second for events which we feel could be bettered somehow.
We looked into using the eta parameter in celery (http://docs.celeryproject.org/en/latest/userguide/calling.html) that lets you schedule a task to run in x amount of time. However it seems to be bad practice to have large etas and also AWS SQS has a visibility timeout of about two hours and so anything more than this time would cause a conflict.
I'm scratching my head right now. On the one had this works, and pretty decent in that things have been separated out with SNS, SQS etc. to ensure scaling-tolerance. However, it just doesn't feel write to query the database every second for events to process. Surely there's an easier way or a service provided by Google/AWS to schedule some event (pub/sub) to occur at some time in the future (x hours, minutes etc.)
Any ideas?
Have you taken a look at AWS Step Functions, specifically Wait State? You might be able to put together a couple of lambda functions with the first one returning a timestamp or the number of seconds to wait to the Wait State and the last one adding the message to SQS after the Wait returns.
Amazon's scheduling solution is the use of CloudWatch to trigger events. Those events can be placing a message in an SQS/SNS endpoint, triggering an ECS task, running a Lambda, etc. A lot of folks use the trick of executing a Lambda that then does something else to trigger something in your system. For example, you could trigger a Lambda that pushes a job onto Redis for a Celery worker to pick up.
When creating a Cloudwatch rule, you can specify either a "Rate" (I.e., every 5 minutes), or an arbitrary time in CRON syntax.
So my suggestion for your use case would be to drop a cloudwatch rule that runs at the time your job needs to kick off (or a minute before, depending on how time sensitive you are). That rule would then interact with your application to kick off your job. You'll only pay for the resources when CloudWatch triggers.
Have you looked into Amazon Simple Notification Service? It sounds like it would serve your needs...
https://aws.amazon.com/sns/
From that page:
Amazon SNS is a fully managed pub/sub messaging service that makes it easy to decouple and scale microservices, distributed systems, and serverless applications. With SNS, you can use topics to decouple message publishers from subscribers, fan-out messages to multiple recipients at once, and eliminate polling in your applications. SNS supports a variety of subscription types, allowing you to push messages directly to Amazon Simple Queue Service (SQS) queues, AWS Lambda functions, and HTTP endpoints. AWS services, such as Amazon EC2, Amazon S3 and Amazon CloudWatch, can publish messages to your SNS topics to trigger event-driven computing and workflows. SNS works with SQS to provide a powerful messaging solution for building cloud applications that are fault tolerant and easy to scale.
You could start the job with apply_async, and then use a countdown, like:
xxx.apply_async(..., countdown=TTT)
It is not guaranteed that the job starts exactly at that time, depending on how busy the queue is, but that does not seem to be an issue in your use case.

AWS SES Schedule sending of email (Node SDK)

Simple as that, I am using AWS SDK in Node to make a Lambda procedure that is in charge of sending emails according to data it receives.
I would like to 'delay' that email, delivering in a date and time received, not in the specific moment that the function was called. The Date and Time to deliver are parameters received by the function. Any thoughts? I couldn't find much searching on the web.
Thanks in advance!
You should develop a queue for sending email because AWS SES does not offer that feature and if you want to send a lot of emails very soon, you have the problem with sending limit. So, the queue is vital in any email sender service.
For the queue, you can use AWS SQS, for handling hard and soft bounces you can use AWS SNS and AWS lambda function to manage all of them.
SES does not provide this natively. What I've done is to create a queue to process the emails plus schedule them within my limits.
Here's the psuedocode:
queue = []
limitPerSecond = <Your API limit>
putEmailsInQueue(queue)
while (true) {
processQueue(queue)
wait 1s
}
function processQueue(queue) {
numberOfEmailsToPop = limitPerSecond
emailsToSend = popEmailsFromQueue(queue, numberOfEmailsToPop)
sendEmails(emailsToSend)
}
You can also check out huhumails.com
Disclaimer: I'm the author of the service and I made it to make it easier for people to worry less about this issue.
HuhuMails acts as the middle-man between you and Amazon SES to take care of email scheduling and make sure your emails are sent within your rate limit. It also accepts date and timezone parameters if you want to send your email in the future.
I'm currently using this for my other websites as well. Hope you and other people find it useful. Let me know if you have any questions.

Resources