ποΈ Core Architecture β
Tempo v3.7.x introduces several industry-leading architectural patterns designed for maximum resilience in complex Monorepo and Proxy-wrapped environments.
π Shared Global Registry β
TempoRuntime β single hardened bridge (v3.0+) β
Prior to the v3.x series, Tempo spread its inter-module state across many globalThis[Symbol.for(β¦)] slots ($terms, $extends, $modules, $installed, $reset, $Plugins, $Register). Each slot was a potential tamper target, making the global namespace difficult to audit securely.
As of modern builds, all bookkeeping is consolidated inside a single TempoRuntime object (#tempo/support). The runtime is stored on globalThis under one hardened, highly protected property:
Symbol.for('magmacomputing/tempo/runtime')The property descriptor is enumerable: false, configurable: false, writable: false. External code can neither replace nor delete the runtime.
Benefits:
- Reduced Global Footprint β Consolidation from seven scatter-slots down to a single root.
- Centralized Hardening β Strict input validation (
Tempo.extend) and hook management (setRegisterHook,fireRegisterHook) operate securely from one nexus. - Scoped Runtimes (Experimental) β
TempoRuntime.createScoped()returns a fresh, isolated runtime for clean test isolation withoutglobalThismanipulation. Note: This remains an experimental internal feature and is not yet fully threaded through all core utilities. Unlike the primary runtime, a scoped runtime is not pinned toglobalThis, does not receive the hardeneddefinePropertyprotections, and relies strictly on lexical scoping. - Multi-Bundle / HMR Safety β
getRuntime()checksglobalThis[BRIDGE]before constructing, guaranteeing that two bundle copies of Tempo always share the identical runtime object, thereby resolving complex split-brain states in monorepos.
User-facing "Global Discovery" slots remain on globalThis. The sym.$Tempo slot (and custom discovery symbols passed to Tempo.init) are intentionally exposed for user-readability, remaining ordinary writable properties. Only sensitive internal bookkeeping was moved into the hardened runtime.
To solve the "Split-Brain" issue inherent in monorepo development, Tempo utilizes a Shared Global Registry. By leveraging Symbol.for('magmacomputing/library/registry') on globalThis, all versions of the Tempo and Library packages share a unified type-identification engine. This ensures classes are accurately identified as constructors even when loaded across disparate module boundaries.
π΅οΈ Decoupled Logging β
Tempo utilizes a centralized, functional diagnostic engine (via logError / logWarn utilities) relying on private context to avoid polluting the public console or altering object state. This ensures parsing telemetry never clashes with standard application logic.
- Context-Aware: Logs rigorously track their discovery path (e.g., "Applied via Global Discovery").
- Zero-Footprint: When
debug: 0, the logging overhead is mathematically eliminated. - Symbol-Gated: Diagnostic metadata is attached via private symbol variable directly (e.g.,
config[sym.$LogConfig]), making it invisible to standard iteration (Object.keys) and serialization (JSON.stringify).
π‘οΈ Hardened Functional Resolution β
The engine implements a "Fail-Safe" execution pattern for functional inputs, automatically recovering from misidentified typesβsuch as ES6 classes wrapped in defensive Proxies or circular dependency deadlocks.
- Defensive Execution: All plugin invocations are wrapped in recursive
try/catchexecution blocks. - Silent Failover: When combined with
catch: true, resolution failures safely return a Void Instance, preventing application crashes while surfacing clear diagnostic symbols for debugging.
ποΈ Tempo Architecture: Internal Protection & Performance β
Tempo employs two distinct methodologies for protecting its internal state. These strategies are highly complementary, each meticulously tailored to a specific scope (Instance vs. Global) and performance requirement.
π§ Methodology Comparison β
| Feature | Lazy Evaluation (Shadowing) | Soft Freeze (Proxy) |
|---|---|---|
| Primary Target | Tempo.#term, Tempo.#fmt (Instance State) | NUMBER, FORMAT (Global Registries) |
| Scope | Instance-Specific: Unique to every separate new Tempo() call. | Global-Shared: One single source of truth used by all instances. |
| Primary Goal | Performance: Avoid computing expensive Terms (e.g., qtr or szn) until explicitly requested. | Extensibility: Allow plugins to safely append new data to registries at runtime. |
| Mechanism | Object.create(proto) + Prototype Shadowing. | new Proxy(target) + Symbol-bypass. |
| Why this one? | Memory Efficiency: Thousands of instances share the same base prototype. | Reference Stability: Shared registries must persist at the same object reference. |
β‘ The "Zero-Cost Constructor" Objective β
Tempo is built with a militant "Performance First" mindset, specifically targeting the computational overhead of the class constructor. In high-frequency applications (like Tickers or real-time Dashboards), creating thousands of objects must be nearly as computationally cheap as primitive assignments.
Status: Achieved. We successfully meet the Zero-Cost objective under stable conditions. Benchmarks demonstrate an instantiation overhead of ~523Β΅s, and a fast-fail rejection speed of ~359Β΅s (steady-state results after warm-up on the documented hardware setup).
This objective is achieved through two primary architectural pillars:
- Lazy Evaluation (Section 1): Deferring the computationally expensive work of string parsing and Term calculation until the first strict property access.
- Master Guard (Section 3): Implementing a high-speed "fast-fail" gatekeeper to instantly reject invalid inputs before parsing logic is engaged.
Together, these pillars help ensure that new Tempo() maintains an extremely fast constructor execution time by completely deferring standard parsing workloads. However, note that these costs can depend on input scanning length and registry-mutation-driven wordlist rebuilds, meaning performance is not universally input- or registry-independent.
π Iteration & Enumerability (Delegator Proxies) β
A delegator Proxy is a wrapper whose traps forward operations to an internal target/handler pair. Unlike a standard Proxy, delegation is explicit and tightly routed through an intermediate forwarding layer. In Tempo, the "Generic Lazy Delegator Proxy" handles the public delegation mechanism, while lazy shadowing initializes the private state. These mechanisms coexist: the instance.term / instance.fmt public API employs the delegator Proxy path, and Tempo.#term / Tempo.#fmt private fields are initialized exactly once via lazy shadowing.
β
Object.keys() Behavior β
Object.keys(instance.fmt) and Object.keys(instance.term) return the enumerable own keys strictly registered on each delegator target.
- Proxy Discovery (Definition): This is the proxy-handler phase that enumerates available target keys and installs enumerable lazy getter properties on the proxy target without computing their values.
- Triggered by Enumeration APIs: Discovery executes when enumeration APIs execute, including
Object.keys(instance.fmt),for...in, andReflect.ownKeys(...). - Timing: Discovery happens at enumeration time (before any property
get), establishing key visibility prior to value resolution. - Relation to Section 1: Discovery only registers getters; actual value computation and memoization trigger purely on-demand.
- After Access: Getter access memoizes values directly onto the target object; keys remain highly stable and do not "move" across prototype links.
π‘οΈ Iteration Notes β
Object.keys/for...in/ Object Spread: Operate reliably on enumerable keys exposed by the delegator target after discovery.[Symbol.iterator]: Maintains explicit iterator semantics where fully implemented.Tempo.registry.formats&Tempo.registry.terms: These static getters provide a registry-wide macroscopic view of available keys, entirely independent of per-instance memoization state.
1. Lazy Evaluation (Shadowing) β
Used for: Tempo.#term, Tempo.#fmt
The Instance Shadowing pattern is engineered for massive scale. When a library handles dense operations, creating thousands of new Proxy() objects injects unacceptable memory overhead. Instead, Tempo exploits the native JavaScript prototype chain.
How it works: β
- Stage 0: All instances initially point to the identical base
#termobject containing un-evaluated getters. - Stage 1: When a Term (e.g.,
.qtr) is accessed, the value is computationally evaluated exactly once. - Stage 2: Tempo utilizes a Generic Lazy Delegator Proxy (via
getLazyDelegator) which catches property access and evaluates it strictly on-demand. - Result: The V8 engine executes lookups via an aggressively optimized Proxy handler, making lookups mathematically comparable to raw property access while keeping the state strictly immutable.
TIP
For deeper implementation schematics, see the Lazy Evaluation Pattern.
2. Soft Freeze Strategy (Proxy) β
Used for: Tempo.NUMBER, Tempo.FORMAT, Tempo.TIMEZONE, Tempo.config
Global registries must remain live yet highly secure. As of the modern v3.x series, these are protected by a "Soft Freeze" layer to prevent state corruption or prototype poisoning by third-party code.
How it works: β
- The User: Interacts with a read-only Proxy that strictly behaves like a frozen object. Direct assignments are hard-blocked to prevent poisoning the global state.
- The Library: Utilizes a private symbol bypass to execute "Transactional Updates" natively via
registryUpdate(). - Result: The object reference remains constant while facilitating deeply controlled extensibility. This ensures that internal high-speed caches (like the Master Guard) can be synchronously rebuilt whenever a registry mutates.
TIP
For deeper implementation schematics, see the Soft Freeze Strategy.
β‘ 3. Master Guard (Guarded-Lazy Strategy) β
Used for: new Tempo(string | number)
The Guarded-Lazy strategy ensures that even under the weight of hundreds of custom plugins, the constructor entry point remains near-instantaneous. This logic is decoupled into a high-performance engine.guard.ts module.
How it works: β
- Longest-Token Matching: To prevent fractional matching (e.g., matching
qtrinsidequarter), the guard executes a greedy "Scan-and-Consume" loop that strongly prioritizes the longest available token match. - Unified Wordlist: The guard systematically ingests all registered Terms, Timezones, Month names, and Custom Events into a single
O(1)Set lookup (average token-lookup performance after cache construction). - High-Speed Gatekeeper: By eliminating complex backtracking regular expressions, the gatekeeper provides deterministic
O(1)average lookup performance regardless of the depth of registered plugins. Note that overall validation time is bounded by the string length during the scan-and-consume phase, plus occasionalO(N)cache rebuild costs when the underlying registry mutates. - Versioned Registry: To avoid catastrophic redundant wordlist rebuilding, the Guard strictly monitors a version counter on the alias registry. The wordlist is dynamically rebuilt only when a valid mutation occurs.
- Auto-Lazy: Valid inputs that successfully clear the guard automatically shift the instance to
mode: 'defer', completely deferring the heavyO(N)parsing work until a property is strictly read.
π§© Centralized Alias Management β
Tempo consolidates all Event and Period alias logic into a deeply optimized AliasEngine.
How it works: β
- Hierarchical Registry: Aliases operate in a strict prototype-aware chain. A local
Tempoinstance can deploy its own private aliases that safely shadow global implementations, all while sharing the underlying resolution engines. - Rich Metadata: Every resolution returns a strict
AliasResult, providing the Parser with immediate categorical knowledge of the alias's origin (global vs local), structural type, and clock-snapping requirements. - Clock Snapping: Time-based aliases (e.g.
8:00) are mathematically "snapped" to absolute precision, clearing sub-second drift (ms, us, ns) directly during the resolution phase. - Decoupled Registration: By deprecating legacy raw objects, the modern registry is highly protected against accidental mutation and supports high-efficiency, version-aware monitoring.
π Validation & Performance β
The algorithmic efficiency of the Master Guard and the success of the Zero-Cost objective remain strictly validated via core benchmarking:
- Instantiation Overhead: ~523Β΅s on average (passing the Master Guard). (Node.js v24.14.1, 12th Gen Intel i7-1255U, Linux x86_64; steady-state measured after 1k warm-up runs, n=10k. Validates the Zero-Cost O(1) objective on this hardware.)
- Fast-Fail Rejection: ~359Β΅s on average (failing the Master Guard). (Node.js v24.14.1, 12th Gen Intel i7-1255U, Linux x86_64; steady-state measured after 1k warm-up runs, n=10k. Demonstrates the Master Guard's low-latency rejection performance.)
TIP
For detailed execution timings and methodology, see the Performance Benchmarks.
π Internal Lifecycle & Reactive Sync β
Tempo commands system-wide synchronization through a deeply integrated, Symbol-based hook ecosystem.
Reactive Registration β
When a plugin is imported via a side-effect (import '@magmacomputing/tempo/duration'), it triggers a strict sym.$Register hook.
- Auto-Sync: The
Tempocore listens for these hooks and synchronously updates its internal registries. - Guard Rebuild: Upon any new Term or layout registration, the Master Guard is automatically rebuilt to dynamically ingest the new tokens, ensuring the "Zero-Cost Constructor" remains entirely synchronized with the ecosystem.
Disposable Engine (Symbol.dispose) β
The Tempo class rigorously implements the explicit resource management pattern.
- Clean Slate: Calling
Tempo[Symbol.dispose]()(or utilizing theusingkeyword in a test suite) comprehensively resets all global registries and configuration parameters back to factory defaults. - Isolation: This is mathematically critical for automated testing environments to prevent memory or state-leaks between discrete test cases.
βοΈ Summary β
The Tempo architecture strictly follows the structural principle of "Right Tool for the Job":
- Shadowing provides the extreme performance and mathematical memory efficiency required for per-instance computed state.
- Proxies enforce the strict reference stability and highly controlled extensibility required for global system registries.
- Master Guard algorithmically ensures that even under massive extensibility, the entry point maintains a true "Zero-Cost Constructor".