@orgloop/core 0.1.5 → 0.1.7

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 (45) hide show
  1. package/README.md +51 -17
  2. package/dist/engine.d.ts +12 -26
  3. package/dist/engine.d.ts.map +1 -1
  4. package/dist/engine.js +61 -448
  5. package/dist/engine.js.map +1 -1
  6. package/dist/errors.d.ts +11 -0
  7. package/dist/errors.d.ts.map +1 -1
  8. package/dist/errors.js +22 -0
  9. package/dist/errors.js.map +1 -1
  10. package/dist/http.d.ts +19 -1
  11. package/dist/http.d.ts.map +1 -1
  12. package/dist/http.js +114 -2
  13. package/dist/http.js.map +1 -1
  14. package/dist/index.d.ts +9 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/logger.d.ts +5 -1
  19. package/dist/logger.d.ts.map +1 -1
  20. package/dist/logger.js +15 -5
  21. package/dist/logger.js.map +1 -1
  22. package/dist/module-instance.d.ts +76 -0
  23. package/dist/module-instance.d.ts.map +1 -0
  24. package/dist/module-instance.js +185 -0
  25. package/dist/module-instance.js.map +1 -0
  26. package/dist/prompt.d.ts +20 -0
  27. package/dist/prompt.d.ts.map +1 -0
  28. package/dist/prompt.js +35 -0
  29. package/dist/prompt.js.map +1 -0
  30. package/dist/registry.d.ts +23 -0
  31. package/dist/registry.d.ts.map +1 -0
  32. package/dist/registry.js +42 -0
  33. package/dist/registry.js.map +1 -0
  34. package/dist/runtime.d.ts +81 -0
  35. package/dist/runtime.d.ts.map +1 -0
  36. package/dist/runtime.js +522 -0
  37. package/dist/runtime.js.map +1 -0
  38. package/dist/scheduler.d.ts +11 -2
  39. package/dist/scheduler.d.ts.map +1 -1
  40. package/dist/scheduler.js +44 -6
  41. package/dist/scheduler.js.map +1 -1
  42. package/dist/transform.d.ts.map +1 -1
  43. package/dist/transform.js +45 -18
  44. package/dist/transform.js.map +1 -1
  45. package/package.json +2 -2
@@ -0,0 +1,522 @@
1
+ /**
2
+ * Runtime — the long-lived host process.
3
+ *
4
+ * Owns shared infrastructure (bus, scheduler, logger, webhook server)
5
+ * and manages modules through a registry. Modules are loaded/unloaded
6
+ * independently without affecting each other.
7
+ */
8
+ import { EventEmitter } from 'node:events';
9
+ import { readFile } from 'node:fs/promises';
10
+ import { generateTraceId } from '@orgloop/sdk';
11
+ import { InMemoryBus } from './bus.js';
12
+ import { ConnectorError, DeliveryError, ModuleNotFoundError, RuntimeError } from './errors.js';
13
+ import { DEFAULT_HTTP_PORT, WebhookServer } from './http.js';
14
+ import { LoggerManager } from './logger.js';
15
+ import { ModuleInstance } from './module-instance.js';
16
+ import { stripFrontMatter } from './prompt.js';
17
+ import { ModuleRegistry } from './registry.js';
18
+ import { matchRoutes } from './router.js';
19
+ import { Scheduler } from './scheduler.js';
20
+ import { InMemoryCheckpointStore } from './store.js';
21
+ import { executeTransformPipeline } from './transform.js';
22
+ // ─── Runtime Class ───────────────────────────────────────────────────────────
23
+ class Runtime extends EventEmitter {
24
+ // Shared infrastructure
25
+ bus;
26
+ scheduler = new Scheduler();
27
+ loggerManager;
28
+ registry = new ModuleRegistry();
29
+ webhookServer;
30
+ // Running state
31
+ running = false;
32
+ httpStarted = false;
33
+ startedAt = 0;
34
+ httpPort;
35
+ dataDir;
36
+ // Circuit breaker
37
+ circuitBreakerOpts;
38
+ circuitRetryTimers = new Map();
39
+ // Stored configs for reload
40
+ moduleConfigs = new Map();
41
+ moduleLoadOptions = new Map();
42
+ constructor(options) {
43
+ super();
44
+ this.bus = options?.bus ?? new InMemoryBus();
45
+ this.loggerManager = options?.loggerManager ?? new LoggerManager();
46
+ this.httpPort =
47
+ options?.httpPort ??
48
+ (process.env.ORGLOOP_PORT
49
+ ? Number.parseInt(process.env.ORGLOOP_PORT, 10)
50
+ : DEFAULT_HTTP_PORT);
51
+ this.dataDir = options?.dataDir;
52
+ this.circuitBreakerOpts = {
53
+ failureThreshold: options?.circuitBreaker?.failureThreshold ?? 5,
54
+ retryAfterMs: options?.circuitBreaker?.retryAfterMs ?? 60_000,
55
+ };
56
+ this.webhookServer = new WebhookServer((event) => this.inject(event));
57
+ }
58
+ // ─── Lifecycle ───────────────────────────────────────────────────────────
59
+ async start() {
60
+ if (this.running)
61
+ return;
62
+ // Start scheduler
63
+ this.scheduler.start((sourceId, moduleName) => this.pollSource(sourceId, moduleName));
64
+ this.running = true;
65
+ this.startedAt = Date.now();
66
+ await this.emitLog('runtime.start', { result: 'started' });
67
+ }
68
+ /** Start the HTTP server for webhooks and control API. */
69
+ async startHttpServer() {
70
+ if (this.httpStarted)
71
+ return;
72
+ this.webhookServer.runtime = this;
73
+ await this.webhookServer.start(this.httpPort);
74
+ this.httpStarted = true;
75
+ }
76
+ /** Whether the HTTP server is currently running. */
77
+ isHttpStarted() {
78
+ return this.httpStarted;
79
+ }
80
+ async stop() {
81
+ if (!this.running)
82
+ return;
83
+ await this.emitLog('runtime.stop', { result: 'stopping' });
84
+ // Deactivate and shutdown all modules
85
+ for (const mod of this.registry.list()) {
86
+ try {
87
+ mod.deactivate();
88
+ this.scheduler.removeSources(mod.name);
89
+ await mod.shutdown();
90
+ }
91
+ catch {
92
+ // Non-blocking
93
+ }
94
+ }
95
+ // Stop webhook server
96
+ if (this.httpStarted) {
97
+ await this.webhookServer.stop();
98
+ this.httpStarted = false;
99
+ }
100
+ // Stop scheduler
101
+ this.scheduler.stop();
102
+ // Clear circuit breaker timers
103
+ for (const timer of this.circuitRetryTimers.values()) {
104
+ clearTimeout(timer);
105
+ }
106
+ this.circuitRetryTimers.clear();
107
+ // Flush and shutdown loggers
108
+ await this.loggerManager.flush();
109
+ await this.loggerManager.shutdown();
110
+ this.running = false;
111
+ }
112
+ // ─── Module Management ───────────────────────────────────────────────────
113
+ async loadModule(config, options) {
114
+ const checkpointStore = options?.checkpointStore ?? new InMemoryCheckpointStore();
115
+ const mod = new ModuleInstance(config, {
116
+ sources: options?.sources ?? new Map(),
117
+ actors: options?.actors ?? new Map(),
118
+ transforms: options?.transforms ?? new Map(),
119
+ loggers: options?.loggers ?? new Map(),
120
+ checkpointStore,
121
+ });
122
+ // Initialize all connectors
123
+ await mod.initialize();
124
+ // Activate and register before adding to scheduler
125
+ // (so the first poll finds the module in the registry)
126
+ mod.activate();
127
+ this.registry.register(mod);
128
+ // Add module loggers to shared LoggerManager (tagged with module name)
129
+ for (const [, logger] of mod.getLoggers()) {
130
+ this.loggerManager.addLogger(logger, mod.name);
131
+ }
132
+ // Register poll sources with shared scheduler
133
+ const defaultInterval = config.defaults?.poll_interval ?? '5m';
134
+ let hasWebhooks = false;
135
+ for (const srcCfg of config.sources) {
136
+ const connector = mod.getSource(srcCfg.id);
137
+ if (!connector)
138
+ continue;
139
+ if (typeof connector.webhook === 'function') {
140
+ // Webhook-based source: register with shared server
141
+ this.webhookServer.addHandler(srcCfg.id, connector.webhook());
142
+ hasWebhooks = true;
143
+ }
144
+ else {
145
+ // Poll-based source: register with shared scheduler
146
+ const interval = srcCfg.poll?.interval ?? defaultInterval;
147
+ this.scheduler.addSource(srcCfg.id, interval, mod.name);
148
+ }
149
+ }
150
+ // Start HTTP server on demand when webhook sources are present
151
+ if (hasWebhooks && !this.httpStarted) {
152
+ await this.startHttpServer();
153
+ }
154
+ // Store config and options for reload
155
+ this.moduleConfigs.set(config.name, config);
156
+ if (options) {
157
+ this.moduleLoadOptions.set(config.name, options);
158
+ }
159
+ await this.emitLog('module.active', {
160
+ result: `module "${config.name}" loaded`,
161
+ module: config.name,
162
+ });
163
+ return mod.status();
164
+ }
165
+ async unloadModule(name) {
166
+ const mod = this.registry.get(name);
167
+ if (!mod) {
168
+ throw new ModuleNotFoundError(name);
169
+ }
170
+ await this.emitLog('module.unloading', {
171
+ result: `unloading module "${name}"`,
172
+ module: name,
173
+ });
174
+ // Deactivate
175
+ mod.deactivate();
176
+ // Remove sources from scheduler
177
+ this.scheduler.removeSources(name);
178
+ // Remove webhook handlers for module sources
179
+ for (const srcCfg of mod.config.sources) {
180
+ this.webhookServer.removeHandler(srcCfg.id);
181
+ }
182
+ // Shutdown module resources
183
+ await mod.shutdown();
184
+ // Remove loggers by module tag
185
+ this.loggerManager.removeLoggersByTag(name);
186
+ // Unregister from registry
187
+ this.registry.unregister(name);
188
+ // Clean stored config
189
+ this.moduleConfigs.delete(name);
190
+ this.moduleLoadOptions.delete(name);
191
+ await this.emitLog('module.removed', {
192
+ result: `module "${name}" removed`,
193
+ module: name,
194
+ });
195
+ }
196
+ async reloadModule(name) {
197
+ const config = this.moduleConfigs.get(name);
198
+ if (!config) {
199
+ throw new ModuleNotFoundError(name);
200
+ }
201
+ const options = this.moduleLoadOptions.get(name);
202
+ await this.unloadModule(name);
203
+ await this.loadModule(config, options);
204
+ }
205
+ // ─── Event Processing ────────────────────────────────────────────────────
206
+ async inject(event, moduleName) {
207
+ const resolved = event.trace_id ? event : { ...event, trace_id: generateTraceId() };
208
+ if (moduleName) {
209
+ const mod = this.registry.get(moduleName);
210
+ if (!mod) {
211
+ throw new ModuleNotFoundError(moduleName);
212
+ }
213
+ await this.processEvent(resolved, mod);
214
+ }
215
+ else {
216
+ // Process through all active modules
217
+ for (const mod of this.registry.list()) {
218
+ if (mod.getState() === 'active') {
219
+ await this.processEvent(resolved, mod);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ async processEvent(event, mod) {
225
+ this.emit('event', event);
226
+ await this.emitLog('source.emit', {
227
+ event_id: event.id,
228
+ trace_id: event.trace_id,
229
+ source: event.source,
230
+ event_type: event.type,
231
+ module: mod.name,
232
+ });
233
+ // Write to bus (WAL)
234
+ await this.bus.publish(event);
235
+ // Match routes from this module
236
+ const matched = matchRoutes(event, mod.getRoutes());
237
+ if (matched.length === 0) {
238
+ await this.emitLog('route.no_match', {
239
+ event_id: event.id,
240
+ trace_id: event.trace_id,
241
+ source: event.source,
242
+ module: mod.name,
243
+ });
244
+ await this.bus.ack(event.id);
245
+ return;
246
+ }
247
+ // Process each matched route
248
+ for (const match of matched) {
249
+ const { route } = match;
250
+ await this.emitLog('route.match', {
251
+ event_id: event.id,
252
+ trace_id: event.trace_id,
253
+ route: route.name,
254
+ source: event.source,
255
+ target: route.then.actor,
256
+ module: mod.name,
257
+ });
258
+ // Run transform pipeline
259
+ let transformedEvent = event;
260
+ if (route.transforms && route.transforms.length > 0) {
261
+ const pipelineOptions = {
262
+ definitions: mod.config.transforms,
263
+ packageTransforms: mod.getTransformsMap(),
264
+ onLog: (partial) => {
265
+ void this.emitLog(partial.phase ?? 'transform.start', {
266
+ ...partial,
267
+ event_id: partial.event_id ?? event.id,
268
+ trace_id: partial.trace_id ?? event.trace_id,
269
+ route: route.name,
270
+ module: mod.name,
271
+ });
272
+ },
273
+ };
274
+ const context = {
275
+ source: event.source,
276
+ target: route.then.actor,
277
+ eventType: event.type,
278
+ routeName: route.name,
279
+ };
280
+ try {
281
+ const result = await executeTransformPipeline(event, context, route.transforms, pipelineOptions);
282
+ if (result.dropped || !result.event) {
283
+ continue; // Skip delivery for this route
284
+ }
285
+ transformedEvent = result.event;
286
+ }
287
+ catch (err) {
288
+ // halt policy throws TransformError — emit error and skip delivery
289
+ this.emit('error', err);
290
+ continue;
291
+ }
292
+ }
293
+ // Deliver to actor
294
+ await this.deliverToActor(transformedEvent, route.name, route.then.actor, route, mod);
295
+ }
296
+ // Ack the event after all routes processed
297
+ await this.bus.ack(event.id);
298
+ }
299
+ async deliverToActor(event, routeName, actorId, route, mod) {
300
+ const actor = mod.getActor(actorId);
301
+ if (!actor) {
302
+ const error = new DeliveryError(actorId, routeName, `Actor "${actorId}" not found`);
303
+ this.emit('error', error);
304
+ return;
305
+ }
306
+ await this.emitLog('deliver.attempt', {
307
+ event_id: event.id,
308
+ trace_id: event.trace_id,
309
+ route: routeName,
310
+ target: actorId,
311
+ module: mod.name,
312
+ });
313
+ const startTime = Date.now();
314
+ try {
315
+ // Build delivery config
316
+ const deliveryConfig = {
317
+ ...(route.then.config ?? {}),
318
+ };
319
+ // Resolve launch prompt if configured
320
+ if (route.with?.prompt_file) {
321
+ try {
322
+ const promptContent = await readFile(route.with.prompt_file, 'utf-8');
323
+ const { content: strippedContent, metadata } = stripFrontMatter(promptContent);
324
+ deliveryConfig.launch_prompt = strippedContent;
325
+ deliveryConfig.launch_prompt_file = route.with.prompt_file;
326
+ deliveryConfig.launch_prompt_meta = metadata;
327
+ }
328
+ catch {
329
+ // Non-fatal: log but continue delivery
330
+ }
331
+ }
332
+ const result = await actor.deliver(event, deliveryConfig);
333
+ const durationMs = Date.now() - startTime;
334
+ if (result.status === 'delivered') {
335
+ await this.emitLog('deliver.success', {
336
+ event_id: event.id,
337
+ trace_id: event.trace_id,
338
+ route: routeName,
339
+ target: actorId,
340
+ duration_ms: durationMs,
341
+ module: mod.name,
342
+ });
343
+ this.emit('delivery', {
344
+ event,
345
+ route: routeName,
346
+ actor: actorId,
347
+ status: 'delivered',
348
+ });
349
+ }
350
+ else {
351
+ await this.emitLog('deliver.failure', {
352
+ event_id: event.id,
353
+ trace_id: event.trace_id,
354
+ route: routeName,
355
+ target: actorId,
356
+ duration_ms: durationMs,
357
+ error: result.error?.message ?? result.status,
358
+ module: mod.name,
359
+ });
360
+ this.emit('delivery', {
361
+ event,
362
+ route: routeName,
363
+ actor: actorId,
364
+ status: result.status,
365
+ });
366
+ }
367
+ }
368
+ catch (err) {
369
+ const durationMs = Date.now() - startTime;
370
+ const error = new DeliveryError(actorId, routeName, 'Delivery failed', { cause: err });
371
+ this.emit('error', error);
372
+ await this.emitLog('deliver.failure', {
373
+ event_id: event.id,
374
+ trace_id: event.trace_id,
375
+ route: routeName,
376
+ target: actorId,
377
+ duration_ms: durationMs,
378
+ error: error.message,
379
+ module: mod.name,
380
+ });
381
+ }
382
+ }
383
+ // ─── Source Polling ───────────────────────────────────────────────────────
384
+ async pollSource(sourceId, moduleName) {
385
+ if (!moduleName)
386
+ return;
387
+ const mod = this.registry.get(moduleName);
388
+ if (!mod || mod.getState() !== 'active')
389
+ return;
390
+ const connector = mod.getSource(sourceId);
391
+ if (!connector)
392
+ return;
393
+ const healthState = mod.getHealthState(sourceId);
394
+ if (!healthState)
395
+ return;
396
+ // Circuit breaker: skip poll if circuit is open
397
+ if (healthState.circuitOpen) {
398
+ return;
399
+ }
400
+ healthState.lastPollAttempt = new Date().toISOString();
401
+ try {
402
+ const store = mod.getCheckpointStore();
403
+ const checkpoint = await store.get(sourceId);
404
+ const result = await connector.poll(checkpoint);
405
+ // Save checkpoint
406
+ if (result.checkpoint) {
407
+ await store.set(sourceId, result.checkpoint);
408
+ }
409
+ // Record successful poll
410
+ healthState.lastSuccessfulPoll = new Date().toISOString();
411
+ healthState.lastError = null;
412
+ healthState.totalEventsEmitted += result.events.length;
413
+ // If recovering from errors, log recovery
414
+ if (healthState.consecutiveErrors > 0) {
415
+ await this.emitLog('source.circuit_close', {
416
+ source: sourceId,
417
+ result: `recovered after ${healthState.consecutiveErrors} consecutive errors`,
418
+ module: moduleName,
419
+ });
420
+ }
421
+ healthState.consecutiveErrors = 0;
422
+ healthState.status = 'healthy';
423
+ // Process each event through the module
424
+ for (const event of result.events) {
425
+ const enriched = event.trace_id ? event : { ...event, trace_id: generateTraceId() };
426
+ await this.processEvent(enriched, mod);
427
+ }
428
+ }
429
+ catch (err) {
430
+ const error = new ConnectorError(sourceId, 'Poll failed', { cause: err });
431
+ this.emit('error', error);
432
+ healthState.consecutiveErrors++;
433
+ healthState.lastError = err instanceof Error ? err.message : String(err);
434
+ // Update health status
435
+ if (healthState.consecutiveErrors >= this.circuitBreakerOpts.failureThreshold) {
436
+ healthState.status = 'unhealthy';
437
+ healthState.circuitOpen = true;
438
+ await this.emitLog('source.circuit_open', {
439
+ source: sourceId,
440
+ error: healthState.lastError,
441
+ result: `${healthState.consecutiveErrors} consecutive failures — polling paused, will retry in ${Math.round(this.circuitBreakerOpts.retryAfterMs / 1000)}s`,
442
+ module: moduleName,
443
+ });
444
+ // Schedule a retry after backoff
445
+ this.scheduleCircuitRetry(sourceId, moduleName);
446
+ }
447
+ else {
448
+ healthState.status = 'degraded';
449
+ await this.emitLog('system.error', {
450
+ source: sourceId,
451
+ error: error.message,
452
+ module: moduleName,
453
+ });
454
+ }
455
+ }
456
+ }
457
+ scheduleCircuitRetry(sourceId, moduleName) {
458
+ const timerKey = `${moduleName}/${sourceId}`;
459
+ const existing = this.circuitRetryTimers.get(timerKey);
460
+ if (existing)
461
+ clearTimeout(existing);
462
+ const timer = setTimeout(async () => {
463
+ this.circuitRetryTimers.delete(timerKey);
464
+ if (!this.running)
465
+ return;
466
+ const mod = this.registry.get(moduleName);
467
+ if (!mod || mod.getState() !== 'active')
468
+ return;
469
+ const healthState = mod.getHealthState(sourceId);
470
+ if (!healthState || !healthState.circuitOpen)
471
+ return;
472
+ await this.emitLog('source.circuit_retry', {
473
+ source: sourceId,
474
+ result: 'attempting recovery poll',
475
+ module: moduleName,
476
+ });
477
+ // Temporarily allow poll by opening the circuit
478
+ healthState.circuitOpen = false;
479
+ await this.pollSource(sourceId, moduleName);
480
+ }, this.circuitBreakerOpts.retryAfterMs);
481
+ this.circuitRetryTimers.set(timerKey, timer);
482
+ }
483
+ // ─── RuntimeControl Implementation ───────────────────────────────────────
484
+ status() {
485
+ return {
486
+ running: this.running,
487
+ pid: process.pid,
488
+ uptime_ms: this.running ? Date.now() - this.startedAt : 0,
489
+ httpPort: this.httpPort,
490
+ modules: this.registry.list().map((m) => m.status()),
491
+ };
492
+ }
493
+ listModules() {
494
+ return this.registry.list().map((m) => m.status());
495
+ }
496
+ getModuleStatus(name) {
497
+ const mod = this.registry.get(name);
498
+ return mod?.status();
499
+ }
500
+ // ─── Logging ─────────────────────────────────────────────────────────────
501
+ async emitLog(phase, fields) {
502
+ const entry = {
503
+ timestamp: new Date().toISOString(),
504
+ event_id: fields.event_id ?? '',
505
+ trace_id: fields.trace_id ?? '',
506
+ phase,
507
+ source: fields.source,
508
+ target: fields.target,
509
+ route: fields.route,
510
+ transform: fields.transform,
511
+ event_type: fields.event_type,
512
+ result: fields.result,
513
+ duration_ms: fields.duration_ms,
514
+ error: fields.error,
515
+ metadata: fields.metadata,
516
+ module: fields.module,
517
+ };
518
+ await this.loggerManager.log(entry);
519
+ }
520
+ }
521
+ export { Runtime };
522
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -4,15 +4,24 @@
4
4
  * Schedules poll operations for sources based on their configured intervals.
5
5
  * Graceful start/stop with interval cleanup.
6
6
  */
7
- export type PollCallback = (sourceId: string) => Promise<void>;
7
+ export type PollCallback = (sourceId: string, moduleName?: string) => Promise<void>;
8
8
  export declare class Scheduler {
9
9
  private readonly sources;
10
10
  private running;
11
11
  private pollCallback;
12
12
  /**
13
13
  * Register a source to be polled at the given interval.
14
+ * If the scheduler is already running, starts polling immediately.
14
15
  */
15
- addSource(sourceId: string, interval: string): void;
16
+ addSource(sourceId: string, interval: string, moduleName?: string): void;
17
+ /**
18
+ * Remove a single source by ID and clear its interval.
19
+ */
20
+ removeSource(sourceId: string): void;
21
+ /**
22
+ * Remove all sources belonging to a given module.
23
+ */
24
+ removeSources(moduleName: string): void;
16
25
  /**
17
26
  * Start polling all registered sources.
18
27
  */
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAQ/D,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAA6B;IAEjD;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKnD;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;YAerB,QAAQ;IAStB;;OAEG;IACH,IAAI,IAAI,IAAI;IAUZ,IAAI,SAAS,IAAI,OAAO,CAEvB;CACD"}
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AASpF,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAA6B;IAEjD;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAcxE;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAWpC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAavC;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;YAerB,QAAQ;IAStB;;OAEG;IACH,IAAI,IAAI,IAAI;IAUZ,IAAI,SAAS,IAAI,OAAO,CAEvB;CACD"}
package/dist/scheduler.js CHANGED
@@ -11,10 +11,48 @@ export class Scheduler {
11
11
  pollCallback = null;
12
12
  /**
13
13
  * Register a source to be polled at the given interval.
14
+ * If the scheduler is already running, starts polling immediately.
14
15
  */
15
- addSource(sourceId, interval) {
16
+ addSource(sourceId, interval, moduleName) {
16
17
  const intervalMs = parseDuration(interval);
17
- this.sources.push({ sourceId, intervalMs, timer: null });
18
+ const source = { sourceId, intervalMs, moduleName, timer: null };
19
+ this.sources.push(source);
20
+ // If scheduler is already running, start polling this source immediately
21
+ if (this.running && this.pollCallback) {
22
+ void this.safePoll(source.sourceId, source.moduleName);
23
+ source.timer = setInterval(() => {
24
+ void this.safePoll(source.sourceId, source.moduleName);
25
+ }, source.intervalMs);
26
+ }
27
+ }
28
+ /**
29
+ * Remove a single source by ID and clear its interval.
30
+ */
31
+ removeSource(sourceId) {
32
+ const idx = this.sources.findIndex((s) => s.sourceId === sourceId);
33
+ if (idx === -1)
34
+ return;
35
+ const source = this.sources[idx];
36
+ if (source.timer) {
37
+ clearInterval(source.timer);
38
+ source.timer = null;
39
+ }
40
+ this.sources.splice(idx, 1);
41
+ }
42
+ /**
43
+ * Remove all sources belonging to a given module.
44
+ */
45
+ removeSources(moduleName) {
46
+ for (let i = this.sources.length - 1; i >= 0; i--) {
47
+ if (this.sources[i].moduleName === moduleName) {
48
+ const source = this.sources[i];
49
+ if (source.timer) {
50
+ clearInterval(source.timer);
51
+ source.timer = null;
52
+ }
53
+ this.sources.splice(i, 1);
54
+ }
55
+ }
18
56
  }
19
57
  /**
20
58
  * Start polling all registered sources.
@@ -26,18 +64,18 @@ export class Scheduler {
26
64
  this.pollCallback = callback;
27
65
  for (const source of this.sources) {
28
66
  // Run first poll immediately
29
- void this.safePoll(source.sourceId);
67
+ void this.safePoll(source.sourceId, source.moduleName);
30
68
  // Then schedule recurring polls
31
69
  source.timer = setInterval(() => {
32
- void this.safePoll(source.sourceId);
70
+ void this.safePoll(source.sourceId, source.moduleName);
33
71
  }, source.intervalMs);
34
72
  }
35
73
  }
36
- async safePoll(sourceId) {
74
+ async safePoll(sourceId, moduleName) {
37
75
  if (!this.pollCallback)
38
76
  return;
39
77
  try {
40
- await this.pollCallback(sourceId);
78
+ await this.pollCallback(sourceId, moduleName);
41
79
  }
42
80
  catch {
43
81
  // Errors handled upstream; scheduler keeps going