firebase functions:shell does not emulate state of memory between invocations - firebase

I am testing my Cloud Functions with firebase functions:shell and realized that it does not seem to emulate the state of memory between invocations.
let flag = false;
exports.test = functions.https.onCall(async (data, context) => {
console.log(flag); // this is still false on second call :-(
flag = true;
return true;
});
I know that functions should be stateless but as the doc says “Cloud Functions often recycles the execution environment of a previous invocation.” and this works in production.
Anyone know if there is a way to test this locally ?

There is currently no way to do this. The issue is being discussed on GitHub. You can follow the issue here.

Related

Is there any need to use await when setting data in firestore from cloudfunctions

I have a web app that is running quite slow and has a few cloud functions used to update/set values in firestore
When I update a value in the firestore database, should I await the completion of the request, or can I trust that the request was sent and the data will be updated?
In other words, with the below function, does the await statement do anything to help with computation, or does it just increase the CPU time I'm using?
exports.exampleFunction = functions.https.onRequest(async (request, response)=> {
await db.collection('users').doc(request.body.userID).update({
username: request.body.username
})
response.send({done: true})
return ;
})
Thanks :)
You can refer to the Stackoverflow Answer where Doug has explained the consequences of removing await from the function.
You can also refer to the Documentation where the importance of managing the lifecycle of a function is explained.
When you return a JavaScript promise to a function, that function keeps running until the promise is resolved or rejected. To indicate that a function has
completed its work successfully, the promise should be resolved. To indicate an error, the promise should be rejected. This means you only need to handle
errors that you want to.

How to trigger Pub/Sub Topic for Firebase Emulator

Using Firebase Functions, I have code that runs every hour via a Google Cloud Scheduler Job.
It looks like this:
exports.hourly_tick =
functions.pubsub.topic("hourly-tick").onPublish((message, context) => {
return getData()
.then((data) => {
sendEmail(data["message"]);
})
.catch((error) => {
return console.log("🚩 Caught error: ", error);
});
});
I need to be able to test this locally, and am able to start my Firebase Emulator via firebase emulators:start from my terminal. However I do not know how to trigger this function in my local test environment to see logs in the local emulator.
How can I test this scheduled job / firebase function with the local emulator?
This is an ongoing feature request in Firebase tools (see GitHub issue).
As mentioned in the thread:
I think we maybe misled with how we represented #2011. It lets those functions be loaded into the emulator but doesn't actually trigger them on a schedule. Instead you'd have to manually trigger them using a Pub/Sub message.
You can check a workaround on this answer where you'd have to manually trigger a scheduled function using a Pub/Sub message.

Activate retry in firebase cloud function programmatically

i'm deploying firebase cloud functions to listen on changes in our firestore via continuous deployment.
I can only find a way to activate retries manually. Which goes contrary to our cd approach.
Looking at the normal gcp cloud functions the retry flag can be given when deploying. But i cannot find a similar option in the firebase-cli or the firebase-functions interface (2.1.0)
Any hints on how to solve this?
Carsten
You can enable retries in Firebase Functions using GCloud Console, manually by hand. Programmatically retrying trigger-based functions was added in firebase-functions 3.10.0 (see changelog and associated pull request).
Since it's not entirely obvious from the PR or the docs, here's a quick example of the syntax:
export const myFirebaseFunc = functions
.runWith({
failurePolicy: {
retry: {},
},
memory: '512MB',
timeoutSeconds: 60,
})
.firestore.document('/path/to/some/doc')
.onCreate(async (snap, context) => {
/* do stuff */
})
At the time of writing this, it looks like the failure policy is simply on or off. Thus, this is equivalent
export const myFirebaseFunc = functions
.runWith({
failurePolicy: true,
memory: '512MB',
timeoutSeconds: 60,
})
.firestore.document('/path/to/some/doc')
.onCreate(async (snap, context) => {
/* do stuff */
})
Some caveats:
You'll also have to deploy with --force
You can enable retries only on triggered functions, not http-called functions.
It would be idiotic not to build in some safeguards. Retry policy maxes out at 7 days, and bills just like any other function invocation, so if you have some unhandled error, it could repeatedly run for a full week. You can use context.eventTimestamp to know when the first attempt roughly started.
Read this: https://firebase.google.com/docs/functions/retries and make sure your function in idempotent.
It was also difficult to discover what to return to force a retry or avoid a retry.
Triggered Firebase functions must return a Promise. (See this vid)
A retry-enabled Firebase function will retry if:
it returns a rejected promise
throws an exception
or the function times out
That means that if you run into an error that you know won't eventually resolve itself with a retry (i.e. you want to stop the function execution and not retry), you can return Promise.resolve({message: 'some message'});
There is currently no similar option for deployment using the Firebase CLI.
This is something being worked on by the Firebase team, so stay tuned for updates.

Stream removed error in Firebase Functions

I have a function that runs on the creation of a new user. The function typically fails on the first call after not being called for a while. I'm hoping someone could help me figure out what could be causing this.
export const onUserCreate = functions.auth.user().onCreate(event => {
const user: User = {
userId: event.data.uid,
email: event.data.email
};
return db.doc(`users/${user.userId}`).set(data);
});
As I use the same like below and it works well:
exports.onUserCreate = functions.auth.user().onCreate(event => {
const user = event.data
console.log(user);
})
This is hardly a permanent answer as this is something Google seems to be looking into.
In the meantime though I did some research on similar error messages across the Google libraries and it looks like it happens occasionally when you initialise a Google library outside of a function (ie. at the top of your file).
I've added this line within the function being executed instead of within the global scope and it looks to have stopped the error:
const datastore = require('#google-cloud/datastore')({});
For example instead of:
const datastore = require('#google-cloud/datastore')({});
module.exports.myFunction = function() {
datastore.get(key).then()....
}
you do
module.exports.myFunction = function() {
const datastore = require('#google-cloud/datastore')({});
datastore.get(key).then()....
}
That would go for Firebase libraries too – not just datastore. This isn't best-practice and should be changed back when the bug is fixed.
This seems to be an error with Firebase Functions right now and is being looked into.
EDIT:
Hello all, Sebastian from the Firestore SDK team here. We believe this
issue is related to the recent update of the GRPC Client SDK and have
been running tests with GRPC 1.7.1. So far, we have not been able to
reproduce this issue with this older GRPC version.
#google-cloud/firestore is now at 0.10.1. If you update your
dependencies, you will be able to pull in this release.
Thanks for your patience.
Sebastian
I had the same issue. Turns out this is a bug in the Firestore Node module. Update #google-cloud/firestore to version 0.10.1 and it should fix the issue.

Execute async tasks in a web garden

I have this function that executes an async task run and return results
public bool CheckNetworkDrive(string drive)
{
var task = new Task<bool>(() => { return CheckNetworkDriveMethod(drive); });
task.Start();
//make async call to check network path to avoid lock in case of not exist
if (task.Wait(5000) && task.Result)
return true;
return false;
}
in local host everything works fine but in webgarden its not seems to work and I can’t figure the exact reason, so can you help or suggest an alternative !
ps, the check method will check network path, if it’s not responding it will block the whole code, so that why I need fire and async wait method.
sorry for inconvenience, it turned out that the problem is not with the parallel task in particular,I'm using window identity impersonation to access network drives and somehow the task is seems to lose impersonation so after I passed the impersonated user to the task everything worked fine.
I found this that helped
How do I set the user identity for tasks when calling Task.WaitAll()

Resources