LiteCore
Couchbase Lite cross-platform core implementation
Loading...
Searching...
No Matches
c4Observer.h File Reference
#include "c4DocumentTypes.h"

Go to the source code of this file.

Collection Observer

typedef void(* C4CollectionObserverCallback) (C4CollectionObserver *observer, void *context)
 Callback invoked by a collection/database observer.
 
NODISCARD CBL_CORE_API C4CollectionObserverc4dbobs_createOnCollection (C4Collection *collection, C4CollectionObserverCallback callback, void *context, C4Error *error)
 Creates a new collection observer, with a callback that will be invoked after one or more documents in the collection have changed.
 
NODISCARD CBL_CORE_API C4CollectionObservation c4dbobs_getChanges (C4CollectionObserver *observer, C4CollectionChange outChanges[], uint32_t maxChanges)
 Identifies which documents have changed in the collection since the last time this function was called, or since the observer was created.
 
CBL_CORE_API void c4dbobs_releaseChanges (C4CollectionChange changes[], uint32_t numChanges)
 Releases the memory used by the C4CollectionChange structs (to hold the docID and revID strings.) This must be called after c4dbobs_getChanges().
 

Document Observer

typedef void(* C4DocumentObserverCallback) (C4DocumentObserver *observer, C4Collection *collection, C4String docID, C4SequenceNumber sequence, void *context)
 Callback invoked by a document observer.
 
NODISCARD CBL_CORE_API C4DocumentObserverc4docobs_createWithCollection (C4Collection *collection, C4String docID, C4DocumentObserverCallback callback, void *context, C4Error *error)
 Creates a new document observer, with a callback that will be invoked when the document changes.
 

Query Observer

A query observer, also called a "live query", notifies the client when the query's result set changes.

(Not just any time the database changes.)

This is done as follows, starting from when the first time an observer on a particular query is enabled:

  1. A separate C4Query instance is created, on a separate database instance (there's one of these background database instances per C4Database.)
  2. The copied query is run on a background thread, and it saves its results.
  3. The query observer(s) are notified so they can see the initial results.
  4. The background thread listens for changes to the database, or changes to the query parameters (c4query_setParameters). In response:
    • If it's been less than 250ms since the last time it ran the query, it first waits 500ms; during this time it ignores further database changes.
    • It runs the query.
    • It compares the new result set to the old one; if they're different, it saves the new results and notifies observers. Otherwise it does nothing.
  5. This background task stops when the last observer is disabled.

Some notes on performance:

All C4Queries on a single C4Database share a single background C4Database, which can only do one thing at a time. That means multiple live queries can bog down since they have to run one after the other. The first time any query observer is added in a given C4Database, the background database instance has to be opened, which takes a few milliseconds. The first time an observer is added to a C4Query, a copy of that query has to be created and compiled by the background database, which can also take a few millseconds. Running a C4Query before adding an observer is a bit of a waste, because the query will be run twice. It's more efficient to skip running it, and instead wait for the first call to the observer. The timing logic in step 4 is a heuristic to provide low latency on occasional database changes, but prevent rapid database changes (as happen during pull replication) from running the query constantly and/or spamming observers with notifications. (The specific times are not currently alterable; they're constants in LiveQuerier.cc.)

typedef void(* C4QueryObserverCallback) (C4QueryObserver *observer, C4Query *query, void *context)
 Callback invoked by a query observer, notifying that the query results have changed.
 
NODISCARD CBL_CORE_API C4QueryObserverc4queryobs_create (C4Query *query, C4QueryObserverCallback callback, void *context)
 Creates a new query observer, with a callback that will be invoked when the query results change, with an enumerator containing the new results.
 
CBL_CORE_API void c4queryobs_setEnabled (C4QueryObserver *obs, bool enabled)
 Enables a query observer so its callback can be called, or disables it to stop callbacks.
 
NODISCARD CBL_CORE_API C4QueryEnumeratorc4queryobs_getEnumerator (C4QueryObserver *obs, bool forget, C4Error *error)
 Returns the current query results, if any.