spooder 6.1.7 → 6.1.93
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/README.md +29 -1
- package/bun.lock +3 -3
- package/package.json +4 -1
- package/src/api.ts +19 -8
package/README.md
CHANGED
|
@@ -655,6 +655,8 @@ type WorkerPoolOptions = {
|
|
|
655
655
|
worker: string | string[];
|
|
656
656
|
size?: number;
|
|
657
657
|
auto_restart?: boolean | AutoRestartConfig;
|
|
658
|
+
onWorkerStart?: (pool: WorkerPool, worker_id: string) => void;
|
|
659
|
+
onWorkerStop?: (pool: WorkerPool, worker_id: string, exit_code: number) => void;
|
|
658
660
|
};
|
|
659
661
|
|
|
660
662
|
type AutoRestartConfig = {
|
|
@@ -1732,7 +1734,7 @@ global_subs: {
|
|
|
1732
1734
|
build_time: async () => {
|
|
1733
1735
|
// Example: fetch build timestamp from git
|
|
1734
1736
|
const process = Bun.spawn(['git', 'log', '-1', '--format=%ct']);
|
|
1735
|
-
const output = await
|
|
1737
|
+
const output = await new Response(process.stdout).text();
|
|
1736
1738
|
return new Date(parseInt(output.trim()) * 1000).toISOString();
|
|
1737
1739
|
},
|
|
1738
1740
|
|
|
@@ -2106,6 +2108,32 @@ pool.on('MSG_REQUEST', msg => {
|
|
|
2106
2108
|
});
|
|
2107
2109
|
```
|
|
2108
2110
|
|
|
2111
|
+
### Lifecycle Callbacks
|
|
2112
|
+
|
|
2113
|
+
Worker pools support lifecycle callbacks to monitor when workers start and stop. Callbacks receive the pool instance, allowing you to communicate with workers immediately.
|
|
2114
|
+
|
|
2115
|
+
```ts
|
|
2116
|
+
const pool = await worker_pool({
|
|
2117
|
+
worker: './worker.ts',
|
|
2118
|
+
auto_restart: true,
|
|
2119
|
+
onWorkerStart: async (pool, worker_id) => {
|
|
2120
|
+
console.log(`Worker ${worker_id} started`);
|
|
2121
|
+
await pool.send(worker_id, 'init', { config: 'value' }, true);
|
|
2122
|
+
},
|
|
2123
|
+
onWorkerStop: (pool, worker_id, exit_code) => {
|
|
2124
|
+
console.log(`Worker ${worker_id} stopped with exit code ${exit_code}`);
|
|
2125
|
+
if (exit_code !== 0 && exit_code !== 42) {
|
|
2126
|
+
console.log(`Worker ${worker_id} crashed`);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
```
|
|
2131
|
+
|
|
2132
|
+
#### Callback Signatures
|
|
2133
|
+
|
|
2134
|
+
- `onWorkerStart: (pool: WorkerPool, worker_id: string) => void` - Fires when a worker registers with the pool
|
|
2135
|
+
- `onWorkerStop: (pool: WorkerPool, worker_id: string, exit_code: number) => void` - Fires when a worker stops
|
|
2136
|
+
|
|
2109
2137
|
### Auto-Restart
|
|
2110
2138
|
|
|
2111
2139
|
The `worker_pool` function supports automatic worker restart when workers crash or close unexpectedly. This feature includes an exponential backoff protocol to prevent restart loops.
|
package/bun.lock
CHANGED
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
"packages": {
|
|
13
|
-
"@types/bun": ["@types/bun@1.3.
|
|
13
|
+
"@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
|
|
14
14
|
|
|
15
|
-
"@types/node": ["@types/node@
|
|
15
|
+
"@types/node": ["@types/node@25.0.6", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-NNu0sjyNxpoiW3YuVFfNz7mxSQ+S4X2G28uqg2s+CzoqoQjLPsWSbsFFyztIAqt2vb8kfEAsJNepMGPTxFDx3Q=="],
|
|
16
16
|
|
|
17
|
-
"bun-types": ["bun-types@1.3.
|
|
17
|
+
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
|
18
18
|
|
|
19
19
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
20
20
|
}
|
package/package.json
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
"name": "spooder",
|
|
3
3
|
"author": "Kruithne <kruithne@gmail.com>",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "6.1.
|
|
5
|
+
"version": "6.1.93",
|
|
6
6
|
"module": "./src/api.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"url": "https://github.com/Kruithne/spooder"
|
|
9
|
+
},
|
|
7
10
|
"bin": {
|
|
8
11
|
"spooder": "./src/cli.ts"
|
|
9
12
|
},
|
package/src/api.ts
CHANGED
|
@@ -33,6 +33,9 @@ type WorkerMessage = {
|
|
|
33
33
|
|
|
34
34
|
const RESPONSE_TIMEOUT_MS = 5000;
|
|
35
35
|
|
|
36
|
+
type WorkerStartCallback = (pool: WorkerPool, worker_id: string) => void;
|
|
37
|
+
type WorkerStopCallback = (pool: WorkerPool, worker_id: string, exit_code: number) => void;
|
|
38
|
+
|
|
36
39
|
export interface WorkerPool {
|
|
37
40
|
id: string;
|
|
38
41
|
send(peer: string, id: string, data?: WorkerMessageData, expect_response?: false): void;
|
|
@@ -59,6 +62,8 @@ type WorkerPoolOptions = {
|
|
|
59
62
|
size?: number;
|
|
60
63
|
auto_restart?: boolean | AutoRestartConfig;
|
|
61
64
|
response_timeout?: number;
|
|
65
|
+
onWorkerStart?: WorkerStartCallback;
|
|
66
|
+
onWorkerStop?: WorkerStopCallback;
|
|
62
67
|
};
|
|
63
68
|
|
|
64
69
|
type WorkerState = {
|
|
@@ -94,6 +99,9 @@ export async function worker_pool(options: WorkerPoolOptions): Promise<WorkerPoo
|
|
|
94
99
|
const callbacks = new Map<string, (data: WorkerMessage) => Promise<void> | void>();
|
|
95
100
|
const pending_responses = new Map<string, { resolve: (message: WorkerMessage) => void, reject: (error: Error) => void, timeout: Timer | undefined }>();
|
|
96
101
|
|
|
102
|
+
const on_worker_start = options.onWorkerStart;
|
|
103
|
+
const on_worker_stop = options.onWorkerStop;
|
|
104
|
+
|
|
97
105
|
async function restart_worker(worker: Worker) {
|
|
98
106
|
if (!auto_restart_enabled)
|
|
99
107
|
return;
|
|
@@ -150,6 +158,9 @@ export async function worker_pool(options: WorkerPoolOptions): Promise<WorkerPoo
|
|
|
150
158
|
if (worker_id)
|
|
151
159
|
pipe_workers.deleteByKey(worker_id);
|
|
152
160
|
|
|
161
|
+
if (worker_id)
|
|
162
|
+
on_worker_stop?.(pool, worker_id, exit_code);
|
|
163
|
+
|
|
153
164
|
if (auto_restart_enabled && exit_code !== WORKER_EXIT_NO_RESTART)
|
|
154
165
|
restart_worker(worker);
|
|
155
166
|
else if (exit_code === WORKER_EXIT_NO_RESTART)
|
|
@@ -180,6 +191,8 @@ export async function worker_pool(options: WorkerPoolOptions): Promise<WorkerPoo
|
|
|
180
191
|
|
|
181
192
|
worker_promises.get(worker)?.();
|
|
182
193
|
worker_promises.delete(worker);
|
|
194
|
+
|
|
195
|
+
on_worker_start?.(pool, worker_id);
|
|
183
196
|
} else if (message.peer === '__broadcast__') {
|
|
184
197
|
const worker_id = pipe_workers.getByValue(worker);
|
|
185
198
|
if (worker_id === undefined)
|
|
@@ -808,7 +821,7 @@ export class ErrorWithMetadata extends Error {
|
|
|
808
821
|
else if (typeof value === 'function')
|
|
809
822
|
resolved_value = await value();
|
|
810
823
|
else if (value instanceof ReadableStream)
|
|
811
|
-
resolved_value = await
|
|
824
|
+
resolved_value = await new Response(value).text();
|
|
812
825
|
|
|
813
826
|
if (typeof resolved_value === 'string' && resolved_value.includes('\n'))
|
|
814
827
|
resolved_value = resolved_value.split(/\r?\n/);
|
|
@@ -957,12 +970,10 @@ export async function parse_template(template: string, replacements: Replacement
|
|
|
957
970
|
}
|
|
958
971
|
}
|
|
959
972
|
|
|
960
|
-
|
|
961
|
-
return match;
|
|
962
|
-
|
|
973
|
+
// missing/undefined items treated as empty array (no output)
|
|
963
974
|
return '';
|
|
964
975
|
});
|
|
965
|
-
|
|
976
|
+
|
|
966
977
|
// Parse t-if tags
|
|
967
978
|
const if_regex = /<t-if\s+test="([^"]+)"\s*>(.*?)<\/t-if>/gs;
|
|
968
979
|
result = await replace_async(result, if_regex, async (match, condition_key, if_content) => {
|
|
@@ -1106,9 +1117,9 @@ export async function git_get_hashes(length = 7): Promise<Record<string, string>
|
|
|
1106
1117
|
await process.exited;
|
|
1107
1118
|
|
|
1108
1119
|
if (process.exitCode as number > 0)
|
|
1109
|
-
|
|
1120
|
+
return {};
|
|
1110
1121
|
|
|
1111
|
-
const stdout = await
|
|
1122
|
+
const stdout = await new Response(process.stdout).text();
|
|
1112
1123
|
const hash_map: Record<string, string> = {};
|
|
1113
1124
|
|
|
1114
1125
|
const regex = /([^\s]+)\s([^\s]+)\s([^\s]+)\t(.+)/g;
|
|
@@ -1128,7 +1139,7 @@ export function git_get_hashes_sync(length = 7): Record<string, string> {
|
|
|
1128
1139
|
});
|
|
1129
1140
|
|
|
1130
1141
|
if (process.exitCode > 0)
|
|
1131
|
-
|
|
1142
|
+
return {};
|
|
1132
1143
|
|
|
1133
1144
|
const stdout = process.stdout.toString();
|
|
1134
1145
|
const hash_map: Record<string, string> = {};
|