@travetto/worker 2.1.3 → 2.2.2
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 +16 -16
- package/package.json +3 -3
- package/src/comm/channel.ts +11 -11
- package/src/comm/parent.ts +1 -1
- package/src/input/async-iterator.ts +3 -3
- package/src/input/iterable.ts +5 -5
- package/src/pool.ts +8 -8
- package/src/support/barrier.ts +7 -6
- package/src/support/timeout.ts +2 -2
- package/src/util.ts +4 -4
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- This file was generated by @travetto/doc and should not be modified directly -->
|
|
2
2
|
<!-- Please modify https://github.com/travetto/travetto/tree/main/module/worker/doc.ts and execute "npx trv doc" to rebuild -->
|
|
3
3
|
# Worker
|
|
4
|
-
## Process management
|
|
4
|
+
## Process management utilities, with a focus on inter-process communication
|
|
5
5
|
|
|
6
6
|
**Install: @travetto/worker**
|
|
7
7
|
```bash
|
|
@@ -26,21 +26,21 @@ class ImageProcessor implements Worker<string> {
|
|
|
26
26
|
active = false;
|
|
27
27
|
proc: ExecutionState;
|
|
28
28
|
|
|
29
|
-
get id() {
|
|
29
|
+
get id(): number | undefined {
|
|
30
30
|
return this.proc.process.pid;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
async destroy() {
|
|
33
|
+
async destroy(): Promise<void> {
|
|
34
34
|
this.proc.process.kill();
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
async execute(path: string) {
|
|
37
|
+
async execute(path: string): Promise<void> {
|
|
38
38
|
this.active = true;
|
|
39
39
|
try {
|
|
40
40
|
this.proc = ExecUtil.spawn('convert images', [path]);
|
|
41
41
|
await this.proc;
|
|
42
|
-
} catch
|
|
43
|
-
|
|
42
|
+
} catch {
|
|
43
|
+
// Do nothing
|
|
44
44
|
}
|
|
45
45
|
this.active = false;
|
|
46
46
|
}
|
|
@@ -54,11 +54,11 @@ export class ImageCompressor extends WorkPool<string, ImageProcessor> {
|
|
|
54
54
|
super(async () => new ImageProcessor());
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
begin() {
|
|
57
|
+
begin(): void {
|
|
58
58
|
this.process(new IterableWorkSet(this.pendingImages));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
convert(...images: string[]) {
|
|
61
|
+
convert(...images: string[]): void {
|
|
62
62
|
this.pendingImages.add(images);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -83,7 +83,7 @@ import { Worker } from './pool';
|
|
|
83
83
|
type Simple<V> = (ch: ParentCommChannel<V>) => Promise<unknown | void>;
|
|
84
84
|
type Param<V, X> = (ch: ParentCommChannel<V>, input: X) => Promise<unknown | void>;
|
|
85
85
|
|
|
86
|
-
const empty = async () => { };
|
|
86
|
+
const empty = async (): Promise<void> => { };
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Spawned worker
|
|
@@ -99,11 +99,11 @@ export class WorkUtil {
|
|
|
99
99
|
destroy: Simple<V> = empty): Worker<X> {
|
|
100
100
|
const channel = new ParentCommChannel<V>(worker());
|
|
101
101
|
return {
|
|
102
|
-
get id() { return channel.id; },
|
|
103
|
-
get active() { return channel.active; },
|
|
102
|
+
get id(): number | undefined { return channel.id; },
|
|
103
|
+
get active(): boolean { return channel.active; },
|
|
104
104
|
init: () => init(channel),
|
|
105
105
|
execute: inp => execute(channel, inp),
|
|
106
|
-
async destroy() {
|
|
106
|
+
async destroy(): Promise<void> {
|
|
107
107
|
await destroy(channel);
|
|
108
108
|
await channel.destroy();
|
|
109
109
|
},
|
|
@@ -119,7 +119,7 @@ When creating your work, via process spawning, you will need to provide the scri
|
|
|
119
119
|
import { WorkPool, WorkUtil, IterableWorkSet } from '@travetto/worker';
|
|
120
120
|
import { ExecUtil, PathUtil } from '@travetto/boot';
|
|
121
121
|
|
|
122
|
-
export function main() {
|
|
122
|
+
export async function main(): Promise<void> {
|
|
123
123
|
const pool = new WorkPool(() =>
|
|
124
124
|
WorkUtil.spawnedWorker<{ data: string }, string>(
|
|
125
125
|
() => ExecUtil.forkMain(PathUtil.resolveUnix(__dirname, 'spawned.ts')),
|
|
@@ -139,7 +139,7 @@ export function main() {
|
|
|
139
139
|
)
|
|
140
140
|
);
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
await pool.process(new IterableWorkSet([1, 2, 3, 4, 5])).then(x => pool.shutdown());
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
|
@@ -147,7 +147,7 @@ export function main() {
|
|
|
147
147
|
```typescript
|
|
148
148
|
import { ChildCommChannel } from '@travetto/worker';
|
|
149
149
|
|
|
150
|
-
export async function main() {
|
|
150
|
+
export async function main(): Promise<void> {
|
|
151
151
|
const exec = new ChildCommChannel<{ data: string }>();
|
|
152
152
|
|
|
153
153
|
exec.on('request', data =>
|
|
@@ -155,7 +155,7 @@ export async function main() {
|
|
|
155
155
|
|
|
156
156
|
exec.send('ready'); // Indicate the child is ready to receive requests
|
|
157
157
|
|
|
158
|
-
const heartbeat = () => setTimeout(heartbeat, 5000); // Keep-alive
|
|
158
|
+
const heartbeat = (): void => { setTimeout(heartbeat, 5000); }; // Keep-alive
|
|
159
159
|
heartbeat();
|
|
160
160
|
}
|
|
161
161
|
```
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/worker",
|
|
3
3
|
"displayName": "Worker",
|
|
4
|
-
"version": "2.
|
|
5
|
-
"description": "Process management
|
|
4
|
+
"version": "2.2.2",
|
|
5
|
+
"description": "Process management utilities, with a focus on inter-process communication",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"exec",
|
|
8
8
|
"child-process",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"directory": "module/worker"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@travetto/base": "^2.
|
|
29
|
+
"@travetto/base": "^2.2.2",
|
|
30
30
|
"@types/generic-pool": "^3.1.11",
|
|
31
31
|
"generic-pool": "^3.8.2"
|
|
32
32
|
},
|
package/src/comm/channel.ts
CHANGED
|
@@ -17,17 +17,17 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
|
|
|
17
17
|
this.#proc.on('message', this.#handleMessage.bind(this));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
get #parentId() {
|
|
20
|
+
get #parentId(): number {
|
|
21
21
|
return process.pid;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
#handleMessage(ev: { type: string }) {
|
|
24
|
+
#handleMessage(ev: { type: string }): void {
|
|
25
25
|
console.debug('Received', { pid: this.#parentId, id: this.id, type: ev.type });
|
|
26
26
|
this.#emitter.emit(ev.type, ev);
|
|
27
27
|
this.#emitter.emit('*', ev);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
get proc() {
|
|
30
|
+
get proc(): T | undefined {
|
|
31
31
|
return this.#proc;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -38,21 +38,21 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
|
|
|
38
38
|
/**
|
|
39
39
|
* Gets channel unique identifier
|
|
40
40
|
*/
|
|
41
|
-
get id() {
|
|
41
|
+
get id(): number | undefined {
|
|
42
42
|
return this.#proc && this.#proc.pid;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Determines if channel is active
|
|
47
47
|
*/
|
|
48
|
-
get active() {
|
|
48
|
+
get active(): boolean {
|
|
49
49
|
return !!this.#proc;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Send data to the parent
|
|
54
54
|
*/
|
|
55
|
-
send(eventType: string, data?: Record<string, unknown>) {
|
|
55
|
+
send(eventType: string, data?: Record<string, unknown>): void {
|
|
56
56
|
console.debug('Sending', { pid: this.#parentId, id: this.id, eventType });
|
|
57
57
|
if (!this.#proc) {
|
|
58
58
|
throw new Error('this.proc was not defined');
|
|
@@ -66,7 +66,7 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
|
|
|
66
66
|
/**
|
|
67
67
|
* Listen for a specific message type
|
|
68
68
|
*/
|
|
69
|
-
on(eventType: string, callback: (e: U) => unknown | void) {
|
|
69
|
+
on(eventType: string, callback: (e: U) => unknown | void): () => void {
|
|
70
70
|
this.#emitter.on(eventType, callback);
|
|
71
71
|
return () => this.off(eventType, callback);
|
|
72
72
|
}
|
|
@@ -74,21 +74,21 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
|
|
|
74
74
|
/**
|
|
75
75
|
* Remove event listener
|
|
76
76
|
*/
|
|
77
|
-
off(eventType: string, callback: (e: U) => unknown | void) {
|
|
77
|
+
off(eventType: string, callback: (e: U) => unknown | void): void {
|
|
78
78
|
this.#emitter.off(eventType, callback);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Listen for a specific message type, once
|
|
83
83
|
*/
|
|
84
|
-
once(eventType: string) {
|
|
84
|
+
once(eventType: string): Promise<U> {
|
|
85
85
|
return new Promise<U>(res => this.#emitter.once(eventType, res));
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Destroy self
|
|
90
90
|
*/
|
|
91
|
-
async destroy() {
|
|
91
|
+
async destroy(): Promise<void> {
|
|
92
92
|
if (this.#proc) {
|
|
93
93
|
console.debug('Killing', { pid: this.#parentId, id: this.id });
|
|
94
94
|
if (this.#proc !== process) {
|
|
@@ -102,7 +102,7 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
|
|
|
102
102
|
/**
|
|
103
103
|
* Remove all listeners, but do not destroy
|
|
104
104
|
*/
|
|
105
|
-
release() {
|
|
105
|
+
release(): void {
|
|
106
106
|
console.debug('Released', { pid: this.#parentId, id: this.id });
|
|
107
107
|
this.#emitter.removeAllListeners();
|
|
108
108
|
}
|
package/src/comm/parent.ts
CHANGED
|
@@ -22,7 +22,7 @@ export class ParentCommChannel<U = unknown> extends ProcessCommChannel<ChildProc
|
|
|
22
22
|
/**
|
|
23
23
|
* Kill self and child
|
|
24
24
|
*/
|
|
25
|
-
override async destroy() {
|
|
25
|
+
override async destroy(): Promise<void> {
|
|
26
26
|
const res = super.destroy();
|
|
27
27
|
await this.#complete;
|
|
28
28
|
return await res;
|
|
@@ -19,7 +19,7 @@ export class ManualAsyncIterator<X> implements AsyncIterator<X> {
|
|
|
19
19
|
/**
|
|
20
20
|
* Wait for next event to fire
|
|
21
21
|
*/
|
|
22
|
-
async next() {
|
|
22
|
+
async next(): Promise<IteratorResult<X>> {
|
|
23
23
|
if (!this.#done && !this.#queue.length) {
|
|
24
24
|
await this.#ready;
|
|
25
25
|
this.#ready = Util.resolvablePromise();
|
|
@@ -31,7 +31,7 @@ export class ManualAsyncIterator<X> implements AsyncIterator<X> {
|
|
|
31
31
|
* Queue next event to fire
|
|
32
32
|
* @param {boolean} immediate Determines if item(s) should be append or prepended to the queue
|
|
33
33
|
*/
|
|
34
|
-
add(item: X | X[], immediate = false) {
|
|
34
|
+
add(item: X | X[], immediate = false): void {
|
|
35
35
|
item = Array.isArray(item) ? item : [item];
|
|
36
36
|
if (!immediate) {
|
|
37
37
|
this.#queue.push(...item);
|
|
@@ -44,7 +44,7 @@ export class ManualAsyncIterator<X> implements AsyncIterator<X> {
|
|
|
44
44
|
/**
|
|
45
45
|
* Close the iterator
|
|
46
46
|
*/
|
|
47
|
-
close() {
|
|
47
|
+
close(): void {
|
|
48
48
|
this.#done = true;
|
|
49
49
|
this.#ready.resolve();
|
|
50
50
|
}
|
package/src/input/iterable.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { WorkSet } from './types';
|
|
|
2
2
|
|
|
3
3
|
type Itr<T> = Iterator<T> | AsyncIterator<T>;
|
|
4
4
|
|
|
5
|
-
const hasAsyncItr = (o: unknown): o is AsyncIterable<unknown> => !!o && Symbol.asyncIterator in
|
|
6
|
-
const hasItr = (o: unknown): o is Iterable<unknown> => !!o && Symbol.iterator in
|
|
5
|
+
const hasAsyncItr = (o: unknown): o is AsyncIterable<unknown> => !!o && typeof o === 'object' && Symbol.asyncIterator in o;
|
|
6
|
+
const hasItr = (o: unknown): o is Iterable<unknown> => !!o && typeof o === 'object' && Symbol.iterator in o;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Basic input source given an iterable input
|
|
@@ -31,7 +31,7 @@ export class IterableWorkSet<X> implements WorkSet<X> {
|
|
|
31
31
|
/**
|
|
32
32
|
* Fetch next item from the iterable
|
|
33
33
|
*/
|
|
34
|
-
async #primeNext() {
|
|
34
|
+
async #primeNext(): Promise<void> {
|
|
35
35
|
const res = await this.#src.next();
|
|
36
36
|
this.#done = !!res.done;
|
|
37
37
|
this.#ondeck = res.value;
|
|
@@ -40,7 +40,7 @@ export class IterableWorkSet<X> implements WorkSet<X> {
|
|
|
40
40
|
/**
|
|
41
41
|
* Determine if the iterable has more data
|
|
42
42
|
*/
|
|
43
|
-
async hasNext() {
|
|
43
|
+
async hasNext(): Promise<boolean> {
|
|
44
44
|
if (this.#ondeck === undefined) {
|
|
45
45
|
await this.#primeNext();
|
|
46
46
|
}
|
|
@@ -50,7 +50,7 @@ export class IterableWorkSet<X> implements WorkSet<X> {
|
|
|
50
50
|
/**
|
|
51
51
|
* Fetch next item
|
|
52
52
|
*/
|
|
53
|
-
async next() {
|
|
53
|
+
async next(): Promise<X> {
|
|
54
54
|
await this.hasNext();
|
|
55
55
|
|
|
56
56
|
const out = this.#ondeck!;
|
package/src/pool.ts
CHANGED
|
@@ -68,7 +68,7 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
68
68
|
/**
|
|
69
69
|
* Creates and tracks new worker
|
|
70
70
|
*/
|
|
71
|
-
async #createAndTrack(getWorker: () => Promise<T> | T, opts: gp.Options) {
|
|
71
|
+
async #createAndTrack(getWorker: () => Promise<T> | T, opts: gp.Options): Promise<T> {
|
|
72
72
|
try {
|
|
73
73
|
this.#pendingAcquires += 1;
|
|
74
74
|
const res = await getWorker();
|
|
@@ -80,12 +80,12 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
80
80
|
this.#createErrors = 0; // Reset errors on success
|
|
81
81
|
|
|
82
82
|
return res;
|
|
83
|
-
} catch (
|
|
83
|
+
} catch (err) {
|
|
84
84
|
if (this.#createErrors++ > opts.max!) { // If error count is bigger than pool size, we broke
|
|
85
|
-
console.error('Failed in creating pool', { error:
|
|
85
|
+
console.error('Failed in creating pool', { error: err });
|
|
86
86
|
process.exit(1);
|
|
87
87
|
}
|
|
88
|
-
throw
|
|
88
|
+
throw err;
|
|
89
89
|
} finally {
|
|
90
90
|
this.#pendingAcquires -= 1;
|
|
91
91
|
}
|
|
@@ -94,7 +94,7 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
94
94
|
/**
|
|
95
95
|
* Destroy the worker
|
|
96
96
|
*/
|
|
97
|
-
async destroy(worker: T) {
|
|
97
|
+
async destroy(worker: T): Promise<void> {
|
|
98
98
|
console.debug('Destroying', { pid: process.pid, worker: worker.id });
|
|
99
99
|
return worker.destroy();
|
|
100
100
|
}
|
|
@@ -102,7 +102,7 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
102
102
|
/**
|
|
103
103
|
* Free worker on completion
|
|
104
104
|
*/
|
|
105
|
-
async release(worker: T) {
|
|
105
|
+
async release(worker: T): Promise<void> {
|
|
106
106
|
console.debug('Releasing', { pid: process.pid, worker: worker.id });
|
|
107
107
|
try {
|
|
108
108
|
if (worker.active) {
|
|
@@ -121,7 +121,7 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
121
121
|
/**
|
|
122
122
|
* Process a given input source
|
|
123
123
|
*/
|
|
124
|
-
async process(src: WorkSet<X>) {
|
|
124
|
+
async process(src: WorkSet<X>): Promise<void> {
|
|
125
125
|
const pending = new Set<Promise<unknown>>();
|
|
126
126
|
|
|
127
127
|
while (await src.hasNext()) {
|
|
@@ -148,7 +148,7 @@ export class WorkPool<X, T extends Worker<X>> {
|
|
|
148
148
|
/**
|
|
149
149
|
* Shutdown pool
|
|
150
150
|
*/
|
|
151
|
-
async shutdown() {
|
|
151
|
+
async shutdown(): Promise<void> {
|
|
152
152
|
while (this.#pendingAcquires) {
|
|
153
153
|
await Util.wait(10);
|
|
154
154
|
}
|
package/src/support/barrier.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Util, ShutdownManager, TimeSpan } from '@travetto/base';
|
|
|
2
2
|
import { Timeout } from './timeout';
|
|
3
3
|
|
|
4
4
|
function canCancel(o: unknown): o is { cancel(): unknown } {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
5
6
|
return !!o && 'cancel' in (o as object);
|
|
6
7
|
}
|
|
7
8
|
|
|
@@ -9,7 +10,7 @@ function canCancel(o: unknown): o is { cancel(): unknown } {
|
|
|
9
10
|
* Build an execution barrier to handle various limitations
|
|
10
11
|
*/
|
|
11
12
|
export class Barrier {
|
|
12
|
-
#support
|
|
13
|
+
#support: string[] = [];
|
|
13
14
|
#barriers = new Map<string, Promise<unknown>>([]);
|
|
14
15
|
|
|
15
16
|
constructor(
|
|
@@ -27,7 +28,7 @@ export class Barrier {
|
|
|
27
28
|
/**
|
|
28
29
|
* Add a new barrier
|
|
29
30
|
*/
|
|
30
|
-
add(p: (() => Promise<unknown>) | Promise<unknown>, support = false) {
|
|
31
|
+
add(p: (() => Promise<unknown>) | Promise<unknown>, support = false): this {
|
|
31
32
|
if (!('then' in p)) {
|
|
32
33
|
p = p();
|
|
33
34
|
}
|
|
@@ -49,7 +50,7 @@ export class Barrier {
|
|
|
49
50
|
/**
|
|
50
51
|
* Clean up, and cancel all cancellable barriers
|
|
51
52
|
*/
|
|
52
|
-
cleanup() {
|
|
53
|
+
cleanup(): void {
|
|
53
54
|
for (const k of this.#support) {
|
|
54
55
|
const el = this.#barriers.get(k);
|
|
55
56
|
if (canCancel(el)) {
|
|
@@ -63,11 +64,11 @@ export class Barrier {
|
|
|
63
64
|
* Wait for all barriers to clear out
|
|
64
65
|
*/
|
|
65
66
|
async wait(): Promise<Error | undefined> {
|
|
66
|
-
let
|
|
67
|
+
let capturedError: Error | undefined;
|
|
67
68
|
// Wait for all barriers to be satisfied
|
|
68
69
|
while (this.#barriers.size) {
|
|
69
|
-
await Promise.race(this.#barriers.values()).catch(
|
|
70
|
+
await Promise.race(this.#barriers.values()).catch(err => capturedError ??= err);
|
|
70
71
|
}
|
|
71
|
-
return
|
|
72
|
+
return capturedError;
|
|
72
73
|
}
|
|
73
74
|
}
|
package/src/support/timeout.ts
CHANGED
|
@@ -18,7 +18,7 @@ export class Timeout extends ExecutionError {
|
|
|
18
18
|
/**
|
|
19
19
|
* Stop timeout from firing
|
|
20
20
|
*/
|
|
21
|
-
cancel() {
|
|
21
|
+
cancel(): void {
|
|
22
22
|
if (this.#id) {
|
|
23
23
|
clearTimeout(this.#id);
|
|
24
24
|
this.#promise.resolve();
|
|
@@ -29,7 +29,7 @@ export class Timeout extends ExecutionError {
|
|
|
29
29
|
/**
|
|
30
30
|
* Wait for timeout as a promise
|
|
31
31
|
*/
|
|
32
|
-
wait() {
|
|
32
|
+
wait(): Promise<void> {
|
|
33
33
|
if (!this.#id) {
|
|
34
34
|
this.#id = setTimeout(() => this.#promise.reject(this), this.#duration);
|
|
35
35
|
this.#id.unref();
|
package/src/util.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { Worker } from './pool';
|
|
|
6
6
|
type Simple<V> = (ch: ParentCommChannel<V>) => Promise<unknown | void>;
|
|
7
7
|
type Param<V, X> = (ch: ParentCommChannel<V>, input: X) => Promise<unknown | void>;
|
|
8
8
|
|
|
9
|
-
const empty = async () => { };
|
|
9
|
+
const empty = async (): Promise<void> => { };
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Spawned worker
|
|
@@ -22,11 +22,11 @@ export class WorkUtil {
|
|
|
22
22
|
destroy: Simple<V> = empty): Worker<X> {
|
|
23
23
|
const channel = new ParentCommChannel<V>(worker());
|
|
24
24
|
return {
|
|
25
|
-
get id() { return channel.id; },
|
|
26
|
-
get active() { return channel.active; },
|
|
25
|
+
get id(): number | undefined { return channel.id; },
|
|
26
|
+
get active(): boolean { return channel.active; },
|
|
27
27
|
init: () => init(channel),
|
|
28
28
|
execute: inp => execute(channel, inp),
|
|
29
|
-
async destroy() {
|
|
29
|
+
async destroy(): Promise<void> {
|
|
30
30
|
await destroy(channel);
|
|
31
31
|
await channel.destroy();
|
|
32
32
|
},
|