Skip to content

Client Data Architecture

Ka-Ping Yee edited this page Jun 20, 2019 · 2 revisions
2019 status: Current

Summary

The Buendia client encapsulates most access to data in an application data model, which retrieves data from a local database and first populates the local database, if necessary. This document gives an overview of how the client data model is structured.

Model Classes

Excluding base and supporting classes, the following model classes are available:

  • AppEncounter: a patient encounter, which may contain many observations
  • AppLocation: a location, including a reference to any parent location
  • AppLocationTree: a tree of AppLocation objects
  • AppPatient: immutable (or rarely-changed) information about a patient
  • AppPatientDelta: information describing a new patient or a patient update
  • AppUser: an application user

See individual classes for more in-depth descriptions.

Requesting Data

Model objects are accessed through the AppModel class, which typically provides results in the form of TypedCursors. TypedCursor is an interface that operates similarly to a Cursor, in that observers can be notified of data updates (in theory) and that data access is abstracted from whether the data is currently loaded in memory. Unlike Cursors, however, TypedCursors provide typed objects rather than tabular data. So, for example, callers can directly retrieve the set of all AppPatients without having any information about database structure.

Data Availability

Currently, AppModel will only produce results for fetch operations if the client database has already been populated with data from the server. Callers can verify this state by checking AppModel.isFullModelAvailable(); if false, the caller will need to first perform a sync to download data from the server. Once the data is available in the database, each AppModel function will access the database; there is currently no in-memory cache.

Event Model

AppModel operations rely on a CrudEventBus object, which provides a publisher/subscriber model for events. When an AppModel operation completes, a corresponding event is published to the CrudEventBus, and any subscribers to that event are notified. See individual AppModel functions to determine the correct event to listen for. For more information on the event model, see Event Bus.

Deserializing Data

To produce TypedCursors, the AppModel needs to convert from traditional database Cursors with tabular data to typed model objects. Generally, this is achieved by using an AppTypeConverter which implements a fromCursor(Cursor) function that performs the conversion by mapping Cursor columns to fields in the model object.

Future Improvements

Add in-memory cache

Currently, every AppModel operation accesses the database, even for data that was recently accessed. This may be not be terribly slow, as SQLite maintains its own cache, but it's possible that performance could be improved by maintaining our own cache of model objects. It will require some profiling to determine if this optimization is really worthwhile.

Consolidate similar model operations

Some model operations contain similar, boilerplate code (e.g. AppAddEncounterSyncTask and AppAddPatientSyncTask) and could almost certainly be refactored into more robust classes.

Clone this wiki locally