I am wondering if there is a way to get the current server time directly.
the way I do it is by writing a doc and using FieldValue.serverTimestamp(), then reading it again.
but is there a way to know what is the current server clock or time without writing and reading again?
FirebaseFirestore.instance.collection('users').doc(currentUser.uid).update({
'currentTime':FieldValue.serverTimestamp(),
});
i cannot use client side time for several reasons
Firestore timestamps are generated only on the server. There is currently no way to immediately read the value of a timestamp field. This means that the server-side timestamp is null until you get the response from the Firebase server. So as you already noticed, you have to write and read it back.
That being said, I recommend you use FieldValue.serverTimestamp() because it can store time units as small as nanoseconds.
Related
I have noticed a delay between the time some data is written to Firestore and when it is available to be read via a query. In my tests I see this can go up to 30sec.
Is this documented anywhere?
Are there ways to decrease this delay?
Is there a way to know the server timestamp corresponding to the data being returned? Or to have any indication about this delay in the data being returned from Firestore?
(say some data is written to the server at 1:00 - the document is created server-side at that time, I query it at 1:01, but due to the delay it returns the data as it was at 0:58 server-side, the timestamp would be 0:58)
Here I am not speaking about anything with high load, my tests were just about writing and then reading 1 small document.
Firestore will have some delays, even I have noticed it. It's better to use the Realtime Database as it lives up to the name, the time lag is minimal, less than a second in most cases !
If you use Firestore on a native device offline first is enabled by default. That means data is first written to a cache on your device and then synced to the backend. On Web you can enable that to. To listen for those changes when a write is saved to the backend you would need to enable includeMetadataChanges on your realtime listeners:
db.collection("cities").doc("SF")
.onSnapshot({
// Listen for document metadata changes
includeMetadataChanges: true
}, (doc) => {
// ...
});
That way you will get a notice when the data is written to the backend. You can read more about it here.
The delay should be only between different devices. If you listen to the changes on your device where you write the data it will be shown immidiately.
Also something you should take care of. If you have offline enabled you should not await for the writes to finish. Just use them as if they are synchronous (even on web with enabled offline feature). I had that before in my code and it looked like the database was slow. By removing the await the code was running much faster.
I didn't find any solutions to avoid reading data from the server when using get(). However, I might found a solution but it's not clear to me if it will work. I found that when using the real-time feature, the client will continuously update as the data changes. So per my understanding, if nothing is changed on the server, no reads charged, right?
However, I read that the listener should be removed, and I understood why, what I cannot understand is, if I close the app (listener is removed) and I open the app the second day, am I charged again for the data that was cached a day before?
I'm really confused because I also read that:
Also, if the listener is disconnected for more than 30 minutes (for example, if the user goes offline), you will be charged for reads as if you had issued a brand-new query.
Removing the listener and going online, are not the same exact thing?
I found that when using the real-time feature, the client will continuously update as the data changes. So per my understanding, if nothing is changed on the server, no reads charged, right?
Every query that reaches the server will incur reads for documents returned by the query. Whenever a document is returned from the server, it costs a read. If you have a listener on a set of query results where only one document changes while the listener is active, it costs one read, because only one document must come from the server, and the rest are already in memory. They stay in memory until the listener is removed.
if I close the app (listener is removed) and I open the app the second day, am I charged again for the data that was cached a day before?
Yes. Whenever the results come from the server, you will be billed for those reads. The cache is not used to satisfy query results when using the server as a source.
Removing the listener and going online, are not the same exact thing?
They are not the same thing. Removing a listener says that you're completely done with the results of the query. Going online temporarily and coming back online just resumes the existing query.
I discovered a very useful function named get(Source source). If I pass CACHE, I can get data only from cache. But how about set(Source source)? I cannot find something similar. I need to save data locally and push it to the server only when needed. How to solve this? Or any other alternatives? Thanks
What you're trying to do is not supported by the Firestore client libraries. Then only kind of writes you can perform will always be synchronized to the server at the earliest opportunity. There is no operation that lets you write, then decide to synchronize later.
What you should do instead is write data to some other local storage (perhaps a database), then write those records to Firestore when you're ready.
Is it possible to limit the speed at which Google Firestore pushes writes made in an app to the online database?
I'm investigating the feasibility of using Firestore to store a data stream from an IoT device via a mobile device/bluetooth.
The main concern is battery cost - receive a new data packet roughly two minutes, I'm concerned about the additional battery drain that an internet round-trip every two minutes, 24hrs a day, will cost. I also would want to limit updates to wifi connections only.
It's not important for the data to be available online real-time. However it is possible for multiple sources to add to the same datastream in a 2-way sybc, (ie online DB and all devices have the merged data).
I'm currently handling that myself, but when I saw the offline capability of Datastore I hoped I could get all that functionality for free.
I know we can't directly control offline-mode in Firestore, but is there any way to prevent it from always and immediately pushing write changes online?
The only technical question I can see here has to do with how batch writes operate, and more importantly, cost. Simply put, a batch write of 100 writes is the same as writing 100 writes individually. The function is not a way to avoid the write costs of firestore. Same goes for transactions. Same for editing a document (that's a write). If you really want to avoid those costs then you could store the values for the thirty minutes and let the client send the aggregated data in a single document. Though you mentioned you need data to be immediate so I'm not sure that's an option for you. Of course, this would be dependent on what one interprets "immediate" as based off the relative timespan. In my opinion, (I know those aren't really allowed here but it's kind of part of the question) if the data is stored over months/years, 30 minutes is fairly immediate. Either way, batch writes aren't quite the solution I think you're looking for.
EDIT: You've updated your question so I'll update my answer. You can do a local cache system and choose how you update however you wish. That's completely up to you and your own code. Writes aren't really automatic. So if you want to only send a data packet every hour then you'd send it at that time. You're likely going to want to do this in a transaction if multiple devices will write to the same stream so one doesn't overwrite the other if they're sending at the same time. Other than that I don't see firestore being a problem for you.
I have a form with a list that shows information from a database. I want the list the update in run time (or almost real time) every time something changes in the database. These are the three ways I can think of to accomplish this:
Set up a timer on the client to check every few seconds: I know how to do this now, but it would involve making and closing a new connection to the database hundreds of times an hour, regardless of whether there was any change
Build something sort of like a TCP/IP chat server, and every time a program updates the database it would also send a message to the TCP/IP server, which in turn would send a message to the client's form: I have no idea how to do this right now
Create a web service that returns the date and time of when the last time the table was changed, and the client would compare that time to the last time the client updated: I could figure out how to build a web service, but I don't how to do this without making a connection to the database anyway
The second option doesn't seem like it would be very reliable, and the first seems like it would consume more resources than necessary. Is there some way to tell the client every time there is a change in the database without making a connection every few seconds, or is it not that big of a deal to make that many connections to a database?
I would imagine connection pooling would make this a non-issue. Depending on your database, it probably won't even notice it.
Are you making the update to the database? Or is the update happening from an external source?
Generally, hundreds of updates per hour won't even bother the DB. Even Access, which is pretty slow, won't cause a performance issue.
Here's a rough idea if you really want to optimize it and you're doing the data updates. Store an application variable on the server side called, say, LastUpdateTime. When you make updates to the database, you can update the LastUpdateTime variable with the current time. Since LastUpdateTime is a very lightweight object in server memory, your clients can technically request the last update time hundreds if not thousands of times per second without any round trip to the database. Based on the last time the client retrieved new information vs. the last update time on the server, you can then go fetch the updated info.
We have a similar question Polling database for updates from C# application. Another idea (may be not a proper solution) would be to use Microsoft Sync Framework. You can use a timer to sync the DB.