How do I deploy my firebase functions into a specific region? - javascript

const functions = require('firebase-functions')
const admin = require('firebase-admin')
admin.initializeApp()
exports.sendChatMsgNotification = functions.region('europe-west1')
firestore
.document('chats/{idChat}/messages/{idMessage}')
.onCreate((snap, context) => {
console.log('----------------start function--------------------')
I am trying to deploy my Firebase cloud function into europe-west1 region because the default is us-central1, but I am always getting errors.
Yes, I have already tried to follow the official documentation https://firebase.google.com/docs/functions/locations#android. I just have no idea how to apply it correctly. I have tried many times.
If someone can just show me how to apply the correct way using my code above, would be highly appreciated!

Before
exports.sendChatMsgNotification = functions.region('europe-west1')
firestore
After (working)
exports.sendChatMsgNotification = functions.region('europe-west1').
firestore
I was only missing a dot (.) before "firestore". Thanks #Jason Berryman for pointing it out!

Related

How can I invoke a firebase storage function locally and manually?

I am fairly familiar with invoking firebase firestore functions manually for testing. I have done this in the past with the docs here. In short I make a wrappedOnWrite variable, assign it to my admin sdk.wrap(my firebase function), and then I invoke it with an object that represents the firestore collection before and after the call. Example:
const testEnv = functions({ projectId: **** }, '****');
let wrappedOnWrite:
| WrappedScheduledFunction
| WrappedFunction<Change<QueryDocumentSnapshot>>;
beforeAll(() => {
// wrap the firebase function, ready to be invoked
wrappedOnWrite = testEnv.wrap(moderateCompetition);
});
const changeDoc: Change<QueryDocumentSnapshot> = {
before: testEnv.firestore.makeDocumentSnapshot(dataBefore, path),
after: testEnv.firestore.makeDocumentSnapshot(dataAfter, path),
};
// call firebase function with the changes inputted to the function
await wrappedOnWrite(changeDoc);
This is great for testing my firestore collections with jest, however, I am never seen this done with firebase storage, and I haven't been able to find many useful resources either. I have a pretty basic firestore .onFinalize function for storage:
export const blurImages = functions.storage.object().onFinalize(async (object) => {}
Is there any way to manually test it like in the example I gave above? When I initially deployed the function, it ran recursively and charged my company a couple of dollars, and I need to be able to run it periodically so that recession doesn't happen on the live function. Thanks in advance :)

How to update a document when a document is added to a specified collection in cloud firestore?

I have 2 collections in my firestore (global and local) and when I add a doc to local I need to update a field in the global doc by 1
Below is the code I have for the same. I am very new to this so I might have some syntactical error as well, please do highlight if you find any.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello world");
}); // For testing, even this is not being deployed
exports.updateGlobal = functions.firestore
.document("/local/{id}")
.onCreate((snapshot, context) => {
console.log(snapshot.data());
return admin
.firebase()
.doc("global/{id}")
.update({
total: admin.firestore.FieldValue.increment(1),
});
});
The Terminal says "function failed on loading user code"
Before this, it showed something along the lines of "admin is undefined" or "cannot access firestore of undefined" which I'm unable to replicate now.
This is a part of a react app which has normal firestore working through firebase npm module
Any other info needed regarding the issue I'll edit the question accordingly, thank you so much for the help.
In addition to loading the firebase-functions and firebase-admin modules, you need to initialize an admin app instance from which Cloud Firestore changes can be made, as follows:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
//...
I see another problem in your CF. You need to use the context object to get the value of id.
exports.updateGlobal = functions.firestore
.document("/local/{id}")
.onCreate((snapshot, context) => {
const docId = context.params.id;
return admin
.firebase()
.doc("global/" + docId)
.update({
total: admin.firestore.FieldValue.increment(1),
});
});
You can also use template literals as follows:
return admin
.firebase()
.doc(`global/${docId}`)
//...

Where should i declare a new firebase database instance?

When using const db = firebase.database(), does it matter where I declare this in a cloud function script?
For example, index.ts which contains all of my cloud functions, should I declare it at the top, or in each individual function?
const db = firebase.database()
export const functionA = functions.https.onCall(async (data, context) => {
// use db here
});
export const functionB = functions.https.onCall(async (data, context) => {
// use db here
});
OR
export const functionA = functions.https.onCall(async (data, context) => {
const db = firebase.database()
});
export const functionB = functions.https.onCall(async (data, context) => {
const db = firebase.database()
});
Or does this not matter?
The first approach creates the db instance when the code loads.
The second approach creates the db instance when the code runs.
Neither is pertinently better than the other, and the firebase.database() operation is very lightweight so it's likely to make little difference in practice.
What does make a difference is whether you load the database SDK to begin with. Some of the SDKs in Firebase are quite big, and not each Cloud Function needs all SDKs. So a common trick to speed up load/cold-start times is to move the require('firebase-...') statements into the body of the Cloud Function(s) that require them.
Normally, if you want to interact, from a Cloud Function, with the Realtime Database you just need to initialize the Admin SDK and get the Database service for the default app (or a given app), as explained here in the doc.
So you would do something like:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// Get the Database service for the default app
const db = admin.database();
To get more details on what Frank explains about Cold Start in his answer, you should read the following article: https://medium.com/firebase-developers/organize-cloud-functions-for-max-cold-start-performance-and-readability-with-typescript-and-9261ee8450f0
However in your case, since your two Cloud Functions use the Admin SDK, there shouldn't be any difference between the two approaches presented in your question, as Frank mentioned.

Failure to Deploy Cloud Function When Using Wildcard in Trigger

I'm trying to deploy a cloud function that will trigger whenever a document is added to a particular collection as below:
const admin = require("firebase-admin");
const functions = require("firebase-functions");
const Firestore = require("#google-cloud/firestore");
const firestore = new Firestore({ projectId: config.projectId });
admin.initializeApp(config);
exports.checkCapacity = functions.firestore.document("gran_canaria/las_palmas_1/miller_pendientes/{albnum}")
.onCreate(async (snapshot, context) => {});
However this throws the Deployment failure error:
Failed to configure trigger providers/cloud.firestore/eventTypes/document.create#firestore.googleapis.com (gcf.us-central1.checkCapacity)
The error clears if I remove the wildcard and change the reference to:
"gran_canaria/las_palmas_1/miller_pendientes/albnum"
I've attempted changing the method to onWrite(), deleting and re-deploying the function and checking the cloud status at https://status.cloud.google.com/ but can't find any solutions.
I have been able to deploy successfully a Cloud Function with a trigger on an onCreate event on my Cloud Firestore.
I have been successful by imply using the provided template in the Console UI when creating the Cloud with the following:
The index.js used is the sample provided by GCP when created the function, which simply prints to the logs which document triggered the change.
Looking at the documentation in Firestore, I see that you probably used the samples provided there, so maybe using the above settings will make it work for you.

Admin SDK cannot set settings for Firestore

So, I've been getting this warning recently:
The behavior for Date objects stored in Firestore is going to change
AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the
following code to your app before calling any other Cloud Firestore methods:
const firestore = new Firestore();
const settings = {/* your settings... */ timestampsInSnapshots: true};
firestore.settings(settings);
With this change, timestamps stored in Cloud Firestore will be read
back as Firebase Timestamp objects instead of as system Date objects.
So you will also need to update code expecting a Date to instead
expect a Timestamp. For example:
// Old:
const date = snapshot.get('created_at');
// New:
const timestamp = snapshot.get('created_at');
const date = timestamp.toDate();
Please audit all existing usages of Date when you enable the new
behavior. In a future release, the behavior will change to the new
behavior, so if you do not follow these steps, YOUR APP MAY BREAK.
I am trying to implement the suggested correction in the admin SDK in my Cloud Functions code, since most of what I am doing is through there.
I tried using admin.firestore().settings({ timestampsInSnapshots: true }) but got the following warning:
admin.firestore(...).settings is not a function
How do I solve it?
I had the same problem. I had to update firebase-functions and firebase-admin.
To upgrade, go to your CLI, then
ProjectDirectory > Functions > npm install firebase-functions#latest firebase-admin#latest --save
Then, at the top, before triggering functions:
const firestore = admin.firestore();
const settings = {timestampsInSnapshots: true};
firestore.settings(settings);
To prevent the "Firestore.settings() has already been called" error, change
db.settings(settings);
to
try{ db.settings(settings); }catch(e){}
i solved with:
const settings = { timestampsInSnapshots: true };
const db = admin.firestore();
db.settings(settings);
db.collection('any');
Try configuring the settings right after initializing the admin SDK that might help.

Categories

Resources