funkju
funkju

Reputation: 3763

How to prevent "conflicting" firebase cloud functions?

I have a set of objects that has a time-based derived property.

I have a Firebase cloud function that is listening for creates and writes to calculate the property and it is working well.

I have also added a function that is triggered via HTTP, like a cron, to recalculate the property early in the morning on Sunday (this property will change weekly).

This is working fine, but whenever the cron function updates a property, the first function catches the write and does the whole calculation over again.

Is there a simple way to prevent this? I've explored setting an environment variable for the first function to detect if the cron is running, but it doesn't seem that environment variables can be set at runtime.

Upvotes: 2

Views: 971

Answers (2)

ElFitz
ElFitz

Reputation: 988

Warning: My approach is a bit heavy handed, and it would probably require a refactoring of your code, so definitely not a solution for you. But I thought it might still interest either you or future readers.


I worked around this by using "commands" (what should be done) and "events" (what has happened). Each has it's own collection, to which my two functions (a CommandsHandler and an EventsHandler) are subscribed.

Each handler handles the commands and events, and may or may not generate their own events and commands depending on what they did, allowing me to completely bypass the kind of issues you described.

In your case, it would behave like the following:

Updates

Command Update item 'Item' with 'blablabla' -> Event Item 'Item' updated -> Command Calculate property 'Property' for item 'Item' -> Event Property 'Property' updated in item 'Item'

Cron

Cron function trigger -> Command Calculate property 'Property' for item 'Item' -> Event Property 'Property' updated in item 'Item'

Upvotes: 1

DoesData
DoesData

Reputation: 7047

You should be able to prevent this by checking the previous value. I'll try to provide an example

exports.yourFunction = functions.database.ref('/somepath/{someKey}').onWrite(event => {
  if (event.data.previous.val().time != event.data.val().time) {
    return;
  }
  else {
    // perform calculation
  }
 });

In summary if the previous value is not the same as the current value then the variable time was just changed by your other function. You'll need to change .time to your variable name.

Note: This does not prevent the function from firing, it only prevents it from preforming the calculation again. If you don't want the function to fire at all you'll have to devise a different way of calculating the value. Such as only calculating it onCreate then use the Cron at a set time interval to update the values. Listening to onWrite will cause the function to fire everytime data is written to Firebase.

You can read more about Firebase Database Triggers

Upvotes: 2

Related Questions