@pikku/schedule 0.12.0 → 0.12.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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
## 0.12.0
|
|
2
2
|
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e04531f: Code quality improvements: resolve oxlint warnings and apply autofixes across the codebase (unused bindings, unnecessary constructors, prefer `const` over `let`, etc.). No behaviour changes.
|
|
8
|
+
- Updated dependencies [62a8725]
|
|
9
|
+
- Updated dependencies [a3bdb0d]
|
|
10
|
+
- Updated dependencies [e0349ff]
|
|
11
|
+
- Updated dependencies [62a8725]
|
|
12
|
+
- Updated dependencies [e04531f]
|
|
13
|
+
- Updated dependencies [62a8725]
|
|
14
|
+
- Updated dependencies [a83efb8]
|
|
15
|
+
- Updated dependencies [8eed717]
|
|
16
|
+
- Updated dependencies [62a8725]
|
|
17
|
+
- Updated dependencies [62a8725]
|
|
18
|
+
- Updated dependencies [62a8725]
|
|
19
|
+
- @pikku/core@0.12.1
|
|
20
|
+
|
|
3
21
|
### New Features
|
|
4
22
|
|
|
5
23
|
- `InMemorySchedulerService` replacing `PikkuTaskScheduler` with full `SchedulerService` interface
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CoreUserSession,
|
|
1
|
+
import type { CoreUserSession, ScheduledTaskInfo, ScheduledTaskSummary } from '@pikku/core';
|
|
2
|
+
import { SchedulerService } from '@pikku/core';
|
|
2
3
|
/**
|
|
3
4
|
* In-memory SchedulerService implementation.
|
|
4
5
|
* Uses CronJob for recurring tasks and setTimeout for delayed RPCs.
|
|
@@ -7,13 +8,6 @@ export declare class InMemorySchedulerService extends SchedulerService {
|
|
|
7
8
|
private cronJobs;
|
|
8
9
|
private delayedTasks;
|
|
9
10
|
private idCounter;
|
|
10
|
-
private handlers?;
|
|
11
|
-
/**
|
|
12
|
-
* Set services needed for processing recurring tasks.
|
|
13
|
-
* Must be called before start() since the scheduler is typically
|
|
14
|
-
* created before singletonServices are available.
|
|
15
|
-
*/
|
|
16
|
-
setServices(handlers: SchedulerRuntimeHandlers): void;
|
|
17
11
|
init(): Promise<void>;
|
|
18
12
|
/**
|
|
19
13
|
* Schedule a one-off delayed RPC call via setTimeout
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { CronJob } from 'cron';
|
|
2
|
-
import { SchedulerService, parseDurationString
|
|
3
|
-
import {
|
|
2
|
+
import { SchedulerService, parseDurationString } from '@pikku/core';
|
|
3
|
+
import { pikkuState } from '@pikku/core/internal';
|
|
4
|
+
import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler';
|
|
5
|
+
const getLogger = () => {
|
|
6
|
+
return pikkuState(null, 'package', 'singletonServices').logger;
|
|
7
|
+
};
|
|
4
8
|
/**
|
|
5
9
|
* In-memory SchedulerService implementation.
|
|
6
10
|
* Uses CronJob for recurring tasks and setTimeout for delayed RPCs.
|
|
@@ -9,33 +13,21 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
9
13
|
cronJobs = new Map();
|
|
10
14
|
delayedTasks = new Map();
|
|
11
15
|
idCounter = 0;
|
|
12
|
-
handlers;
|
|
13
|
-
/**
|
|
14
|
-
* Set services needed for processing recurring tasks.
|
|
15
|
-
* Must be called before start() since the scheduler is typically
|
|
16
|
-
* created before singletonServices are available.
|
|
17
|
-
*/
|
|
18
|
-
setServices(handlers) {
|
|
19
|
-
this.handlers = handlers;
|
|
20
|
-
}
|
|
21
16
|
async init() { }
|
|
22
17
|
/**
|
|
23
18
|
* Schedule a one-off delayed RPC call via setTimeout
|
|
24
19
|
*/
|
|
25
20
|
async scheduleRPC(delay, rpcName, data, session) {
|
|
26
|
-
if (!this.handlers) {
|
|
27
|
-
throw new Error('InMemorySchedulerService requires setServices() before scheduling RPCs');
|
|
28
|
-
}
|
|
29
21
|
const delayMs = typeof delay === 'string' ? parseDurationString(delay) : delay;
|
|
30
22
|
const taskId = `inmem-${++this.idCounter}-${Date.now()}`;
|
|
31
23
|
const scheduledFor = new Date(Date.now() + delayMs);
|
|
32
24
|
const timer = setTimeout(async () => {
|
|
33
25
|
this.delayedTasks.delete(taskId);
|
|
34
26
|
try {
|
|
35
|
-
await
|
|
27
|
+
await runScheduledTask({ name: rpcName, session });
|
|
36
28
|
}
|
|
37
29
|
catch (err) {
|
|
38
|
-
|
|
30
|
+
getLogger().error(`Failed to execute delayed RPC '${rpcName}': ${err}`);
|
|
39
31
|
}
|
|
40
32
|
}, delayMs);
|
|
41
33
|
this.delayedTasks.set(taskId, {
|
|
@@ -89,9 +81,6 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
89
81
|
* Start recurring scheduled tasks.
|
|
90
82
|
*/
|
|
91
83
|
async start() {
|
|
92
|
-
if (!this.handlers) {
|
|
93
|
-
throw new Error('InMemorySchedulerService requires setServices() before start()');
|
|
94
|
-
}
|
|
95
84
|
const scheduledTasks = getScheduledTasks();
|
|
96
85
|
for (const [, task] of scheduledTasks) {
|
|
97
86
|
this.startCronJob(task.name, task.schedule);
|
|
@@ -108,9 +97,9 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
108
97
|
}
|
|
109
98
|
startCronJob(name, schedule) {
|
|
110
99
|
const job = new CronJob(schedule, async () => {
|
|
111
|
-
|
|
112
|
-
await
|
|
113
|
-
|
|
100
|
+
getLogger().info(`Running scheduled task: ${name}`);
|
|
101
|
+
await runScheduledTask({ name });
|
|
102
|
+
getLogger().debug(`Completed scheduled task: ${name}`);
|
|
114
103
|
}, null, true);
|
|
115
104
|
this.cronJobs.set(name, job);
|
|
116
105
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/schedule",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"test:coverage": "bash run-tests.sh --coverage"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"@pikku/core": "^0.12.
|
|
19
|
+
"@pikku/core": "^0.12.1"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^24.10.12",
|
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import { describe, test } from 'node:test'
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
|
+
import { pikkuState } from '@pikku/core/internal'
|
|
3
4
|
|
|
4
5
|
import { InMemorySchedulerService } from './in-memory-scheduler-service.js'
|
|
5
6
|
|
|
6
7
|
describe('InMemorySchedulerService scheduleRPC', () => {
|
|
7
|
-
test('
|
|
8
|
-
const scheduler = new InMemorySchedulerService()
|
|
9
|
-
await assert.rejects(() => scheduler.scheduleRPC(0, 'testRpc', {}), {
|
|
10
|
-
message:
|
|
11
|
-
'InMemorySchedulerService requires setServices() before scheduling RPCs',
|
|
12
|
-
})
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
test('uses empty wire context and does not create wire services', async () => {
|
|
16
|
-
const scheduler = new InMemorySchedulerService()
|
|
17
|
-
const session = { userId: 'user-1' }
|
|
18
|
-
|
|
8
|
+
test('schedules and executes delayed RPC', async () => {
|
|
19
9
|
const logger = {
|
|
20
10
|
info: () => {},
|
|
21
11
|
warn: () => {},
|
|
@@ -23,25 +13,22 @@ describe('InMemorySchedulerService scheduleRPC', () => {
|
|
|
23
13
|
error: () => {},
|
|
24
14
|
}
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
pikkuState(null, 'package', 'singletonServices', {
|
|
17
|
+
logger,
|
|
18
|
+
} as any)
|
|
28
19
|
|
|
20
|
+
const scheduler = new InMemorySchedulerService()
|
|
29
21
|
try {
|
|
30
|
-
scheduler.
|
|
31
|
-
|
|
32
|
-
invokeRPC: async (_rpcName: string, _data: any, sessionArg?: any) => {
|
|
33
|
-
invokeCalls += 1
|
|
34
|
-
capturedSession = sessionArg
|
|
35
|
-
},
|
|
36
|
-
runScheduledTask: async () => {},
|
|
22
|
+
const taskId = await scheduler.scheduleRPC(50, 'testRpc', { ok: true }, {
|
|
23
|
+
userId: 'user-1',
|
|
37
24
|
} as any)
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
assert.ok(taskId)
|
|
26
|
+
|
|
27
|
+
const task = await scheduler.getTask(taskId)
|
|
28
|
+
assert.ok(task)
|
|
29
|
+
assert.equal(task.rpcName, 'testRpc')
|
|
40
30
|
} finally {
|
|
41
31
|
await scheduler.close()
|
|
42
32
|
}
|
|
43
|
-
|
|
44
|
-
assert.equal(invokeCalls, 1)
|
|
45
|
-
assert.equal(capturedSession, session)
|
|
46
33
|
})
|
|
47
34
|
})
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { CronJob } from 'cron'
|
|
2
|
-
import {
|
|
2
|
+
import type {
|
|
3
3
|
CoreUserSession,
|
|
4
|
-
SchedulerService,
|
|
5
|
-
SchedulerRuntimeHandlers,
|
|
6
4
|
ScheduledTaskInfo,
|
|
7
5
|
ScheduledTaskSummary,
|
|
8
|
-
parseDurationString,
|
|
9
6
|
} from '@pikku/core'
|
|
10
|
-
import {
|
|
7
|
+
import { SchedulerService, parseDurationString } from '@pikku/core'
|
|
8
|
+
import { pikkuState } from '@pikku/core/internal'
|
|
9
|
+
import { runScheduledTask, getScheduledTasks } from '@pikku/core/scheduler'
|
|
11
10
|
|
|
12
11
|
interface DelayedTask {
|
|
13
12
|
taskId: string
|
|
@@ -18,6 +17,10 @@ interface DelayedTask {
|
|
|
18
17
|
timer: ReturnType<typeof setTimeout>
|
|
19
18
|
}
|
|
20
19
|
|
|
20
|
+
const getLogger = () => {
|
|
21
|
+
return pikkuState(null, 'package', 'singletonServices')!.logger
|
|
22
|
+
}
|
|
23
|
+
|
|
21
24
|
/**
|
|
22
25
|
* In-memory SchedulerService implementation.
|
|
23
26
|
* Uses CronJob for recurring tasks and setTimeout for delayed RPCs.
|
|
@@ -26,16 +29,6 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
26
29
|
private cronJobs = new Map<string, CronJob>()
|
|
27
30
|
private delayedTasks = new Map<string, DelayedTask>()
|
|
28
31
|
private idCounter = 0
|
|
29
|
-
private handlers?: SchedulerRuntimeHandlers
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Set services needed for processing recurring tasks.
|
|
33
|
-
* Must be called before start() since the scheduler is typically
|
|
34
|
-
* created before singletonServices are available.
|
|
35
|
-
*/
|
|
36
|
-
setServices(handlers: SchedulerRuntimeHandlers): void {
|
|
37
|
-
this.handlers = handlers
|
|
38
|
-
}
|
|
39
32
|
|
|
40
33
|
async init(): Promise<void> {}
|
|
41
34
|
|
|
@@ -48,12 +41,6 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
48
41
|
data?: any,
|
|
49
42
|
session?: CoreUserSession
|
|
50
43
|
): Promise<string> {
|
|
51
|
-
if (!this.handlers) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
'InMemorySchedulerService requires setServices() before scheduling RPCs'
|
|
54
|
-
)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
44
|
const delayMs =
|
|
58
45
|
typeof delay === 'string' ? parseDurationString(delay) : delay
|
|
59
46
|
const taskId = `inmem-${++this.idCounter}-${Date.now()}`
|
|
@@ -62,11 +49,9 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
62
49
|
const timer = setTimeout(async () => {
|
|
63
50
|
this.delayedTasks.delete(taskId)
|
|
64
51
|
try {
|
|
65
|
-
await
|
|
52
|
+
await runScheduledTask({ name: rpcName, session })
|
|
66
53
|
} catch (err: unknown) {
|
|
67
|
-
|
|
68
|
-
`Failed to execute delayed RPC '${rpcName}': ${err}`
|
|
69
|
-
)
|
|
54
|
+
getLogger().error(`Failed to execute delayed RPC '${rpcName}': ${err}`)
|
|
70
55
|
}
|
|
71
56
|
}, delayMs)
|
|
72
57
|
|
|
@@ -126,14 +111,7 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
126
111
|
* Start recurring scheduled tasks.
|
|
127
112
|
*/
|
|
128
113
|
async start(): Promise<void> {
|
|
129
|
-
if (!this.handlers) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
'InMemorySchedulerService requires setServices() before start()'
|
|
132
|
-
)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
114
|
const scheduledTasks = getScheduledTasks()
|
|
136
|
-
|
|
137
115
|
for (const [, task] of scheduledTasks) {
|
|
138
116
|
this.startCronJob(task.name, task.schedule)
|
|
139
117
|
}
|
|
@@ -153,9 +131,9 @@ export class InMemorySchedulerService extends SchedulerService {
|
|
|
153
131
|
const job = new CronJob(
|
|
154
132
|
schedule,
|
|
155
133
|
async () => {
|
|
156
|
-
|
|
157
|
-
await
|
|
158
|
-
|
|
134
|
+
getLogger().info(`Running scheduled task: ${name}`)
|
|
135
|
+
await runScheduledTask({ name })
|
|
136
|
+
getLogger().debug(`Completed scheduled task: ${name}`)
|
|
159
137
|
},
|
|
160
138
|
null,
|
|
161
139
|
true
|