Skip to content

Tempo Plugin

@magmacomputing/tempo-plugin-ticker ​

npm version npm peer dependency version License TypeScript Ready

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 using disposer 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.active snapshot 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-ticker

Quickstart ​

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)';
Executes 100% in browser via native ESM sandbox
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 scope

Auto-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?) ​

ParameterTypeDescription
intervalOrOptionsTicker.Interval | Ticker.OptionsNumber of seconds, cron expression, RRULE string, calendar term, or comprehensive options object.
callback(t: Tempo, stop: () => void) => voidOptional pulse callback.

Ticker.Options Configuration ​

OptionTypeDefaultDescription
seconds / ssnumber1Seconds interval step. Negative values count backwards.
minutes / minumber—Minutes interval step.
hours / hhnumber—Hours interval step.
days / ddnumber—Days interval step.
months / mmnumber—Calendar months interval step.
years / yynumber—Years interval step.
cronstring—Standard 5-field cron expression (e.g. '*/15 * * * *').
rrulestring—Standard RFC 5545 iCalendar recurrence rule string.
seedstring | Date | TempoCurrent timeInitial timestamp or starting point for virtual clocks and countdowns.
untilstring | Date | Tempo—Inclusive termination boundary.
limitnumber—Maximum pulse count before automatic shutdown (limit: 0 stops immediately).
labelstring—Descriptive label visible in Ticker.active telemetry.

TickerInstance Object ​

Method / PropertyReturn TypeDescription
ticker.stop()voidStops the ticker, clears active timers, and finalizes pending async iterators.
ticker.pulse()TempoManually triggers a pulse, advances state, and notifies listeners.
ticker.infoobjectTelemetry snapshot: { next, ticks, limit, interval, stopped }.
ticker.on(event, cb)thisRegisters listeners for 'pulse', 'stop', or 'catch'.
[Symbol.dispose]voidSynchronous 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 ​

PropertyReturn TypeDescription
Ticker.activeSnapshot[]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.

Released under the MIT License.