trigger function on firebase deploy functions - firebase

Does anyone know if there is an easy way to trigger a function everytime i re-deploy some funciont to firebase?
I have an specific firabase functions which i define inside GCP (this way when i do "firebase deploy" it doesnt re-deploy, unnisntal or touch in any form my current function)
but sometimes i might update this function manually on GCP and i would like to trigger a inner function of its code everytime it happens... is it possible?
ex:
exports.decrementAction = (req, res) => {/*do stuff*/res.status(200).send("ok")};
function auxiliary(){
//to be called on re-deploy
}

Unfortunately, there isn't an easy way for you to trigger a function within a code that is being redeployed. Since this code is only being deployed at the moment, this wouldn't be possible to be done automatically.
The alternative would be to have this function separately from the "root" function in the moment of deploying and use triggers to run this other Cloud Function, when the first is redeployed. This way, it would be possible to run it based in the deployment of the other.
You can get more information on the triggers available for Cloud Functions here: Calling Cloud Functions. With them, you should be able to configure the timing for the execution.
Besides that, it might be worth it to raise a Feature Request for Google's to verify the possibility of adding this in future releases.
Let me know if the information clarified!

I think there exists a manner.
With Pub/Sub you can catch logs from Stackdriver (docs). Those services allow you to store only the logs related to the deployment of a Cloud Function.
The store could be, for instance, Cloud Firestore. As you should know, there is available a trigger for Cloud Firestore events.
Finally, every time an event log related to a function's deployment is generated, it will be stored and triggers a function attached to that event. In the function, you can parse or filter the logs.

Related

How to continue running Firebase Cloud Function after request is finished

Really bizarre that Firebase doesn't seem to work quite like typical Express app. Whatever I write in Express and copy-paste to Firebase Functions I typically get error. There is one that I can't figure out on my own though.
This endpoint is designed to start a function and live long enough to finish even longer task. That request is a webhook (send docs, we will transform them and ping you when it's done to specified another webhook). Very simplified example below:
router.post('/', (req, res) => {
try {
generateZipWithDocuments(data) // on purpose it's not async so request can return freely
res.sendStatus(201)
} catch (error) {
res.send({ error })
}
})
On my local machine it works (both pure Express app and locally emulated Firebase Functions), but in the cloud it has problems and even though I put a cavalcade of console.log() I don't get much information. No error from Firebase.
If generateZipWithDocuments() is not asynchronous res.sendStatus() will be immediately executed after it, and the Cloud Function will be terminated (and the job done by generateZipWithDocuments() will not be completed). See the doc here for more details.
You have two possibilities:
You make it asynchronous and you wait its job is completed before sending the response. You would typically use async/await for that. Note that the maximum execution time for a Cloud Function is 9 minutes.
You delegate the long time execution job to another Cloud Function and, then, you send the response. For delegating the job to another Cloud Function, you should use Pub/Sub. See Pub/Sub triggers, the sample quickstart, and this SO thread for more details on how to implement that. In the Pub/Sub triggered Function, when the job is done you can inform the user via an email, a notification, the update of a Firestore document on which you have set a listener, etc... If generateZipWithDocuments() takes a long time, it is clearly the most user friendly option.

Firebase One-time Functions

I'm sure these are common scenarios, but after researching some hours, I couldn't really find what the common practice is. Maybe someone with more experience in Firebase can point me to the right direction.
I have two particular scenarios:
1. Code that runs once
Example 1: adding new data to all users in firestore, which is needed for a new feature
Example 2: start duplicating data into existing documents
I currently write the code in a cloud function, and run it on a firestore event (onUpdate of a "hidden" document) and then I immediately delete the function if everything goes well.
I also increase the timeout and memory for this function, as the idea is to potentially update millions of documents.
2. Manually trigger a function from the firebase console (or command line)
Example: Give a user admin privileges in the app (function that sets custom claims and firestore data). We don't have time to implement a back-office, so doing this from the firebase web portal/console would be ideal, specifying the user id.
My current solution is to use a https function, and run it from the GCP portal (on the function's "Testing" tab, being able to pass a json). BUT the function can be triggered publicly, which I don't really like...
What are the common practices for these scenarios?
To expand on my comment: if you want to create a node script to run one-off code, you just write your JS code like for any cloud function but simply run it immediately. Something like this.
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
db.collection('users')
.where('myField', '==', true)
.get()
.then(querySnapshot => {
querySnapshot.docs.forEach(doc => {
// update doc
});
});
If you save this as script.js and execute it with node script.js you’ll be pointed towards downloading a JSON file with credentials. Follow the instructions and you can then run the script again and now you’re running your own code on Firestore, from the command line.
For administrative type operations, you're better off just running them on your desktop or some other server you control. Cloud Functions is not well suited for long running operations, or things that must just happen once on demand.
Case 1 really should be managed by a standalone program or script that you can monitor by running it on your desktop.
Case 2 can be done a number of ways, such as building your own admin web site. But you might find it easiest to mirror the contents of a document to custom claims using a Firestore trigger. Read this: https://medium.com/firebase-developers/patterns-for-security-with-firebase-supercharged-custom-claims-with-firestore-and-cloud-functions-bb8f46b24e11

Manually trigger scheduled or trigger function

Is there any way to manually trigger a scheduled function and/or a Firestore trigger function? I have two scenarios I need to solve:
A cloud function that is listening to a Firestore document (onCreate) didn't fire - it failed on 3 of about 1,000 invocations, so I need to manually trigger it for these 3 documents. Is this possible (to manually trigger this function)?
I have a scheduled function that runs hourly, but threw an error b/c of a map in the Firestore document when the code expected an array. Any way I can manually run the scheduled function once rather than waiting an hour before it runs again?
-- firebase console
-- functions
-- "..." at right side of cron job
-- "view in cloud scheduler"
-- "run now" at right side of function
You can run a firestore scheduled function via the FirebaseTools and running it locally. Starting the shell command eg npm run build && firebase functions:shell will allow you to invoke a Scheduled Function eg:
export const parseGarminHealthAPIActivityQueue = functions.region('europe-west2').runWith({
timeoutSeconds: TIMEOUT_IN_SECONDS,
memory: MEMORY
}).pubsub.schedule('every 10 minutes').onRun(async (context) => {
await parseQueueItems(ServiceNames.GarminHealthAPI);
});
It's not possible to manually trigger a function from the Firebase console. Your best bet is to use the methods shown in the Cloud documentation, which involve using gcloud's call command or the Cloud console's Testing tab. Neither of these are very easy, as you will have to construct the JSON payload to the function manually.
If I may make a suggestion - if your functions are failing due to errors, you should consider enabling retry on your functions, and making sure that your functions only generate errors for situations that should be retried. Depending on manual invocation in the event of a failure will not scale very well - errors should be handled by code as much as possible.

Using cloud function to denormalize firestore data issue

I am using many cloud function trigger and admin sdk to do multi-path update.I don't want to do too much multi-path update in client cause it will make firestore rules very complex and firestore rules also have document access call limits.So I decide to using cloud function to do most denomorlization stuff.
There is how one of my function work.
cloud function triggered at profiles/{userId}
and i using .get to load multi-path update needed paths at
profilesPaths/{userId}
set writebatch.update on those paths
writebatch.commit()
And I think there have a problem.cloud function is asynchronous right?.So when function are running to step 3 And at the same moment a client delete one of update path from cf already loaded document at profilesPaths/{userId} (already loaded at step 2).and now cloud function loaded document is not the latest version.Will this happend? or i should using transactions to lock those documents?
Yes, Cloud Functions run asynchronous, and possibly in parallel. You should be using transactions to make sure that updates are consistent among all the clients that are trying to modify them concurrently.

Disable Cloud Functions for Firebase through Firebase dashboard (or cli)

Is there a way to disable a Cloud Function for Firebase through the Firebase dashboard?
I deployed a Cloud Function with a bug which caused an infinite loop of the function being triggered, updating the data, then the function triggering again. I discovered the error quickly, but I had to fix the code and redeploy the entire project to get the function to stop triggering.
Even though I deployed the new function, the deployment took some time and the function was triggered hundreds of times (which actually caused others to be triggered hundreds of times).
I'd like to be able to disable a function immediately when this happens, but I don't see any options in the dashboard or through the Firebase CLI.
If you view Cloud Functions in the Cloud Console, you can delete them individually from there: https://console.cloud.google.com/functions
Dont want to delete the function as I want to keep the usage history, logs, health ect?
This work around,long winded, but does the trick:
Disable function:
comment out the code in then function in your index.js
deploy just the firebase function:
firebase deploy --only functions:functionName
Enable function:
uncomment code
redeploy just the function with above line
Unfortunately Firebase has only a delete option and no disable option :(
A thing that I'm doing which isn't particularly neat but does the job. is just add a node in the database. for me I have a weekly script I run where I don't want my cloud functions to run when that's running. so at the top of my function I read that node and if the script is running, I just return early. not ideal but saves me having to comment out and redeploy every time
For me the fastest way is to edit function code directly in Google Cloud Console editor. In case of the HTTP function adding something like this at the beginning of a handler
res.status(500).send('The function is disabled');
return;
I use a solution similar to Red Baron. I have a Firestore Collection of booleans (one for each function) and I check that boolean at the beginning of my function to determine if it's allowed to run. The function will indeed be called, but it won't do anything if that boolean is set to false. It's not a perfect solution because it doesn't completely disable the function. But at least it will retain the log history.

Resources