How to turn triggers into subscriptions.
In the first part of this blog series, we discussed lessons learned from migrating an IBM Cloud Foundry-based Python app to IBM Cloud Code Engine. The code is part of an IBM Cloud solution tutorial that utilized both Cloud Foundry and IBM Cloud Functions for GitHub traffic data analytics.
In this post, we are detailing how we migrated the Cloud Functions part. How did we address the daily data collection? What Code Engine features were utilized? What are the lessons learned?
For the previous version of our tutorial — "Combining serverless and Cloud Foundry for data retrieval and analytics" — we used a Cloud Functions action to collect traffic data from GitHub. That action was invoked daily by a Cloud Functions alarm trigger based on a defined rule. The action itself was pretty small and written in Python.
Code Engine has a similar concept to triggers and rules — subscriptions allow you to associate an app to an event producer. The ping event has a cron-like syntax and is similar to the alarm trigger in Cloud Functions. Thus, it is a direct replacement and used in our migrated tutorial.
App vs. job
As of this writing, a ping event sends a HTTP POST request to an app and a configured path. An app(lication) is one of two workload types supported by Code Engine. An app serves HTTP requests whereas a job, the second workload type, is executed once and then exits. A job is comparable to the classic batch job.
Although a job comes closer to the daily task of collecting the traffic data, we have to utilize an app. For the migration, we decided to integrate the data collection into the web app and expose it as API function (see below). One reason is that the code to initialize the database connection was already present in the web app and could simply be reused. Even better, we took the advantage and added a manually triggered data collection to the app. With that code change, we only have the Python web app — the additional asset of a cloud function is gone. Thus, only a single code object needs to be built and deployed. The alternative would have been to deploy the data collection as job and invoke it by a dedicated, triggered app.
The following command creates the subscription to ping events for the path /collectStats, executed daily at 6 am:
To secure the API call, a secret token needs to be passed. In addition, we could check the request header for conformance and the correct metadata.
Moving the daily data collection from an IBM Cloud Functions action to an API call in the Python web app deployed to IBM Cloud Code Engine was, more or less, straight-forward. Both Cloud Functions and Code Engine support a cron-like event producer that allows for the scheduling of the daily task.
There were different options on how to port the Cloud Functions action. We decided to integrate it into the web app to simplify code and offer more functionality. For everything in context, read the tutorial on serverless web app and eventing for data retrieval and analytics. The source code is available in the GitHub repository github-traffic-stats, the old code version in the branch "cloudfoundry".
We did not discuss how a regular Cloud Functions action could have been migrated to Code Engine. Both serverless compute options support containerized code and, therefore, the deployment vehicle.