Skip to main content

Cache layout

Census stores its cache in Memgraph, behind the CacheStore trait of crates/store-api. Memgraph is the only backend. Every backend must pass the conformance checks in crates/store-api/src/conformance/, and apply each change in one transaction.

The cache holds only data that Census can fetch again. There are no migrations: a build with a different layout version empties the cache at startup and refills it from the sources.

Nodes​

Every node carries inventory and view. view is empty for the default view, and the branch name in a branch view. There are no relationships: the records of an entity are found by (inventory, view, hfid).

LabelKeyHolds
:Record{inventory}/{contribution}/{view}/{object_type}/{native_id}One contribution's observation of one source object: native id, source reference, object type, original and cleaned HFID, exclusion, one observation per field and the location observation.
:Entity{inventory}/{view}/{hfid}The resolved entity: one f_<field> property per non-null resolved value, one loc_<level> property per level of the resolved location, the location path, and the full resolution.
:ContributionState{inventory}/{contribution}/{view}Snapshot, health, last publication, last attempt, last error, the branch view it supplied and why, and the collection hash.
:InventoryStateinventoryThe resolution hash, and ready or rebuilding.
:CacheLayoutThe layout version.

The object type is part of a record's key because a source numbers each type separately: a NetBox device and a virtual machine can both have id 5.

Each node stores its whole value as one JSON property (record_json, entity_json, state_json), which reads decode. The other properties exist for queries and indexes.

Observations​

A record holds one observation per field the contribution supplied:

KeyMeaning
statevalue, unknown or cleared. A field without an entry was not supplied.
valueThe normalized, typed value.
outcomeas_reported, mapped, defaulted, unmapped, wrong_type or ambiguous.
originalThe value as the source reported it.
path, level_pathsThe source path of the field, or of each location level.
observed_atWhen Census received the observation. Publication compares it with the refresh start.
confirmed_atWhen the source last confirmed the value. Freshness is computed from it.

Keeping the original value lets Census normalize every observation again after a vocabulary or mapping change, without fetching from the sources.

Queries on resolved values​

Filters, sorting and counts run on the entity's f_<field> and loc_<level> properties. A null resolved value is not stored, which is why a null never matches a filter. Memgraph indexes are per label and property, so Census creates one index per field name and level name used by any inventory, shared by every inventory that uses the name.

Indexes also exist on the keys, inventory and hfid, and on a record's contribution and excluded properties.

Values computed at read time​

Completeness depends on the state of every contribution, and freshness on the time of the request. Both are computed when a query runs, from the contribution states, the count of excluded records and each value's confirmed_at, and are not stored on the entity.