@quarry-systems/drift-timer 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +308 -0
  2. package/package.json +35 -0
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # MCG Timer Plugin
2
+
3
+ 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.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Simple Delays**: Sleep for a specified duration
8
+ - ✅ **Scheduled Waits**: Wait until a specific date/time
9
+ - ✅ **Cron Patterns**: Daily, weekly, monthly scheduling
10
+ - ✅ **Business Days**: Skip weekends automatically
11
+ - ✅ **Flexible Storage**: Custom paths for timer metadata
12
+ - ✅ **Callbacks**: onStart and onComplete hooks
13
+ - ✅ **Two Usage Modes**: Plugin-based or action-based
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @quarry-systems/drift-timer
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### Plugin-Based Approach
24
+
25
+ ```typescript
26
+ import { ManagedCyclicGraph } from '@quarry-systems/managed-cyclic-graph';
27
+ import { mcgTimerPlugin, sleep, dailyAt } from '@quarry-systems/drift-timer';
28
+
29
+ const graph = new ManagedCyclicGraph()
30
+ .use(mcgTimerPlugin)
31
+
32
+ .node('wait5sec', {
33
+ type: 'timernode',
34
+ meta: {
35
+ timer: sleep(5000) // Wait 5 seconds
36
+ }
37
+ })
38
+
39
+ .node('dailyReport', {
40
+ type: 'timernode',
41
+ meta: {
42
+ timer: dailyAt(9, 0) // Wait until 9:00 AM
43
+ }
44
+ })
45
+
46
+ .build();
47
+ ```
48
+
49
+ ### Action-Based Approach
50
+
51
+ ```typescript
52
+ import { ManagedCyclicGraph } from '@quarry-systems/managed-cyclic-graph';
53
+ import { createTimerAction, sleep, nextBusinessDay } from '@quarry-systems/drift-timer';
54
+
55
+ const graph = new ManagedCyclicGraph()
56
+ .node('processOrder', {
57
+ execute: [
58
+ // ... process order logic
59
+ ]
60
+ })
61
+
62
+ .node('waitForBusinessDay', {
63
+ execute: [
64
+ createTimerAction('waitForBusinessDay', nextBusinessDay(9, 0))
65
+ ]
66
+ })
67
+
68
+ .node('sendReport', {
69
+ execute: [
70
+ // ... send report logic
71
+ ]
72
+ })
73
+
74
+ .build();
75
+ ```
76
+
77
+ ## API Reference
78
+
79
+ ### Helper Functions
80
+
81
+ #### `sleep(ms: number)`
82
+ Sleep for a specified duration in milliseconds.
83
+
84
+ ```typescript
85
+ sleep(5000) // Sleep for 5 seconds
86
+ sleep(60000) // Sleep for 1 minute
87
+ ```
88
+
89
+ #### `waitUntil(date: Date | string | number)`
90
+ Wait until a specific date/time.
91
+
92
+ ```typescript
93
+ waitUntil(new Date('2024-12-25T00:00:00'))
94
+ waitUntil('2024-12-25T00:00:00')
95
+ waitUntil(Date.now() + 3600000) // 1 hour from now
96
+ ```
97
+
98
+ #### `dailyAt(hour: number, minute?: number)`
99
+ Wait until the next occurrence of a specific time each day.
100
+
101
+ ```typescript
102
+ dailyAt(9, 0) // Wait until 9:00 AM
103
+ dailyAt(17, 30) // Wait until 5:30 PM
104
+ ```
105
+
106
+ #### `weeklyAt(dayOfWeek: number, hour: number, minute?: number)`
107
+ Wait until the next occurrence of a specific day and time each week.
108
+
109
+ ```typescript
110
+ weeklyAt(1, 9, 0) // Monday at 9:00 AM (0=Sunday, 1=Monday, ...)
111
+ weeklyAt(5, 17, 0) // Friday at 5:00 PM
112
+ ```
113
+
114
+ #### `nextBusinessDay(hour?: number, minute?: number)`
115
+ Wait until the next business day (skips weekends) at the specified time.
116
+
117
+ ```typescript
118
+ nextBusinessDay() // Next business day at midnight
119
+ nextBusinessDay(9, 0) // Next business day at 9:00 AM
120
+ nextBusinessDay(8, 30) // Next business day at 8:30 AM
121
+ ```
122
+
123
+ ### Configuration Options
124
+
125
+ ```typescript
126
+ interface TimerConfig {
127
+ sleepMs?: number; // Sleep duration in milliseconds
128
+ waitUntil?: Date | string | number; // Target date/time
129
+ cronPattern?: CronPattern; // Cron-like scheduling
130
+ storePath?: string; // Custom storage path
131
+ onStart?: (ctx) => void; // Callback when timer starts
132
+ onComplete?: (ctx) => void; // Callback when timer completes
133
+ }
134
+ ```
135
+
136
+ ### Cron Pattern Options
137
+
138
+ ```typescript
139
+ interface CronPattern {
140
+ type: 'daily' | 'weekly' | 'monthly' | 'custom';
141
+ hour?: number; // Hour (0-23)
142
+ minute?: number; // Minute (0-59)
143
+ dayOfWeek?: number; // Day of week (0-6, Sunday=0)
144
+ dayOfMonth?: number; // Day of month (1-31)
145
+ skipWeekends?: boolean; // Skip Saturday/Sunday
146
+ expression?: string; // Custom cron expression (future)
147
+ }
148
+ ```
149
+
150
+ ## Examples
151
+
152
+ ### Retry with Exponential Backoff
153
+
154
+ ```typescript
155
+ const graph = new ManagedCyclicGraph()
156
+ .use(mcgTimerPlugin)
157
+
158
+ .node('attempt1', {
159
+ execute: [/* try operation */]
160
+ })
161
+
162
+ .node('wait1', {
163
+ type: 'timernode',
164
+ meta: { timer: sleep(1000) } // Wait 1 second
165
+ })
166
+
167
+ .node('attempt2', {
168
+ execute: [/* retry operation */]
169
+ })
170
+
171
+ .node('wait2', {
172
+ type: 'timernode',
173
+ meta: { timer: sleep(2000) } // Wait 2 seconds
174
+ })
175
+
176
+ .node('attempt3', {
177
+ execute: [/* final retry */]
178
+ })
179
+
180
+ .build();
181
+ ```
182
+
183
+ ### Daily Report Generation
184
+
185
+ ```typescript
186
+ const graph = new ManagedCyclicGraph()
187
+ .use(mcgTimerPlugin)
188
+
189
+ .node('waitForMorning', {
190
+ type: 'timernode',
191
+ meta: {
192
+ timer: dailyAt(8, 0) // Every day at 8:00 AM
193
+ }
194
+ })
195
+
196
+ .node('generateReport', {
197
+ execute: [/* generate report */]
198
+ })
199
+
200
+ .node('sendReport', {
201
+ execute: [/* send report */]
202
+ })
203
+
204
+ // Loop back to wait for next day
205
+ .edge('sendReport', 'waitForMorning', 'any')
206
+
207
+ .build();
208
+ ```
209
+
210
+ ### Weekend-Aware Processing
211
+
212
+ ```typescript
213
+ const graph = new ManagedCyclicGraph()
214
+ .use(mcgTimerPlugin)
215
+
216
+ .node('checkData', {
217
+ execute: [/* check for new data */]
218
+ })
219
+
220
+ .node('waitForBusinessDay', {
221
+ type: 'timernode',
222
+ meta: {
223
+ timer: nextBusinessDay(9, 0)
224
+ }
225
+ })
226
+
227
+ .node('processData', {
228
+ execute: [/* process during business hours */]
229
+ })
230
+
231
+ .build();
232
+ ```
233
+
234
+ ### With Callbacks
235
+
236
+ ```typescript
237
+ const graph = new ManagedCyclicGraph()
238
+ .use(mcgTimerPlugin)
239
+
240
+ .node('scheduledTask', {
241
+ type: 'timernode',
242
+ meta: {
243
+ timer: {
244
+ ...dailyAt(10, 0),
245
+ onStart: (ctx) => {
246
+ console.log('Timer started, waiting until 10:00 AM');
247
+ },
248
+ onComplete: (ctx) => {
249
+ console.log('Timer completed, executing task now');
250
+ }
251
+ }
252
+ }
253
+ })
254
+
255
+ .build();
256
+ ```
257
+
258
+ ## Metadata Storage
259
+
260
+ Timer metadata is stored in the context at `data.timer.{nodeId}` by default:
261
+
262
+ ```typescript
263
+ {
264
+ data: {
265
+ timer: {
266
+ wait5sec: {
267
+ startTime: 1701234567890,
268
+ targetTime: 1701234572890,
269
+ duration: 5000,
270
+ completed: true
271
+ }
272
+ }
273
+ }
274
+ }
275
+ ```
276
+
277
+ You can customize the storage path:
278
+
279
+ ```typescript
280
+ {
281
+ timer: {
282
+ ...sleep(5000),
283
+ storePath: 'data.customPath.myTimer'
284
+ }
285
+ }
286
+ ```
287
+
288
+ ## Use Cases
289
+
290
+ - **Rate Limiting**: Add delays between API calls
291
+ - **Retry Logic**: Wait before retrying failed operations
292
+ - **Scheduled Tasks**: Run tasks at specific times
293
+ - **Business Hours**: Ensure operations run during business days
294
+ - **Cooldown Periods**: Enforce waiting periods between actions
295
+ - **Batch Processing**: Wait for batch windows
296
+ - **Compliance**: Respect time-based regulations
297
+
298
+ ## Best Practices
299
+
300
+ 1. **Use Business Day Scheduling** for operations that should only run during work hours
301
+ 2. **Add Callbacks** for logging and monitoring timer events
302
+ 3. **Store Metadata** in custom paths when you need to track multiple timers
303
+ 4. **Combine with Guards** to create conditional timing logic
304
+ 5. **Use Action-Based** approach when mixing timers with other actions
305
+
306
+ ## License
307
+
308
+ ISC
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@quarry-systems/drift-timer",
3
+ "version": "0.1.0-alpha.1",
4
+ "description": "Timer and scheduling plugin for Drift",
5
+ "main": "./src/index.js",
6
+ "types": "./src/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc -p .",
9
+ "clean": "rimraf dist || rm -rf dist",
10
+ "dev": "tsc -p . --watch",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest"
13
+ },
14
+ "keywords": [
15
+ "drift",
16
+ "plugin",
17
+ "timer",
18
+ "delay",
19
+ "schedule",
20
+ "cron"
21
+ ],
22
+ "author": "Brett Nye",
23
+ "license": "ISC",
24
+ "devDependencies": {
25
+ "typescript": "^5.0.0",
26
+ "vitest": "^2.1.0"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE.md",
32
+ "CHANGELOG.md"
33
+ ],
34
+ "type": "commonjs"
35
+ }