Reputation: 1
A while back, I wrote a small Flask app (deployed as an AWS lambda via Serverless) to do some on-the-fly DynamoDB updates via Slack slash commands. A coworker suggested adding a component so that updates could be scheduled in advance.
I looked up using APscheduler and added a new component to the app. In the abbreviated example following, a Slack slash command would send a POST request to the app's "/scheduler" endpoint:
from flask import Flask, request
from apscheduler.schedulers.background import BackgroundScheduler
from pytz import timezone
[etc...]
app = Flask(__name__)
city = timezone([my timezone])
sched = BackgroundScheduler(timezone=city)
sched.start()
def success_webhook(markdown):
webhook_url = os.environ["webhook_url"]
data = json.dumps({"text": {"type": "mrkdwn", "text": markdown}})
headers = {"Content-Type": "application/json"}
r.post(webhook_url, data=data, headers=headers)
def pass_through(package):
db = boto3.resource(
"dynamodb",
region_name=os.environ["region_name"],
aws_access_key_id=os.environ["aws_access_key_id"],
aws_secret_access_key=os.environ["aws_secret_access_key"],
)
table = db.Table(table_name)
update_action = table.update_item(
Key={"id": "[key]"},
UpdateExpression="SET someValue = :val1",
ExpressionAttributeValues={":val1": package["text"]},
)
if update_action["ResponseMetadata"]["HTTPStatusCode"] == 200:
success_webhook("success")
@app.route("/scheduler", methods=["POST"])
def scheduler():
incoming = (request.values).to_dict()
sched.add_job(pass_through, "date", run_date=incoming["run_date"],
id=incoming["id_0"], args=[incoming])
return "success", 200
if __name__ == "__main__":
app.run()
I tested locally and everything worked fine -- I could schedule jobs and they would run on time; other app endpoints for checking scheduled jobs and removing scheduled jobs [not shown above] also worked as expected.
But once I spun up the AWS lambda running the Flask app, the scheduler never actually runs the pass_through()
function for the jobs. Sure, the job gets added -- I can also see it in the list of jobs and remove it from the schedule -- but when the time comes for the lambda to actually run pass_through()
, it doesn't. Wondering if anyone knows anything about this situation?
Upvotes: 0
Views: 760
Reputation: 126
Lambda execution will stop right after you return a value, so even when you schedule the job here:
sched.add_job(pass_through, "date", run_date=incoming["run_date"],
id=incoming["id_0"], args=[incoming])
return "success", 200
The lambda execution will stop and the job will not run later.
If you need to schedule jobs you probably need another solution that is not lambda, however you may use cloudwatch to trigger you lambdas on schedule: https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html
Upvotes: 1