@quarry-systems/drift-timer
v0.1.0-alpha.1
Published
Timer and scheduling plugin for Drift
Downloads
211
Maintainers
Readme
MCG Timer Plugin
A comprehensive timer and scheduling plugin for Managed Cyclic Graph (MCG) that enables nodes to delay execution, wait for specific times, and schedule based on cron-like patterns.
Features
- ✅ Simple Delays: Sleep for a specified duration
- ✅ Scheduled Waits: Wait until a specific date/time
- ✅ Cron Patterns: Daily, weekly, monthly scheduling
- ✅ Business Days: Skip weekends automatically
- ✅ Flexible Storage: Custom paths for timer metadata
- ✅ Callbacks: onStart and onComplete hooks
- ✅ Two Usage Modes: Plugin-based or action-based
Installation
npm install @quarry-systems/drift-timerQuick Start
Plugin-Based Approach
import { ManagedCyclicGraph } from '@quarry-systems/managed-cyclic-graph';
import { mcgTimerPlugin, sleep, dailyAt } from '@quarry-systems/drift-timer';
const graph = new ManagedCyclicGraph()
.use(mcgTimerPlugin)
.node('wait5sec', {
type: 'timernode',
meta: {
timer: sleep(5000) // Wait 5 seconds
}
})
.node('dailyReport', {
type: 'timernode',
meta: {
timer: dailyAt(9, 0) // Wait until 9:00 AM
}
})
.build();Action-Based Approach
import { ManagedCyclicGraph } from '@quarry-systems/managed-cyclic-graph';
import { createTimerAction, sleep, nextBusinessDay } from '@quarry-systems/drift-timer';
const graph = new ManagedCyclicGraph()
.node('processOrder', {
execute: [
// ... process order logic
]
})
.node('waitForBusinessDay', {
execute: [
createTimerAction('waitForBusinessDay', nextBusinessDay(9, 0))
]
})
.node('sendReport', {
execute: [
// ... send report logic
]
})
.build();API Reference
Helper Functions
sleep(ms: number)
Sleep for a specified duration in milliseconds.
sleep(5000) // Sleep for 5 seconds
sleep(60000) // Sleep for 1 minutewaitUntil(date: Date | string | number)
Wait until a specific date/time.
waitUntil(new Date('2024-12-25T00:00:00'))
waitUntil('2024-12-25T00:00:00')
waitUntil(Date.now() + 3600000) // 1 hour from nowdailyAt(hour: number, minute?: number)
Wait until the next occurrence of a specific time each day.
dailyAt(9, 0) // Wait until 9:00 AM
dailyAt(17, 30) // Wait until 5:30 PMweeklyAt(dayOfWeek: number, hour: number, minute?: number)
Wait until the next occurrence of a specific day and time each week.
weeklyAt(1, 9, 0) // Monday at 9:00 AM (0=Sunday, 1=Monday, ...)
weeklyAt(5, 17, 0) // Friday at 5:00 PMnextBusinessDay(hour?: number, minute?: number)
Wait until the next business day (skips weekends) at the specified time.
nextBusinessDay() // Next business day at midnight
nextBusinessDay(9, 0) // Next business day at 9:00 AM
nextBusinessDay(8, 30) // Next business day at 8:30 AMConfiguration Options
interface TimerConfig {
sleepMs?: number; // Sleep duration in milliseconds
waitUntil?: Date | string | number; // Target date/time
cronPattern?: CronPattern; // Cron-like scheduling
storePath?: string; // Custom storage path
onStart?: (ctx) => void; // Callback when timer starts
onComplete?: (ctx) => void; // Callback when timer completes
}Cron Pattern Options
interface CronPattern {
type: 'daily' | 'weekly' | 'monthly' | 'custom';
hour?: number; // Hour (0-23)
minute?: number; // Minute (0-59)
dayOfWeek?: number; // Day of week (0-6, Sunday=0)
dayOfMonth?: number; // Day of month (1-31)
skipWeekends?: boolean; // Skip Saturday/Sunday
expression?: string; // Custom cron expression (future)
}Examples
Retry with Exponential Backoff
const graph = new ManagedCyclicGraph()
.use(mcgTimerPlugin)
.node('attempt1', {
execute: [/* try operation */]
})
.node('wait1', {
type: 'timernode',
meta: { timer: sleep(1000) } // Wait 1 second
})
.node('attempt2', {
execute: [/* retry operation */]
})
.node('wait2', {
type: 'timernode',
meta: { timer: sleep(2000) } // Wait 2 seconds
})
.node('attempt3', {
execute: [/* final retry */]
})
.build();Daily Report Generation
const graph = new ManagedCyclicGraph()
.use(mcgTimerPlugin)
.node('waitForMorning', {
type: 'timernode',
meta: {
timer: dailyAt(8, 0) // Every day at 8:00 AM
}
})
.node('generateReport', {
execute: [/* generate report */]
})
.node('sendReport', {
execute: [/* send report */]
})
// Loop back to wait for next day
.edge('sendReport', 'waitForMorning', 'any')
.build();Weekend-Aware Processing
const graph = new ManagedCyclicGraph()
.use(mcgTimerPlugin)
.node('checkData', {
execute: [/* check for new data */]
})
.node('waitForBusinessDay', {
type: 'timernode',
meta: {
timer: nextBusinessDay(9, 0)
}
})
.node('processData', {
execute: [/* process during business hours */]
})
.build();With Callbacks
const graph = new ManagedCyclicGraph()
.use(mcgTimerPlugin)
.node('scheduledTask', {
type: 'timernode',
meta: {
timer: {
...dailyAt(10, 0),
onStart: (ctx) => {
console.log('Timer started, waiting until 10:00 AM');
},
onComplete: (ctx) => {
console.log('Timer completed, executing task now');
}
}
}
})
.build();Metadata Storage
Timer metadata is stored in the context at data.timer.{nodeId} by default:
{
data: {
timer: {
wait5sec: {
startTime: 1701234567890,
targetTime: 1701234572890,
duration: 5000,
completed: true
}
}
}
}You can customize the storage path:
{
timer: {
...sleep(5000),
storePath: 'data.customPath.myTimer'
}
}Use Cases
- Rate Limiting: Add delays between API calls
- Retry Logic: Wait before retrying failed operations
- Scheduled Tasks: Run tasks at specific times
- Business Hours: Ensure operations run during business days
- Cooldown Periods: Enforce waiting periods between actions
- Batch Processing: Wait for batch windows
- Compliance: Respect time-based regulations
Best Practices
- Use Business Day Scheduling for operations that should only run during work hours
- Add Callbacks for logging and monitoring timer events
- Store Metadata in custom paths when you need to track multiple timers
- Combine with Guards to create conditional timing logic
- Use Action-Based approach when mixing timers with other actions
License
ISC
