I'm slightly confused about the availability of a collections, and exactly what happens when I use them in different places. I have a collection at /imports/api/clubs When I use it in my Meteor.methods it works fine. If I then import it into say a template file /imports/ui/pages/new_club.js and insert something into it, will it update the local cache only? Is the local collection reactive, i.e. will my helpers re-run?
A Meteor collection contains 0-N documents. A collection can be managed or unmanaged.
A managed collection:
is persisted via MongoDB on a server. It will survive either the client or the server stopping.
Exists only on the server unless it is published to the client via either the autopublish package or via one or more publications
the server automatically has read-write access to all documents in the collection
publications can be used to restrict the subset of the documents (both which documents and which keys) are available to any particular client.
changes to a collection on the server are automatically and asynchronously propagated to the affected client(s) via Meteor's DDP protocol which normally runs over WebSocket.
if changes are made to a collection from the client, the client's view is immediately updated (called an "optimistic update", part of Meteor's "latency compensation") and then the server attempts to make the same change. The server version ultimately "wins" in that changes from the server are asynchronously re-propagated back to the affected client(s).
An unmanaged collection:
exists only on the client
can be written to and read from only from the client
is not shared between clients
On the server side Meteor has access to the full MongoDB API. On the client side, Meteor has implemented "minimongo" which presents a restricted API. Minimongo is notably missing mongodb's aggregation framework as well as geo-queries.
Finally, to answer your specific question: yes, collections are reactive to changes made anywhere, either on the client you're on, by the server, or initiated on someone else's client
Related
I am wondering if IndexedDB is the only cache Firestore uses.
To be clear, I am not talking about persisting data with enableIndexedDbPersistence(). I am talking about an internal store for the sole purpose of optimistic updates when the app is still in state. Is there something similar to redux, svelte store, or InMemoryCache which is run in the background when a subscription is open?
It seems that when I use onSnapShot() for a list of items, and I update an item in the list with setDoc elsewhere, the UI gets updated immediately, optimistically.
Perhaps Firestore is just that quick where the data is sent to the server, changed, and sent back to the client with the UI being updated that quickly, but it seems to me it is an optimistic update.
Does Firestore use any other caching techniques or state management techniques when the app is still running besides IndexedDB?
J
References (maybe releated):
Does Firebase cache the data?
As long as you have an active onSnapShot listener, the Firestore SDK will have a copy of the latest query snapshot for that listener in memory. If you attach another listener to the same (or partially overlapping) data, that listener may get (part of) its data from the existing listener.
So when you perform an update in the same client as where you have a listener, the SDK immediately applies that update to its local copy of the data and fires an event (so that is almost instantly). It then sends the update to the server, which executes it on the backend storage layer. If that update gets rejected (a relatively rare occurrence), the client will revert the change it make locally and fire another event with the corrected state.
An easy way to see this in practice is to perform a write operation that is rejected by your security rules. You'll briefly see the invalid state on the client, before it reverts to the correct state. This invalid state only happens on the client that performs the invalid write, so it's typically fine to ignore it there.
I have a single page web application and I have NOT enabled offline persistence.
A component in this application has subscribed to a document using the onSnapshot function and recieves updates.
An other component in the same application instance reads the same document using the get function. Will firebase provide the same instance of the document, which is already loaded in the subscription? Or will it do a new request to the server?
A third component in the same application instance subscribes to the same document. Will this trigger new requests to the server?
What about reading and subscribing collections?
What about subscribing to a collection which is already subscribed, but the second subscription is called after narrowing results with the where function? Will Firestore reuse the already loaded complete collection and filter in my client instance? Or will it make server requests?
As a rule, Firestore does maintain a local cache, mostly for latency/response, not for cost savings. That said, if a document can be read from the cache, it will be, saving the read. I wouldn't try to "design" it in, however; memory limits and other considerations mean you don't really know what's in the cache or not, and shouldn't know.
IF this performance/cost is important to you, it's better to combine Firestore with something like Redux (which I do) to maintain local "sets" of documents to reduce round-trip calls, and Listeners to keep Redux current.
yes. Firebase stores documents and collections in cache memory. when you are offline you can access cache copy of data. also you can manage cache copy of documents and collections.
read this offical docs for more info
https://firebase.google.com/docs/firestore/manage-data/enable-offline
I am learning meteor and did the to-do project in meteor's tutorial. I was wondering how to hide some data from the client since files outside the server folder can be seen from the client.
Let's say a user does register to the app and want to call an external api to fetch some data and i use a secret to do so, and I dont want to expose this secret. Then I want to add this data that i got to the user collection.
Actually I use Meteor methods (ran by client and server).
Thank you.
You can do this in a Meteor Method. Put the code for this method in /server and it won't be shared with the client. You call the method from the client using Meteor.call()
Also note that it's good practice to put secrets in a settings file and to manage this file outside of your version control system. See Making Use of Settings.json
I was wondering if it is possible that a server can subscribe to a collection from the clients so that only the server got everything and the users only have their local copy of the data.
I would like to create a meteor (mobile) app where people can create some content and store it in a collection (only local on the device) that noone can see except the "owner" itself locally and the server who owns everything. If a local collection is created the server subscribes to that collection so the server can collect all the data from every user and show it e.g. on a website. So I have 3 Components. The mobile app that generates the content (clients), the server that collects everything, and a website that only read the db with the complete content.
so,
is it possible that a server can subscribe to every collection from every user?
Yes, but the idea is: every subscribed user (client) is allowed to see his data. Have a look at the collection.allow(options) documentation. A client subscribes to a collection and the server decides what the client can see.
If you have some kind of authentication (or if you use the Accounts Meteor package) you can use Meteor.publish()on server side to only publish what belongs to the current user.
For example:
//Common Collection for both client and server (declared in lib/ for example):
//(will be a full DB on the server and a minimongo with published data only
//on the client)
Data = new Mongo.Collection('Data');
//Server: (publish to client only what belongs to the user)
Meteor.publish('userData', function(){
return Data.find({your_user_id_field:this.userId});
});
//Client: (the client only gets the data that belongs to him/her)
Meteor.subscribe('userData');
[... use the local collection as usual ...]
I'd like to better understand how the subscription model works - let's say I have some global subscriptions ie. they are loaded when the client starts, assuming it's the client's first connection to the Meteor server then all required data will be populated in minimongo and kept in sync with the server for the duration of the session.
But what happens when the client closes the app and reconnects at later stage:
Is the local store kept indefinitely on the client?
If above is true, then when the user re-connects would the data be synced to handle any differences between the local and server dbs?
Minimongo is an in-memory javascript datastore. Because it is not persisted to disk, none of the data will be available after the client browser/tab is closed. When a client reconnects, minimongo will be empty and all active subscription data will be synced as if for the first time.