Skip to main content
Version: 3.0.0

Core Concepts

This page provides detailed definitions of ChronoLog's core data model concepts. For a high-level overview, see the Overview.

Conceptual Hierarchy

CONCEPTUAL HIERARCHYChronicleclient-level namespace / containerStoryclient-level time-series datasetStoryChunkservice-internal time-windowed event batchEventclient-visible individual recordstoryIdeventTimeclientIdeventIndexlogRecord (application payload)ArchiveArchiveArchiveArchiveordered by EventSequence (eventTime, clientId, eventIndex)

Client-facing developers primarily interact with Chronicle, Story, and Event. System and infrastructure developers also work with internal concepts such as StoryChunk and Archive.

Client-Level Concepts

Chronicle

A Chronicle is the top-level organizational unit in ChronoLog — a named container that groups related Stories together for easier data management. Each Chronicle is uniquely identified by a numeric ChronicleId, computed as CityHash64(chronicleName). This deterministic hashing means that any process in the distributed system can independently derive the same ID from the same name without coordination.

Chronicle-level attributes (indexing granularity, type, tiering policy, user-defined properties and metadata) are reserved for future use. The v3.0.0 client API does not expose them — Client::CreateChronicle takes only the chronicle name.

Story names are scoped within their parent Chronicle, so two different Chronicles may each contain a Story with the same name without conflict. The Chronicle maintains an acquisition reference count that tracks how many clients are currently using it.

Story

A Story is a time-series dataset within a Chronicle. It represents a logical stream of events that client applications generate over time. Each Story is uniquely identified by a StoryId, computed as CityHash64(chronicleName + storyName). Concatenating the Chronicle name ensures that identically named Stories in different Chronicles receive distinct IDs.

Story-level attributes (indexing granularity, type, tiering policy, access permission) are reserved for future use. The v3.0.0 client API does not expose them — Client::AcquireStory takes only the chronicle name and the story name.

The ChronoVisor maintains an in-memory representation of each Story that tracks which clients have acquired (are actively writing to) the Story. This acquirer client map is protected by a mutex for thread-safe concurrent access. The Story's acquisition count acts as a reference counter — a Story cannot be removed while any client holds it.

Event

An Event is the atomic data unit in ChronoLog. Every piece of data stored in the system is represented as an Event. Each event carries five fields: the storyId identifying which Story it belongs to, an eventTime timestamp, the clientId of the application that generated it, an eventIndex (per-client counter to disambiguate events with identical timestamps), and a logRecord containing the opaque application payload.

Events are globally ordered by a composite key called EventSequence, which is the tuple (eventTime, clientId, eventIndex). This three-part key is essential for distributed uniqueness: because multiple clients on different HPC nodes may generate events at the same timestamp, the clientId component distinguishes them. The eventIndex further handles the case where the same client produces multiple events within a single timestamp granularity (e.g., from different threads). Equality comparison checks all identifying fields (storyId, eventTime, clientId, eventIndex) but deliberately excludes the logRecord payload.

Service-Internal Concepts

StoryChunk

A StoryChunk is a container for Events that fall within a specific time window [startTime, endTime) — including the start time and excluding the end time. Events within a StoryChunk are stored in a sorted map keyed by EventSequence, ensuring they are always maintained in global order.

StoryChunks are the unit of data movement through the distributed pipeline. ChronoKeeper processes on compute nodes collect events into StoryChunks during a configurable acceptance window. When the window expires, the StoryChunk is forwarded to a ChronoGrapher process on a storage node. Because multiple ChronoKeepers may handle events for the same Story, each produces a partial StoryChunk for overlapping time ranges. The ChronoGrapher merges these partial chunks into its own StoryPipeline — a sequence of StoryChunks ordered by start time.

Each StoryChunk also carries a revisionTime field that records when it was last modified, enabling the system to track data freshness during the merge process.

Archive

An Archive provides historical storage associated with a Chronicle. Each Archive is identified by an ArchiveId, computed as CityHash64(toString(chronicleId) + archiveName). Archives reserve a user-defined property list for application-specific metadata; it is not exposed by the v3.0.0 client API.