How to remove listener for DocumentSnapshot events (Google Cloud FireStore) - firebase

I'm new in Google Cloud FireStore.
The Document object has a function call onSnapshot to attaches a listener for DocumentSnapshot events.
Is there a function to remove that listener (like offSnapshot)? If not how can I implement it?

In case of the web and node.js SDK, calling onSnapshot returns a function that you need to save in a variable and call when you want to remove the listener.
var unsubscribe = db.collection("cities").onSnapshot(function (querySnaphot) {
// do something with the data.
});
// Stop listening to changes
unsubscribe();
The other SDKs offer similar functionality.
See https://firebase.google.com/docs/firestore/query-data/listen#detach_a_listener for reference.

Related

Firebase functions logging does not work from non-callable functions

I'm getting started with Firebase Functions. I made a simple callable function:
exports.myCallable = functions.https.onCall((data, context) => {
console.log('I am here.');
functions.logger.log('I am here 2.');
});
As expected, I see these logs in the Logs tab in Firebase Console.
However, I also made this function, which should trigger when the user creates their account.
exports.setGroupAfterAuth = functions.auth.user().onCreate((user) => {
console.log('I am here 3.');
functions.logger.log('I am here 4.');
});
In this case, I see that the function was called in Firebase Console, but I do not see my logs.
Why do the logs appear in Firebase Console for the first function but not the second, and what can I do to make them appear in the second?
It's not possible to use the Firebase Functions client SDK to invoke an auth onCreate function.
Auth onCreate functions can only be invoked by actually creating a new user account. They cannot be invoked directly from your app.
The client SDK can only be used to invoke callable functions, as described in the linked documentation. The funciton must be declared with functions.https.onCall.

Cloud Functions: callback is not a function

According to https://cloud.google.com/functions/docs/writing/background
You use background functions when you want to have your Cloud Function invoked indirectly in response to an event, such as a message on a Cloud Pub/Sub topic, a change in a Cloud Storage bucket, or a Firebase event.
And the function paramaters are (data, context, callback): https://cloud.google.com/functions/docs/writing/background#function_parameters
However, when I write a simple function like
exports = module.exports = functions.firestore
.document(path)
.onWrite((change, context, callback) => {
callback()
return
})
I get an error that says
TypeError: callback is not a function
Is callback not part of Firestore background functions? The documentation says it is
If not, is there anyway to immediately exit a function?
The Firebase API is different than the Google Cloud API. What you linked to was the Cloud API, which accepts a callback parameter. The Firebase API which you are actually using does not. The Firebase API for background functions requires you to return a promise that resolves after all the work is complete. There is no callback to call in that case.

Firebase: Writing Custom Callable Cloud Function vs Cloud Firestore Trigger Function

I learned all about Google Cloud Functions Triggers and I understood that they are good for doing some data preprocessing before write/update/delete happens in Cloud Firestore. This is true right?
However, instead of listening to changes in the database, I would like to write custom code in Cloud Functions and call it directly from the client SDK.
The reason I want to do this is because I don't want to have long complicated database integration logic in my client code. I just want to call a cloud function named createGame for instance and let the custom cloud function handle the nested calls to the Firestore, do sanity checks and return me with only the clean data that the client will be displaying.
I found out that there is a Flutter plugin for this called cloud_functions.
Also this documentation shows how to write custom callable functions.
We can write the custom callable Cloud Function as follows:
exports.createGame = functions.https.onCall((data, context) => {
// ...
return {
...
}
});
We can call the corresponding custom callable Cloud Function from Flutter client as follows:
final dynamic response = await CloudFunctions.instance.call(
functionName: 'createGame',
parameters: <String, dynamic>{
'message': 'hello world!',
'count': clientCount,
},
);
There are tons of Cloud Functions trigger examples/videos/tutorials. But very few of callable Cloud Functions. That's why I am a little skeptic about this subject.
Question:
My question is if this is good practice? Or should I do what this specific Cloud Function is doing from the client? Please answer while keeping pricing, speed, reliability and other factors in mind also:)
One last thing,
The function implementation uses https.onCall. Do you think https is slowing things down?

Using Offline Persistence in Firestore in a Flutter App

I'm developing a app that uses Firebase's Firestore to send data to the web. One of the functions of the app is being able to save data in the device while being offline and send it to Firestore when internet connection is restored.
I activated offline persistence but it dosen't work.
DEBUG CONSOLE:
W/OkHttpClientTransport(28536): Failed closing connection
W/OkHttpClientTransport(28536): javax.net.ssl.SSLException: Write error: ssl=0x7f7acfc408: I/O error during system call, Broken pipe
W/OkHttpClientTransport(28536): at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_write(Native Method)
W/OkHttpClientTransport(28536): at com.google.android.gms.org.conscrypt.NativeSsl.write(:com.google.android.gms#14798020#14.7.98 (040406-222931072):4)
How can I activate offline persistence and sync with Firestore when internet is restored?
MY CODE:
Future<Null> sendFirebaseData(var selectedModel) async {
Firestore.instance.enablePersistence(true);
var certID = await getIDCertificado();
var dateTime = new DateTime.now();
var nowHour = new DateFormat('kk:mm:ss').format(dateTime);
Map<String, dynamic> dataHeader = {
'ID': certID,
};
Map<String, dynamic> finalDataMap = {}..addAll(dataGeneral)
..addAll(dataInstrumento)..addAll(dataPadrao)
..addAll(dataAdicional)..addAll(dataHeader);
await Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);}
when you use offline persistence in Firestore, don't use Transactions or await for response.
so, change this :
await Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);
to this:
Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);
When you restore your internet connection your data will be sync automatically, even if you are in background.
Doesn't work when your app is closed.
Context Of Promises & Callbacks when Offline
Why the above code change to remove "await" works.
Reference: Firebase Video - How Do I Enable Offline Support 11:13
Your callback won't be called and your promise won't complete until the document write has been successful on the server. This is why if your UI waits until the write completes to do something, it appears to freeze in "offline mode" even if the write was actually made to the local cache.
It is OK to not use async / await, .then() or callbacks. Firestore will always "act" as if the data change was applied immediately, so you don't need to wait to be working with fresh data.
You only need to use callbacks and promises when you need to be sure that a server write has happened, and you want to block other things from happening until you get that confirmation.
I think the currrent answer is outdated. According to the firebase documentation, offline persistentence is enabled by default for Android and iOS. For the web, it is not.
In flutter, the firestore implementation is based on the underlying OS. So you're safe on mobile apps, but not with flutter for web.
It is enabled by default but still only when you are not using await or transactions, further you can use timeout to stop listening to network connection by firestore after a specific time.
ref.setData(newNote.toMap()).timeout(Duration(seconds: 2),onTimeout:() {
//cancel this call here
print("do something now");
});

Comparing Cloud Functions for Firebase database triggers onCreate(), onWrite(), onUpdate(), when to use?

It's a simple question, I have seen all these methods addressed in the title in the documentation but all the examples are using onWrite() for triggering database events which then one would have to check to make sure it's not for removing or updating with
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
.onWrite(event => {
...
// Only edit data when it is first created.
if (event.data.previous.exists()) {
return;
}
// Exit when the data is deleted.
if (!event.data.exists()) {
return;
}
...
});
The only examples with onCreate() for instance, are related to auth events. Is there a reason or am I just being paranoid? Why not just use onCreate() and not bother the check?
onCreate(), onUpdate() and onDelete() were added in the Firebase SDK for Cloud Functions (v0.5.9) release on 7 July 2017. This is detailed in the release notes:
An updated beta release of the Firebase SDK for Cloud Functions
(v0.5.9) is now available. It includes the ability to listen to
granular create, update, and delete database events by using the
onCreate(), onUpdate(), and onDelete() methods.
Prior to that release, the only database event handler was onWrite(). The documentation has not yet been updated to include examples of the new handlers.
There is no reason not to take advantage of the convenience of the new handlers.

Resources