0

I am currently trying to delay some actions with the cloud firestore but the setTimeout/setInterval doesn't seem to work for my code.

export const onTimerCreate = functions.firestore

.document("File/One")
.onCreate((snapshot, context) => {
  setTimeout(countdown, 5000);
  const messageData = snapshot.data()

  const delay = countdown()
  return snapshot.ref.update ({ delay : delay })
})

function countdown() {
  return 0
}

I am trying to make sure the snapshot updates with a new value after that delay of 5 seconds but it just happens instantly every time... not sure what to do?

4
  • I know nothing about Google Cloud Functions, but maybe just return snapshot.ref.update ({ delay : 5000 })? Commented Jan 21, 2019 at 22:28
  • No that won't work, it will just update the value, I want the function to execute with a delay of 5 seconds Commented Jan 21, 2019 at 22:34
  • Maybe setTimeout(function () { snapshot.ref.update ({ delay : delay }) }, 5000) that's the standard way of delaying a function call... Commented Jan 21, 2019 at 22:35
  • I get error this error log: "Error: Update() requires either a single JavaScript object or an alternating list of field/value pairs that can be followed by an optional precondition. Argument "dataOrField" is not a valid Document. Couldn't serialize object of type "Timeout". Firestore doesn't support JavaScript objects with custom prototypes (i.e. objects that were created via the 'new' operator)." Commented Jan 21, 2019 at 22:44

1 Answer 1

4

First thing's first - you can't delay a write to Firestore with Cloud Functions. I can't tell for sure if that's what you're trying to do here, but if so, you should give up that idea right now. Cloud Functions only trigger after some action has already taken place. You can't intercept a write. You can prevent a write with security rules, but security rules won't effectively allow you to delay the write. The write will happen as fast as possible.

Assuming that you do actually want to just do something in delay after the write occurs, you can use setTimeout, but be aware that you are paying for the CPU time associated with those 5 seconds.

Since background functions are required to return a promise that resolves only after all the background is complete, you need to create and arrange for that Promise to resolve after the timeout finishes, and after any other async work completes. Since you're using TypeScript (or at least you've tagged it here), async/await is the easiest way to get this done:

export const onTimerCreate = functions.firestore
.document("File/One")
.onCreate(async (snapshot, context) => {
  await sleep(5000)

  const messageData = snapshot.data()
  await snapshot.ref.update ({ delay : delay })
})

async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, will try it out. About what you said about the CPU I'm paying for what did u mean? How much would they charge me and how can I find it out?
I'm not sure I agree with this assessment. With regard to triggers, absolutely that's true. However, you can write a Function to act as an API between the client and Firestore, and control the write operations in there. You can even go through a PubSub to help control the rate of writes.
@miles_b The OP is asking about a background type trigger, for which it's not possible to intercept a direct write to Firestore, or whatever it is that changed. If the question was about an http trigger, I would have said something very different.
@DougStevenson Is this also the recommended way (e.g. delaying for 2000ms) if I want to reduce "transactions" repeating because of interfering document changes? If the creation of file A triggers the creation of file B, C and D which each read/update file E (bad architecture I agree), would you rather have 50% of the transactions repeating until all work is done or set apart the creation of file B, C and D by e.g. 2000ms? I guess the latter also costs less (CPU time) than the transactions doing multiple reads again when repeating.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.