Evict & Remove
As the development of your app progresses toward production, apply more careful thought to how you approach to data that is synchronized across all clients that access your Ditto database.
In peer-to-peer database design, there are technical tradeoffs between the amount of data synced across peers and timeliness of access to synced data:
- The greater the amount of data synced across connected peer devices, the more timely offline read access becomes. That is, database resilience in offline scenarios increases when there are more documents being synced across distributed peers.
- The fewer the number of documents synced, the less the likelihood that peer devices run out of disk space and experience memory leaks, as well as the performance of the peer-to-peer mesh network that interconnects them degrades.
Eviction
Given these technical tradeoffs, use the Subscription and Eviction APIs carefully to implement your tradeoff design decisions:
- To sync more data across peers connected in the mesh, call
.subscribe()
. - To remove data stored locally on peer device, call
.evict()
.
collection.find("owner == 'Bob'").evict()
warning
Make sure that you stop subscriptions before calling evict()
. If not, the subscription remains active and, even if you reset the data in a device, the evicted data will reappear on the screen in a single instantaneous flicker.
When do I evict data?
The cadence that you choose to remove data stored locally on a device depends on your app's use case and data volume:
- If you want to mitigate the risk of depleting local disk space, memory leaks, and a degraded mesh network connection, evict data at least once per day.
- If you want to increase offline database resiliency, evict data no more than once per week.
How can I force clients to evict data?
If you want to indicate that a batch of documents are irrelevant and, although
they are to be retained, should not sync across peers, add the isSafeToEvict
field to the document property tree, and then use some means to inform clients
to flag any documents that they consider irrelevant.
{ "_id": "abc123", "color": "red", "mileage": 40000, "isSafeToEvict": true, "createdAt": "2023-05-22T22:24:24.217Z"}
To ensure that small peers continue syncing documents that are considered
relevant, include isSafeToEvict == false
in their subscription queries. That
way, only the document that a client sets to 'true' are prevented
from syncing. Once flagged, the
clients purge the irrelevant documents from their caches, all the while normal
transactional operations continues without interruption.
collection.find("createdAt > "'2023-05-22T22:24:24.217Z" && isSafeToEvict == false").subscribe()
Soft-delete documents
Eviction is not permanent; as long as there is at least one active subscription whose query includes an evicted document, that document will reappear as soon as it is available in the mesh.
Consider using a "soft-delete" pattern in your application. You should use a
field like isArchived: true
instead of calling remove()
, and then evict that data. You can query and
synchronize only the documents that not been marked archived. Using a
soft-delete pattern, documents can be synced or updated again if necessary.
{ "_id": "123abc", "name": "Foo", "isArchived": true // add this field}
And query non-archived documents like so:
let liveQuery = ditto .store.collection('cars') .find('!isArchived').observeLocal((documents) => { console.log('these are the unarchived documents', documents) })
You can easily un-archive these documents by calling update on that field:
ditto.store.collection('cars').update((mutableDoc) => { mutableDoc["isArchived"] = false})
Remove
Removes will delete or remove one or more documents from the collection. Calling remove will sync removals to the local device and to other devices as well.
danger
Removing documents will remove documents from the local device and other
peers. Your application code should consider remove
calls to be destructive.
In other words, if you call remove on document, your application should consider
this document gone throughout your system.
In the v4 version of Ditto, any device can “undo” the remove by calling upsert on the document with _id=abc123
again.
collection.findByID(docID).remove()