@magmacomputing/tempo-plugin-ticker
A high-performance Community plugin for the Tempo ecosystem providing temporal continuous execution loops, best-effort scheduling with millisecond resolution, explicit resource management disposers (using / await using), async generator streams, and multi-clock synchronization.
Unlike raw setInterval, Tempo Ticker handles calendar arithmetic, month-length adjustments, daylight saving shifts, recurrence rules, and cron schedules with zero timer drift.
Key Features
- Zero-Drift Scheduling: Calendar-aware intervals with month-length adjustments, DST shift correction, and cron/RRULE recurrence.
- Explicit Resource Management: First-class
using/await usingdisposer support (Symbol.dispose/Symbol.asyncDispose) for leak-free scoped lifecycles. - Async Generator Streams:
for await (const t of ticker)streaming loop support for reactive pipelines and telemetry. - Rich Event Listeners:
.on('pulse'),.on('stop'),.on('catch')hooks for fine-grained control and error isolation. - Registry Diagnostics:
Ticker.activesnapshot of all running tickers for health monitoring. - Multi-Clock Synchronization: Synchronize multiple tickers to shared NTP-corrected clocks via
@magmacomputing/tempo-plugin-ntp.
Installation
bash
npm install @magmacomputing/tempo-plugin-tickerQuickstart
Interactive Demo (@magmacomputing/tempo-plugin-ticker)
Open in Full REPL↗// ⏰ Continuous Temporal Ticker Demo (@magmacomputing/tempo-plugin-ticker)
const { TickerPlugin } = await import('@magmacomputing/tempo-plugin-ticker');
Tempo.use(TickerPlugin);
console.log('Starting 1-second cadence ticker...');
let count = 0;
const ticker = Tempo.ticker({ seconds: 1 }, (t, stop) => {
count++;
console.log(`Tick #${count}:`, t.format('{hh}:{mi}:{ss}'));
if (count >= 3) {
console.log('Ticker stopped after 3 ticks.');
stop();
}
});
return 'Ticker started (executes in console stream)';typescript
import { Tempo } from '@magmacomputing/tempo';
import '@magmacomputing/tempo-plugin-ticker/install';
{
await using ticker = Tempo.ticker({ seconds: 1 }, (t) => {
console.log('Tick:', t.format('{hh}:{mi}:{ss}'));
});
// Keep scope alive to observe repeated ticks
await new Promise((resolve) => setTimeout(resolve, 2500));
} // ⚡ Cleaned up automatically upon leaving scopeAuto-Installation (Side-Effect Import)
typescript
import { Tempo } from '@magmacomputing/tempo';
import '@magmacomputing/tempo-plugin-ticker/install';
const ticker = Tempo.ticker({ seconds: 1 });Plugin Registration
typescript
import { Tempo } from '@magmacomputing/tempo';
import { TickerPlugin } from '@magmacomputing/tempo-plugin-ticker';
Tempo.use(TickerPlugin);Async Generator Stream
typescript
async function streamClock() {
await using ticker = Tempo.ticker({ seconds: 1 });
let count = 0;
for await (const t of ticker) {
console.log('Stream tick:', t.iso);
if (++count >= 5) break;
}
}API Reference
Creation: Tempo.ticker(intervalOrOptions?, callback?)
| Parameter | Type | Description |
|---|---|---|
intervalOrOptions | Ticker.Interval | Ticker.Options | Number of seconds, cron expression, RRULE string, calendar term, or comprehensive options object. |
callback | (t: Tempo, stop: () => void) => void | Optional pulse callback. |
Ticker.Options Configuration
| Option | Type | Default | Description |
|---|---|---|---|
seconds / ss | number | 1 | Seconds interval step. Negative values count backwards. |
minutes / mi | number | — | Minutes interval step. |
hours / hh | number | — | Hours interval step. |
days / dd | number | — | Days interval step. |
months / mm | number | — | Calendar months interval step. |
years / yy | number | — | Years interval step. |
cron | string | — | Standard 5-field cron expression (e.g. '*/15 * * * *'). |
rrule | string | — | Standard RFC 5545 iCalendar recurrence rule string. |
seed | string | Date | Tempo | Current time | Initial timestamp or starting point for virtual clocks and countdowns. |
until | string | Date | Tempo | — | Inclusive termination boundary. |
limit | number | — | Maximum pulse count before automatic shutdown (limit: 0 stops immediately). |
label | string | — | Descriptive label visible in Ticker.active telemetry. |
TickerInstance Object
| Method / Property | Return Type | Description |
|---|---|---|
ticker.stop() | void | Stops the ticker, clears active timers, and finalizes pending async iterators. |
ticker.pulse() | Tempo | Manually triggers a pulse, advances state, and notifies listeners. |
ticker.info | object | Telemetry snapshot: { next, ticks, limit, interval, stopped }. |
ticker.on(event, cb) | this | Registers listeners for 'pulse', 'stop', or 'catch'. |
[Symbol.dispose] | void | Synchronous disposer hook for using blocks. |
[Symbol.asyncDispose] | Promise<void> | Asynchronous disposer hook for await using blocks. |
[Symbol.asyncIterator] | AsyncGenerator<Tempo> | Streaming generator support for for await (const t of ticker) loops. |
Static Ticker Namespace
| Property | Return Type | Description |
|---|---|---|
Ticker.active | Snapshot[] | Returns an array of snapshots for all currently running (non-stopped) Tickers. |
Topic Guides
Explore detailed guides on specific capabilities:
- Intervals & Scheduling Engines: Semantic durations (
{ months: 1 }), calendar terms (#timeOfDay), 5-field Cron expressions (0 9 * * 1-5), RFC 5545 RRULE, countdowns, and one-shot meeting alerts. - Resource Management & Lifecycle: Explicit resource management (
using/await using), async generators (for await), programmatic controls (stop,info,pulse), limits, and zombie process prevention. - Event Streams & Reactive Clocks: Event listeners (
.on('pulse'),.on('stop'),.on('catch')), registry diagnostics (Ticker.active), and zero-drift multi-timezone dashboards with UI signals. - Production Use Cases & Architectural Patterns: Zero-drift telemetry heartbeats, leak prevention via
using, streaming market tick generators, multi-timezone cron schedules, and laptop sleep recovery.
License
This is a Community plugin. It is completely free and open-source for personal and commercial use under the MIT license.