How to abort Document Creation in Firestore onCreate trigger - firebase

I am trying to limit document creation of my each subscriber for a certain number of documents.
In my cloud function, I create an onCreate trigger and even I return "null" if document count doesn't match with my limits, firestore still creates this document.
I digged into firestore and cloud functions documentations but could not find any example how to cancel/abort a cloud function trigger.
Bonus question;
Do I have any way to alert customer wheter he/she exceeded the limit of this document creation? I thought I can update a seperate alert document in my trigger function and read and display this to customer. Do you know any way to listen onCreate trigger's result and display the error real time?
Any help please?
Many Thanks.

What you're trying to do isn't possible. Cloud Functions respond to events that occur within some product (such as Firestore). The event indicates that some change already happened. All you can do is choose what you want to do in response to that event. You can't prevent the change from taking place. The best you could do is undo the change by performing the opposite of what already happened. So, if a document was created, and that violates whatever rules you want to enforce, then you can simply delete the document.

Related

Firebase notification or alert for deletion of a collection

In Firestore, I have seen multiple ways to restrict the deletion of documents with security rules and to prevent the deletion of a collection by using Acess Controls.
But is there a way to get a notification or an alert when a collection is deleted in Firestore?
Deleting a collection is critical and it's surprising that there is no easy way to stay aware of it.
Collections are automatically created when a first document is added to them, and automatically removed when the last document is removed from them. There is no notification for either of these events though.
If you have a use-case that requires knowing when the collection is created/deleted, you'll have to detect adding the first document/removing the last document in your application code with a query.

Using Firestore Triggers to Manage User Document Count

If every document in a collection is a user resource that is limited, how can you ensure the user does not go over their assigned limit?
My first thought was to take advantage of the Firestore triggers to avoid building a real backend, but the triggers sometimes fire more than once even if the inputed data has not changed. I was comparing the new doc to the old doc and taking action if certain keys did not match but if GCP fires the same function twice I get double the result. In this case incrementing or decrementing counts.
The Firestore docs state:
Events are delivered at least once, but a single event may result in multiple function invocations. Avoid depending on exactly-once mechanics, and write idempotent functions.
So in my situation the only solution I can think of is saving the event id's somewhere and ensuring they did not fire already. Or even worse doing a read on each call to count the current docs and adjust them accordingly (increasing read costs).
Whats a smart way to approach this?
If reinvocations (which while possible are quite uncommon) are a concern for your use-case, you could indeed store the ID of the invocation event or something less frequent, like (depending on the use-case) the source document ID.

When writing to Firestore, how can I know that all triggered have finsihed?

Background: I am using Firestore as the main database for my (web) application. I also pre-render the data stored in there, which basically means that I collect all data needed for specific requests so I can later fetch them in a single read access, and I store that pre-rendered data in a separate Firestore collection.
When a user changes some data, I want to know when this background rendering is finished, so I can then show updated data. Until rendering is finished, I want to show a loading indicator ("spinner") so the user knows that what he is currently looking at is outdated data.
Until now, I planned to have the application write the changed data into the database and use a cloud funtion to propagate the changed data to the collection of pre-rendered data. This poses a problem because the writing application only knows when the original write access is finished, but not when the re-rendering is finished, so it doesn't know when to update its views. I can hook into the table of rendered views to get an update when the rendering finished, but that callback won't be notified if nothing visibly changes, so I still do not know when to remove the spinner.
My second idea was to have the renderer function publish to a pubsub topic, but this fails because if the user's requests happens to leave the original data unchanged, the onUpdate/renderer is not called, so nothing gets published on the pubsub and again the client does not know when to remove the spinner.
In both cases, I could theoretically first fetch the data and look if something changed, but I feel that this too easily introduces subtle bugs.
My final idea was to disallow direct writes to the database and have all write actions be performed through cloud functions instead, that is, more like a classical backend. These functions could then run the renderer and only send a response (or publish to a pubsub) when the renderer is finished. But this has two new problems: First, these functions have full write access to the whole database and I'm back to checking the user's permissions manually like in a classical backend, not being able to make use of Firestore's rules for permissions. Second, in this approach the renderer won't get before/after snapshots automatically like it would get for onUpdate, so I'm back to fetching each record before updating so the renderer knows what changed and won't re-render huge parts of the database that were not actually affected at all.
Ideally, what (I think) I need is either
(1) a way to know when a write access to the database has finished including the onUpdate trigger, or
(2) a way to have onUpdate called for a write access that didn't actually change the database (all updated fields were updated to the values they already contained).
Is there any way to do this in Firestore / cloud functions?
You could increment a counter in the rendered documents, in such a way a field always changes even if there is no change for the "meaningful" fields
For that, the best is to use FieldValue.increment.

How to initiate a single calculation from batched document onWrite triggers

I have a subcollection with documents. If any of them are added or removed, I need to trigger a calculation to derive an overall count (amongst other things) and store that in the parent document.
In order to listen for the document changes, I have a firestore onWrite background function. From this function, I would like to trigger the calculation via pubsub. However, it will happen that the system updates many subcollection documents at once. If I delete 100 documents, I do not want the calculation to be triggered 100 times. That would be a real waste of resources.
So I'm wondering, is there already some sort of mechanism in place that would batch these triggers or the pubsub topic publishing, or do I need to do something specific to make this happen?
If there are other ways to better solve this problem I'm open to suggestions of course. I could possibly even introduce a Redis store if that helps.

Do Firestore Function Triggers count as reads?

I know what you are probably thinking, "why does it matter? Don't try to over-complicate it just to optimize pricing". In my case, I need to.
I have a collection with millions of records in Firestore, and each document gets updated quite often. Every-time one gets updated, I need to do some data-cleaning (and more). So I have a function trigger by onUpdate that does that. In the function there's two parameters: document before update and document after update.
My question is:
Because the document is been passed as an argument, does that count as a database read?
The event generated by Cloud Firestore to send to Cloud Functions should not count as an extra read beyond what what was done by the client to initially trigger that event.

Resources