This file captures component-specific architectural and operational decisions for Chronicle Threads. Identifiers follow the THR-<Tag>-NNN pattern from the Nine-Box taxonomy (FN, NF-P, NF-S, NF-O, TEST, DOC, OPS, UX, RISK). Numbers are unique within the THR scope.
- Date
-
2015-02-24
- Context
-
-
Chronicle Threads aims to simplify concurrent programming for event-driven systems while delivering predictable low-latency behaviour.
-
Traditional multi-threaded handler models often require complex locking, which introduces contention, bugs, and unpredictable pauses on the hot path.
-
- Decision Statement
-
-
Each
EventLoopinstance runs on a dedicated Java platform thread. -
All
EventHandlerinstances registered with a givenEventLoop(except handlers withBLOCKINGorCONCURRENTpriorities, which use their own threading model within anEventGroup) are executed serially by that single thread.
-
- Alternatives Considered
- * Multi-threaded event loops
-
-
Description: Execute handlers from a shared loop across a thread pool.
-
Pros: Higher potential throughput if handlers are fully independent.
-
Cons: Requires thread-safe handlers, more locking, less predictable latency, and harder reasoning about shared state.
-
- * Actor model per handler
-
-
Description: Each handler has its own queue and dedicated thread.
-
Pros: Strong isolation between handlers.
-
Cons: Higher resource usage (threads, queues) and higher message-passing overhead than serial invocation on one loop.
-
- Rationale for Decision
-
-
Single-threaded loops make handler implementation simpler by removing most intra-loop locking requirements.
-
They support low-jitter latency by avoiding lock contention in the main execution path.
-
The model aligns with a common thread-per-core pattern used in low-latency systems.
-
- Impact & Consequences
-
-
Positive:
-
Simplifies handler development and testing.
-
Improves latency predictability for all handlers on a given loop.
-
Makes it easier to reason about state owned by handlers on one loop.
-
-
Negative:
-
Throughput of a single
EventLoopis bounded by one CPU core. -
A misbehaving or blocking handler on a standard loop can starve other handlers on that loop. This is mitigated by using
EventGroupwithBLOCKINGorCONCURRENThandlers on separate threads or thread pools.
-
-
- Notes/Links
-
-
Core implementation:
VanillaEventLoop,MediumEventLoop. -
Requirements: Handler management requirements, including THR-FN-006.
-
- Date
-
2015-02-24
- Context
-
-
For latency-critical fast threads (often pinned to isolated cores), minimising wake-up time when new work arrives is essential.
-
Standard pause strategies that yield or sleep introduce variable and often large delays before a thread resumes work.
-
- Decision Statement
-
-
EventLoopinstances configured for maximum performance (for example usingPauserMode.BUSYorPauserMode.TIMED_BUSY) use a busy-spinning or near busy-spinningPauserby default. -
Other pauser modes (
YIELDING,BALANCED,SLEEPY,MILLI) remain available and are recommended for less latency-sensitive loops or where CPU cores are constrained.
-
- Alternatives Considered
- * Yielding pauser as default
-
-
Description: Call
Thread.yield()when idle. -
Pros: More CPU-friendly than pure busy-spin.
-
Cons: Higher and less predictable wake-up latency.
-
- * Sleeping pauser as default
-
-
Description: Sleep or park immediately when idle.
-
Pros: Lowest CPU usage when idle.
-
Cons: Highest wake-up latency and jitter.
-
- * Adaptive pauser as universal default (for example
BALANCED) -
-
Description: Combine spinning, yielding, and sleeping adaptively.
-
Pros: Good general-purpose balance.
-
Cons: Not as fast as a dedicated busy-spin for the most latency-sensitive loops.
-
- Rationale for Decision
-
-
Busy-spinning keeps the thread hot on its core and avoids scheduler and context-switch overhead, giving the minimum wake-up latency when events arrive.
-
Users can explicitly opt into less aggressive pausers when CPU utilisation must be reduced.
-
- Impact & Consequences
-
-
Positive:
-
Minimises p99.99 and tail latency for designated fast threads.
-
Provides predictable entry into handler code once an event is visible.
-
-
Negative:
-
Consumes a full CPU core even when idle, so requires careful system configuration (isolated cores, enough headroom for other work).
-
Misuse (too many busy-spinning threads) can degrade overall system performance.
-
-
- Notes/Links
-
-
Key classes:
Pauser,BusyPauser,PauserMode. -
Requirements: Idle strategy and key performance targets (THR-FN-010, THR-NF-P-027..THR-NF-P-031).
-
Additional guidance:
README.adocpauser section.
-
- Date
-
2018-05-11
- Context
-
-
Chronicle Queue and other disk-backed Chronicle components can fail or lose data if the underlying storage fills up.
-
Operations teams need early, component-aware warning of low disk-space conditions to act before failure.
-
- Decision Statement
-
-
Chronicle Threads provides a background monitoring singleton
DiskSpaceMonitor. -
The monitor periodically checks disk usage for paths associated with Chronicle components (for example queue directories as they are initialised).
-
When free space falls below a configurable threshold, a
NotifyDiskLowservice (defaultNotifyDiskLowLogWarn) logs warnings. The threshold is configured via system propertychronicle.disk.monitor.threshold.percent.
-
- Alternatives Considered
- * No built-in monitoring
-
-
Description: Rely solely on external system-level disk monitoring.
-
Pros: Keeps the library simpler.
-
Cons: External monitoring might not be tuned to Chronicle usage; users can forget to set it up.
-
- * More aggressive built-in actions
-
-
Description: Automatically halt writers when space is critically low.
-
Pros: Could prevent writes that would immediately fail.
-
Cons: Too intrusive for a general-purpose library; better handled by application policy.
-
- Rationale for Decision
-
-
A built-in monitor provides a lightweight, Chronicle-aware early warning without enforcing policy.
-
Logging is non-intrusive and keeps responsibility for operational response with the application and operations teams.
-
The
ServiceLoaderbasedNotifyDiskLowcontract allows custom notification or escalation strategies.
-
- Impact & Consequences
-
-
Positive:
-
Gives early warning of storage exhaustion for Chronicle workloads.
-
Reduces the risk of unexpected failures caused by full disks.
-
-
Negative:
-
Adds minimal overhead (one background thread plus periodic I/O).
-
Effectiveness depends on log monitoring or a custom
NotifyDiskLowimplementation.
-
-
- Notes/Links
-
-
Key classes:
DiskSpaceMonitor,NotifyDiskLow,NotifyDiskLowLogWarn. -
Properties:
chronicle.disk.monitor.disable,chronicle.disk.monitor.threshold.percent(see also system properties table.)
-
- Date
-
2025-03-01
- Context
-
-
The project needs a consistent, structured way to identify and trace requirements, decisions, tests, and possibly code artefacts.
-
Earlier schemes using ad-hoc or simple sequential numbering made it difficult to infer scope or intent from an identifier alone.
-
- Decision Statement
-
-
All functional requirements (in
project-requirements.adoc) and architectural decisions (in this log) use identifiers prefixed withTHR-, followed by a Nine-Box tag (for exampleFN,NF-P,OPS,DOC) and a sequence number (for exampleTHR-FN-001). -
The Nine-Box tag definitions and usage guidelines are maintained in
AGENTS.md.
-
- Alternatives Considered
- * Simple sequential numbering (for example
REQ-001,DEC-001) -
-
Description: Use only numeric sequence numbers.
-
Pros: Very easy to implement and explain.
-
Cons: Conveys no information about type or domain.
-
- * Custom project-specific categorisation scheme
-
-
Description: Invent a bespoke set of categories for Chronicle Threads only.
-
Pros: Could be tailored closely to the project.
-
Cons: Extra effort to define and maintain; less transferable knowledge for staff working across multiple Chronicle projects.
-
- Rationale for Decision
-
-
The Nine-Box taxonomy already provides a broadly applicable and documented set of categories.
-
Using the same taxonomy across Chronicle projects improves consistency and makes it easier for people to move between modules.
-
Including the tag in identifiers gives immediate context about what an item represents.
-
- Impact & Consequences
-
-
Positive:
-
Better traceability between requirements, decisions, tests, and code.
-
Easier for team members to understand the role of an item from its ID.
-
Supports better organisation and searching in documentation and tooling.
-
-
Negative:
-
Requires familiarity with the Nine-Box taxonomy and consistent application.
-
Initial documentation and training overhead (captured in
AGENTS.md).
-
-
- Notes/Links
-
-
Nine-Box taxonomy details and guidance:
AGENTS.md. -
Requirements catalogue: Functional requirements for Chronicle Threads.
-
- Date
-
2025-03-01
- Context
-
-
EventGroupcoordinates multiple child loops and routes handlers based on their declaredHandlerPriority. -
Not all deployments require every priority; some groups should expose a restricted set of priorities or be effectively disabled for application handlers.
-
Earlier behaviour allowed handlers to be added even when the group had not been configured explicitly with a corresponding priority set, making it harder to reason about which handlers were admissible.
-
- Decision Statement
-
-
EventGroupinstances are configured with a set of supported handler priorities. -
Loops are only materialised for the priorities included in this set; other loops are omitted.
-
Attempts to register a handler whose
HandlerPriorityhas no corresponding loop (for example because that priority is not in the configured set) fail fast with anIllegalStateException. -
A group configured with an empty priority set retains only its monitor loop; attempts to add handlers with any other priority are rejected.
-
- Alternatives Considered
- * Implicit support for all priorities
-
-
Description: Treat all priorities as supported unless explicitly disabled, materialising loops lazily on first handler registration.
-
Pros: Minimal configuration, potentially simpler for small deployments.
-
Cons: Harder to predict resource usage and topology; accidental handler registration can silently create extra loops and threads.
-
- * Soft failure for unsupported priorities
-
-
Description: Drop or log handlers whose priorities are not supported instead of throwing.
-
Pros: Avoids exceptions in misconfigured systems.
-
Cons: Silent misconfiguration is dangerous; handlers may never run with little or no visibility.
-
- Rationale for Decision
-
-
An explicit priority set makes
EventGrouptopology predictable and keeps resource allocation under operator control. -
Failing fast when a handler targets an unsupported priority surfaces configuration errors early in development and testing.
-
Retaining only the monitor loop when the set is empty supports scenarios where an
EventGroupinstance is used purely for monitoring infrastructure rather than application handlers.
-
- Impact & Consequences
-
-
Positive:
-
Clearer reasoning about which handlers can attach to a given group.
-
Better alignment between configuration (builder calls) and the underlying loop topology.
-
Easier to construct priority-limited or monitor-only groups without surprising background loops.
-
-
Negative:
-
A stricter contract means some previously permissive configurations now fail fast and require explicit updates to their configured priority sets.
-
Callers that expect to use priorities that are not enabled for a given group must update their configuration or routing.
-
-
- Notes/Links
-
-
Requirements: THR-FN-004 and THR-FN-005 handler management requirements.
-
Key types:
EventGroup,EventGroupBuilder.withPriorities(java.util.Set),HandlerPriority.
-