HomeLearnArticleRealm Triggers Treats and Tricks - Document-Based Trigger Scheduling

Realm Triggers Treats and Tricks - Document-Based Trigger Scheduling

Published: May 26, 2021

  • Atlas
  • Realm
  • JavaScript
  • ...

By Pavel Duchovny

Rate this article

In this blog series, we are trying to inspire you with some reactive Realm trigger use cases. We hope these will help you bring your application pipelines to the next level.

Essentially, triggers are components in our Atlas projects/Realm apps that allow a user to define a custom function to be invoked on a specific event.

  • Database triggers: We have triggers that can be scheduled based on database events—like deletes, inserts, updates, and replaces—called database triggers.
  • Scheduled triggers: We can schedule a trigger based on a cron expression via scheduled triggers.
  • Authentication triggers: These triggers are only relevant for Realm authentication. They are triggered by one of the Realm auth providers' authentication events and can be configured only via a Realm application.

For this blog post, I would like to focus on trigger scheduling patterns.

Let me present a use case and we will see how the discussed mechanics might help us in this scenario. Consider a meeting management application that schedules meetings and as part of its functionality needs to notify a user 10 minutes prior to the meeting.

How would we create a trigger that will be fired 10 minutes before a timestamp which is only known by the "meeting" document?

First, let's have a look at the meetings collection documents example:

1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 event : "Mooz Meeting",
4 eventDate : ISODate("2021-03-20:14:00:00Z"),
5 meetingUrl : "https://mooz.meeting.com/5ca4bbcea2dd94ee58162aa7",
6 invites : ["jon.doe@myemail.com", "doe.jonas@myemail.com"]
7 }

I wanted to share an interesting solution based on triggers, and throughout this article, we will use a meeting notification example to explain the discussed approach.

#Prerequisites

Of course, an initial step will be to verify we have an Atlas project with owner privileges to create triggers.

If you haven't yet set up your free cluster on MongoDB Atlas, now is a great time to do so. You have all the instructions in this blog post.

#The Idea Behind the Main Mechanism

I will use the event example as a source document initiating the flow with an insert to a meetings collection:

1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 event : "Mooz Meeting",
4 eventDate : ISODate("2021-03-20:11:00:00Z"),
5 meetingUrl : "https://mooz.meeting.com/5ca4bbcea2dd94ee58162aa7"
6 invites : ["jon.doe@example.com"],
7 phone : "+123456789"
8}

Once we insert this document into the meetings collection, it will create the following record in a helper collection called notifications using an insert trigger:

1{
2 _id : ObjectId("5ca4bbcea2dd94ee58162aa7"),
3 triggerDate : ISODate("2021-03-10:50:00:00Z")
4}

The time and _id are calculated from the source document and aim to fire once 2021-03-10:50:00:00Z arrives via a fireScheduleTasks trigger. This trigger is based on a delete operation out of a TTL index on the triggerDate field from the notifications.

This is when the user gets the reminder!

Trigger configuration on notifications collection

On a high level, here is the flow described above.

Main Flow
A meeting document is tracked by a trigger, creating a notification document. This document at the specified time will cause a delete event. The delete will fire a notification trigger to notify the user.

There are three main components that allow our system to trigger based on our document data.

#1. Define a Notifications Helper Collection

First we need to prepare our notifications collection. This collection will be created implicitly by the following index creation command.

Now we will create a TTL index. This index will cause the schedule document to expire when the value in triggerDate field arrives at its expiry lifetime of 0 seconds after its value.

1db.notifications.createIndex( { "triggerDate": 1 }, { expireAfterSeconds: 0 } )

#2. Building a Trigger to Populate the Schedule Collection

When setting up your scheduleTasks trigger, make sure you provide the following:

  1. Linked Atlas service and verify its name.
  2. The database and collection name we are basing the scheduling on, e.g., meetings.
  3. The relevant trigger operation that we want to schedule upon, e.g., when an event is inserted.
  4. Link it to a function that will perform the schedule collection population.
Trigger configuration on event collection
My trigger UI configuration to populate the scheduling collection.

To populate the notifications collection with relevant triggering dates, we need to monitor our documents in the source collection. In our case, the user's upcoming meeting data is stored in the "meeting" collection with the userId field. Our trigger will monitor inserts to populate a Scheduled document.

1exports = function(changeEvent) {
2 // Get the notifications collection
3 const coll = context.services.get("<ATLAS-SERVICE>").db("<DATABASE>").collection("notifications");
4
5 // Calculate the "triggerDate" and populate the trigger collection and duplicate the _id
6 const calcTriggerDate = new Date(changeEvent.fullDocument.eventDate - 10 * 60000);
7 return coll.insertOne({_id:changeEvent.fullDocument._id,triggerDate: calcTriggerDate });
8};

Important: Please replace <ATLAS-SERVICE> and <DATABASE> with your linked service and database names.

#3. Building the Trigger to Perform the Action on the "Trigger Date"

In order to react to the TTL "delete" event happening exactly when we want our scheduled task to be executed, we need to use an "on delete" database trigger I call fireScheduleTasks.

When setting up your fireScheduleTasks trigger, make sure you provide the following:

  1. Linked Atlas service and verify its name.
  2. The database and collection for the notifications collection, e.g., notifications.
  3. The relevant trigger operation that we want to schedule upon, which is "DELETE."
  4. Link it to a function that will perform the fired task.
Trigger configuration on notifications collection

Now that we have populated the notifications collection with the triggerDate, we know the TTL index will fire a "delete" event with the relevant deleted _id so we can act upon our task.

In my case, 10 minutes before the user's event starts, my document will reach its lifetime and I will send a text using Twilio service to the attendee's phone.

A prerequisite for this stage will be to set up a Twilio service using your Twilio cloud credentials.

  1. Make sure you have a Twilio cloud account with its SID and your Auth token.
  2. Set up the SID and Auth token into the Realm Twilio service configuration.
  3. Configure your Twilio Messaging service and phone number.

Once we have it in place, we can use it to send SMS notifications to our invites.

1exports = async function(changeEvent) {
2 // Get meetings collection
3 const coll = context.services.get("<ATLAS-SERVICE>").db("<DATABASE>").collection("meetings");
4
5 // Read specific meeting document
6 const doc = await coll.findOne({ _id: changeEvent.documentKey._id});
7
8 // Send notification via twilio SMS
9 const twilio = context.services.get("<TWILIO-SERVICE>");
10 twilio.send({
11 to: doc.phone,
12 from: "+123456789",
13 body: `Reminder : Event ${doc.event} is about to start in 10min at ${doc.scheduledOn}`
14 });
15};

Important: Please replace <ATLAS-SERVICE> and <DATABASE> with your linked service and database names.

#Wrap-Up

With the presented technique, we can leverage existing triggering patterns to build new ones. This may open your mind to other ideas to design your next flows on MongoDB Realm.

Please look out for my next article in this series where we will use triggers to auto-translate our documents and benefit Atlas Search multilingual abilities.

If you have questions, please head to our developer community website where the MongoDB engineers and the MongoDB community will help you build your next big idea with MongoDB.

Rate this article

More from this series

Triggers Tricks and Treats
  • Realm Triggers Treats and Tricks - Document-Based Trigger Scheduling
  • Realm Triggers Treats and Tricks - Auto Increment a Running ID Field
  • Triggers Treats and Tricks: Cascade Document Delete Using Triggers Preimage
MongoDB Icon
  • Developer Hub
  • Documentation
  • University
  • Community Forums

© MongoDB, Inc.