React to Database Changes with OpenWhisk Actions
The Database to Connect to
If you already have a database you want to use, skip to the next section. If not, here’s where we set up a Cloudant (hosted Apache CouchDB) database on IBM Cloud.
There is a web interface but I mostly use the command line as I find it faster (also since I’m a disabled user, web interfaces can be painful although IBM Cloud isn’t awful). These examples are all command-line based but if you’re more of a graphical user, feel free to check out the web version also!
First, create a new database to use for the example. mine is called events
and is created with the following command:
bx service create cloudantNoSQLDB Lite events
The command should show that the database was created and it will appear if you run bx service list
.
Before we can connect to the database, we’ll need some credentials to do that with. Here is how to create a new set of access credentials, in this case called mykey
:
bx service key-create events mykey
With this in place, we can create the action that will be invoked when a new database entry is added.
Set up the Actions
In OpenWhisk (and therefore IBM Cloud Functions), there is a concept of “packages” that keep things together. In this example the credentials will belong to the package, and actions will be added to it to make use of those parameters.
Firstly, the package should be created (or updated if it exists)
bx wsk package update dbevent
Next, let’s create an action to handle the newly-inserted document. Mine is for an entry in the users database (which must exist) and the code is fairly simple:
function main(data) {
if(data._id) {
console.log("New record created for user: " + data.user_name);
} else {
console.log("No document received");
}
}
This code is in a file called db-listener.js
. To add it to the dbevent
action, the command is:
bx wsk action update dbevent/db-listener db-listener.js
At this point, we’re only halfway there! This action expects the document with its data fields to be available, but by default the Cloudant changes feed only gives document ID. However, help is at hand: the built-in Cloudant package has a “read” action that we can add into a sequence so that the process looks something like this:
- new document inserted to Cloudant
- changes feed trigger fires in OpenWhisk
- rule makes trigger invoke a sequence
- first action in sequence fetches the actual document rather than just the ID
- the
db-listener
action created above then fires
To use the built-in Cloudant features, OpenWhisk needs to know about the Cloudant database to use. It will pick up the database and credentials when this command is run:
bx wsk package refresh
Follow this command with bx wsk package list
and the package ending Bluemix_events_mykey
should appear in the list. Copy the fully-qualified name containing the account and space currently being used – we’ll need that in a moment.
At this point, we’re ready to use Cloudant so let’s create the sequence to fetch the document with the Cloudant read
action and then pass it to the dbevent/db-listener
action created above:
bx wsk action update dbevent/db-doc --sequence /Lorna.Mitchell_dev/Bluemix_events_mykey/read,dbevent/db-listener
Now we’re ready! By linking the changes trigger to this sequence with a rule, we’ll observe the code running in response to database changes.
Set up triggers and rules
First, configure a trigger from the database changes feed (you’ll need that copied fully-qualified database package name again from before):
bx wsk trigger create db-change --feed /Lorna.Mitchell_dev/Bluemix_events_mykey/changes --param dbname users
The trigger doesn’t fire until it has at least one rule associated with it – so here’s the command to link the above trigger to our sequence:
bx wsk rule update db-users db-change dbevent/db-doc
bx wsk rule enable db-users
Everything is ready, let’s watch it in action!
Cloudant Database Changes in Action
A simple way to see everything as-it-happens on OpenWhisk is to use the command:
bx wsk activation poll
This command is blocking, and will output information about what is happening. Run this in a separate terminal window.
Time to make a change to that users
database!
Using your Cloudant client of choice (I’ll admit that I did use curl to quickly add a record here!), add a record to the users
database. Remember that the action expects a user_name
field … and watch the activations happen!
I can see that the db-change
trigger fired, the db-doc
sequence has two activation IDs inside it (one for each action), the built-in read
action ran and shows the data it passed on to the db-listener
…. which itself output “New record created for user: Alice” as expected.
The output of the activation command can be confusing because the output of each individual piece isn’t in the order it actually happened in! Do scroll up as-needed to inspect what happened.
Reacting to Database Changes
Although the db-listener
action in this example only outputs a log line, the possibilities here are endless. In my own applications I use code like this to add messages to a queue or to send notifications to the slackbot in response to changes. Hopefully this example with the sequence show helps you to come up with and implement ideas of your own. Let me know what you build!