@rdfc/js-runner 3.0.3 → 3.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.
package/lib/writer.js CHANGED
@@ -9,6 +9,10 @@ export class WriterInstance {
9
9
  awaitingProcessed = [];
10
10
  openStreams = 0;
11
11
  shouldClose = [];
12
+ closed = false;
13
+ _canceled = false;
14
+ cancelSignal = new AbortController();
15
+ cancelHandlers = new Set();
12
16
  runnerId;
13
17
  constructor(uri, client, notifyOrchestrator, runnerId, logger) {
14
18
  this.client = client;
@@ -17,8 +21,62 @@ export class WriterInstance {
17
21
  this.logger = logger;
18
22
  this.runnerId = runnerId;
19
23
  }
24
+ get canceled() {
25
+ return this._canceled;
26
+ }
27
+ on(event, listener) {
28
+ if (event === 'cancel') {
29
+ this.cancelHandlers.add(listener);
30
+ }
31
+ return this;
32
+ }
33
+ cancellationError() {
34
+ return new Error(`Writer for channel ${this.uri} was canceled by the connected reader`);
35
+ }
36
+ emitCancel() {
37
+ for (const handler of this.cancelHandlers) {
38
+ try {
39
+ Promise.resolve(handler()).catch((error) => {
40
+ this.logger.error(`Cancel listener for channel ${this.uri} failed: ${String(error)}`);
41
+ });
42
+ }
43
+ catch (error) {
44
+ this.logger.error(`Cancel listener for channel ${this.uri} failed: ${String(error)}`);
45
+ }
46
+ }
47
+ }
48
+ assertCanWrite() {
49
+ if (this._canceled) {
50
+ throw this.cancellationError();
51
+ }
52
+ if (this.closed) {
53
+ throw new Error(`Writer for channel ${this.uri} is closed`);
54
+ }
55
+ }
56
+ async raceWithCancellation(promise) {
57
+ this.assertCanWrite();
58
+ return await new Promise((resolve, reject) => {
59
+ const onAbort = () => reject(this.cancellationError());
60
+ this.cancelSignal.signal.addEventListener('abort', onAbort, {
61
+ once: true,
62
+ });
63
+ promise.then((value) => {
64
+ this.cancelSignal.signal.removeEventListener('abort', onAbort);
65
+ resolve(value);
66
+ }, (error) => {
67
+ this.cancelSignal.signal.removeEventListener('abort', onAbort);
68
+ reject(error);
69
+ });
70
+ });
71
+ }
72
+ rejectPendingProcessed(error) {
73
+ while (this.awaitingProcessed.length > 0) {
74
+ this.awaitingProcessed.shift().reject(error);
75
+ }
76
+ }
20
77
  awaitProcessed() {
21
- return new Promise((res) => this.awaitingProcessed.push(res));
78
+ this.assertCanWrite();
79
+ return new Promise((resolve, reject) => this.awaitingProcessed.push({ resolve, reject }));
22
80
  }
23
81
  async any(any) {
24
82
  if ('stream' in any) {
@@ -32,6 +90,7 @@ export class WriterInstance {
32
90
  }
33
91
  }
34
92
  async buffer(buffer) {
93
+ this.assertCanWrite();
35
94
  this.logger.debug(`${this.uri} sends buffer ${buffer.length} bytes`);
36
95
  const localSequenceNumber = this.localSequenceNumber++;
37
96
  const handledPromise = this.awaitProcessed();
@@ -41,33 +100,43 @@ export class WriterInstance {
41
100
  await handledPromise;
42
101
  }
43
102
  async stream(buffer, transform) {
103
+ this.assertCanWrite();
44
104
  this.openStreams += 1;
45
105
  const t = transform || ((x) => x);
46
106
  const stream = this.client.sendStreamMessage();
47
- const handledPromise = this.awaitProcessed();
48
- const writeStreamMessageChunk = promisify(stream.write.bind(stream));
49
- const localSequenceNumber = this.localSequenceNumber++;
50
- await writeStreamMessageChunk({
51
- id: {
52
- channel: this.uri,
53
- localSequenceNumber,
54
- runner: this.runnerId,
55
- },
56
- });
57
- const id = await new Promise((res) => stream.once('data', res));
58
- this.logger.debug(`${this.uri} streams message with id ${JSON.stringify(id)}`);
59
- for await (const msg of buffer) {
60
- const processedPromise = new Promise((res) => stream.once('data', res));
61
- await writeStreamMessageChunk({ data: { data: t(msg) } });
62
- await processedPromise;
63
- }
64
- stream.end();
65
- await handledPromise;
66
- this.openStreams -= 1;
67
- if (this.shouldClose.length > 0)
68
- await this.close();
107
+ try {
108
+ const handledPromise = this.awaitProcessed();
109
+ const writeStreamMessageChunk = promisify(stream.write.bind(stream));
110
+ const localSequenceNumber = this.localSequenceNumber++;
111
+ await writeStreamMessageChunk({
112
+ id: {
113
+ channel: this.uri,
114
+ localSequenceNumber,
115
+ runner: this.runnerId,
116
+ },
117
+ });
118
+ const id = await this.raceWithCancellation(new Promise((res) => stream.once('data', res)));
119
+ this.logger.debug(`${this.uri} streams message with id ${JSON.stringify(id)}`);
120
+ for await (const msg of buffer) {
121
+ const processedPromise = new Promise((res) => stream.once('data', res));
122
+ await writeStreamMessageChunk({ data: { data: t(msg) } });
123
+ await processedPromise;
124
+ }
125
+ stream.end();
126
+ await handledPromise;
127
+ }
128
+ finally {
129
+ this.openStreams -= 1;
130
+ if (!stream.writableEnded) {
131
+ stream.end();
132
+ }
133
+ if (this.shouldClose.length > 0) {
134
+ await this.close();
135
+ }
136
+ }
69
137
  }
70
138
  async string(msg) {
139
+ this.assertCanWrite();
71
140
  this.logger.debug(`${this.uri} sends string ${msg.length} characters`);
72
141
  const localSequenceNumber = this.localSequenceNumber++;
73
142
  const handledPromise = this.awaitProcessed();
@@ -81,16 +150,34 @@ export class WriterInstance {
81
150
  await handledPromise;
82
151
  }
83
152
  async close(issued = false) {
153
+ if (issued) {
154
+ if (!this.closed) {
155
+ this._canceled = true;
156
+ this.emitCancel();
157
+ }
158
+ this.closed = true;
159
+ const cancelError = this.cancellationError();
160
+ this.rejectPendingProcessed(cancelError);
161
+ this.cancelSignal.abort(cancelError);
162
+ let waiting = this.shouldClose.pop();
163
+ while (waiting) {
164
+ waiting();
165
+ waiting = this.shouldClose.pop();
166
+ }
167
+ return;
168
+ }
169
+ if (this.closed) {
170
+ return;
171
+ }
84
172
  if (this.openStreams !== 0) {
85
173
  await new Promise((resolve) => this.shouldClose.push(resolve));
86
174
  return;
87
175
  }
88
176
  this.logger.debug(`${this.uri} closes stream`);
89
- if (!issued) {
90
- await this.notifyOrchestrator({
91
- close: { channel: this.uri },
92
- });
93
- }
177
+ this.closed = true;
178
+ await this.notifyOrchestrator({
179
+ close: { channel: this.uri },
180
+ });
94
181
  let resolve = this.shouldClose.pop();
95
182
  while (resolve) {
96
183
  resolve();
@@ -99,7 +186,10 @@ export class WriterInstance {
99
186
  }
100
187
  handled() {
101
188
  if (this.awaitingProcessed.length > 0) {
102
- this.awaitingProcessed.shift()();
189
+ this.awaitingProcessed.shift().resolve();
190
+ }
191
+ else if (this.closed || this._canceled) {
192
+ return;
103
193
  }
104
194
  else {
105
195
  this.logger.error('Expected to be waiting for a message to be processed, but this is not the case ' +
@@ -107,4 +197,4 @@ export class WriterInstance {
107
197
  }
108
198
  }
109
199
  }
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBbUJoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBRXZCLGlCQUFpQixHQUFzQixFQUFFLENBQUE7SUFFekMsV0FBVyxHQUFXLENBQUMsQ0FBQTtJQUN2QixXQUFXLEdBQXNCLEVBQUUsQ0FBQTtJQUUxQixRQUFRLENBQVE7SUFFakMsWUFDRSxHQUFXLEVBQ1gsTUFBb0IsRUFDcEIsa0JBQTRCLEVBQzVCLFFBQWdCLEVBQ2hCLE1BQWM7UUFFZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUE7UUFDNUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUE7UUFDZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtJQUMxQixDQUFDO0lBRU8sY0FBYztRQUNwQixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDL0QsQ0FBQztJQUVELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBUTtRQUNoQixJQUFJLFFBQVEsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FB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R0FBRyxFQUFFLENBQUE7UUFDcEMsT0FBTyxPQUFPLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxDQUFBO1lBQ1QsT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDbEMsQ0FBQztJQUNILENBQUM7SUFLRCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUcsRUFBRSxDQUFBO1FBQ25DLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsaUZBQWlGO2dCQUMvRSxJQUFJLENBQUMsR0FBRyxDQUNYLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG4gIHN0cmVhbTxUPihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtOiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cbiAgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPlxuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+XG59XG5jb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKClcbmV4cG9ydCBjbGFzcyBXcml0ZXJJbnN0YW5jZSBpbXBsZW1lbnRzIFdyaXRlciB7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nXG4gIGxvY2FsU2VxdWVuY2VOdW1iZXI6IG51bWJlciA9IDFcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJ1bm5lckNsaWVudFxuICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGVcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IExvZ2dlclxuXG4gIHByaXZhdGUgYXdhaXRpbmdQcm9jZXNzZWQ6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIG9wZW5TdHJlYW1zOiBudW1iZXIgPSAwXG4gIHByaXZhdGUgc2hvdWxkQ2xvc2U6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIHJlYWRvbmx5IHJ1bm5lcklkOiBzdHJpbmdcblxuICBjb25zdHJ1Y3RvcihcbiAgICB1cmk6IHN0cmluZyxcbiAgICBjbGllbnQ6IFJ1bm5lckNsaWVudCxcbiAgICBub3RpZnlPcmNoZXN0cmF0b3I6IFdyaXRhYmxlLFxuICAgIHJ1bm5lcklkOiBzdHJpbmcsXG4gICAgbG9nZ2VyOiBMb2dnZXIsXG4gICkge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50XG4gICAgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3IgPSBub3RpZnlPcmNoZXN0cmF0b3JcbiAgICB0aGlzLnVyaSA9IHVyaVxuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyXG4gICAgdGhpcy5ydW5uZXJJZCA9IHJ1bm5lcklkXG4gIH1cblxuICBwcml2YXRlIGF3YWl0UHJvY2Vzc2VkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzKSA9PiB0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLnB1c2gocmVzKSlcbiAgfVxuXG4gIGFzeW5jIGFueShhbnk6IEFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICgnc3RyZWFtJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyZWFtKGFueS5zdHJlYW0pXG4gICAgfVxuICAgIGlmICgnYnVmZmVyJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnVmZmVyKGFueS5idWZmZXIpXG4gICAgfVxuICAgIGlmICgnc3RyaW5nJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyaW5nKGFueS5zdHJpbmcpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBidWZmZXIgJHtidWZmZXIubGVuZ3RofSBieXRlc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgaGFuZGxlZFByb21pc2UgPSB0aGlzLmF3YWl0UHJvY2Vzc2VkKClcblxuICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgIG1zZzogeyBkYXRhOiBidWZmZXIsIGNoYW5uZWw6IHRoaXMudXJpLCBsb2NhbFNlcXVlbmNlTnVtYmVyIH0sXG4gICAgfSlcbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgYXN5bmMgc3RyZWFtPFQgPSBVaW50OEFycmF5PihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtPzogKHg6IFQpID0+IFVpbnQ4QXJyYXksXG4gICkge1xuICAgIHRoaXMub3BlblN0cmVhbXMgKz0gMVxuICAgIGNvbnN0IHQgPSB0cmFuc2Zvcm0gfHwgKCh4OiB1bmtub3duKSA9PiA8VWludDhBcnJheT54KVxuICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuY2xpZW50LnNlbmRTdHJlYW1NZXNzYWdlKClcblxuICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG4gICAgY29uc3Qgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsgPSBwcm9taXNpZnkoc3RyZWFtLndyaXRlLmJpbmQoc3RyZWFtKSlcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBhd2FpdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayh7XG4gICAgICBpZDoge1xuICAgICAgICBjaGFubmVsOiB0aGlzLnVyaSxcbiAgICAgICAgbG9jYWxTZXF1ZW5jZU51bWJlcixcbiAgICAgICAgcnVubmVyOiB0aGlzLnJ1bm5lcklkLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgaWQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzKSA9PiBzdHJlYW0ub25jZSgnZGF0YScsIHJlcykpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgIGAke3RoaXMudXJpfSBzdHJlYW1zIG1lc3NhZ2Ugd2l0aCBpZCAke0pTT04uc3RyaW5naWZ5KGlkKX1gLFxuICAgIClcblxuICAgIGZvciBhd2FpdCAoY29uc3QgbXNnIG9mIGJ1ZmZlcikge1xuICAgICAgY29uc3QgcHJvY2Vzc2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcbiAgICAgIGF3YWl0IHdyaXRlU3RyZWFtTWVzc2FnZUNodW5rKHsgZGF0YTogeyBkYXRhOiB0KG1zZykgfSB9KVxuICAgICAgLy8gQXdhaXQgYSBtZXNzYWdlIG9uIHRoZSBzdHJlYW0sIGluZGljYXRpbmcgdGhhdCB0aGUgY2h1bmsgaGFzIGJlZW4gcHJvY2Vzc2VkXG4gICAgICBhd2FpdCBwcm9jZXNzZWRQcm9taXNlXG4gICAgfVxuXG4gICAgc3RyZWFtLmVuZCgpXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuXG4gICAgdGhpcy5vcGVuU3RyZWFtcyAtPSAxXG5cbiAgICBpZiAodGhpcy5zaG91bGRDbG9zZS5sZW5ndGggPiAwKSBhd2FpdCB0aGlzLmNsb3NlKClcbiAgfVxuXG4gIGFzeW5jIHN0cmluZyhtc2c6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBzdHJpbmcgJHttc2cubGVuZ3RofSBjaGFyYWN0ZXJzYClcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoKVxuXG4gICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgbXNnOiB7XG4gICAgICAgIGRhdGE6IGVuY29kZXIuZW5jb2RlKG1zZyksXG4gICAgICAgIGNoYW5uZWw6IHRoaXMudXJpLFxuICAgICAgICBsb2NhbFNlcXVlbmNlTnVtYmVyLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgYXdhaXQgaGFuZGxlZFByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFjZWZ1bGx5IGNsb3NlcyB0aGlzIGNoYW5uZWwuXG4gICAqXG4gICAqIEJlaGF2aW9yOlxuICAgKiAtIElmIHRoZXJlIGFyZSBzdGlsbCBhY3RpdmUgc3RyZWFtcywgY2xvc2luZyBpcyBkZWZlcnJlZCB1bnRpbCB0aGV5IGNvbXBsZXRlLlxuICAgKiAtIElmIG11bHRpcGxlIGNhbGxlcnMgaW52b2tlIGBjbG9zZSgpYCB3aGlsZSB3YWl0aW5nLCB0aGVpciBQcm9taXNlcyBhcmUgcXVldWVkIGFuZFxuICAgKiAgIHJlc29sdmVkIG9uY2UgdGhlIGNoYW5uZWwgYWN0dWFsbHkgY2xvc2VzLlxuICAgKiAtIElmIHRoaXMgc2lkZSBpbml0aWF0ZWQgdGhlIGNsb3NlIChgaXNzdWVkID0gZmFsc2VgKSwgYSBjbG9zZSBtZXNzYWdlIGlzIHNlbnQgdG8gdGhlIHJlbW90ZS5cbiAgICpcbiAgICogQHBhcmFtIGlzc3VlZCAtIElmIHRydWUsIGluZGljYXRlcyB0aGUgY2xvc2UgcmVxdWVzdCBvcmlnaW5hdGVkIHJlbW90ZWx5XG4gICAqL1xuICBhc3luYyBjbG9zZShpc3N1ZWQgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIENhc2UgMTogQWN0aXZlIHN0cmVhbXMgc3RpbGwgcnVubmluZyDihpIgd2FpdCB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBObyBhY3RpdmUgc3RyZWFtcyDihpIgcGVyZm9ybSBhY3R1YWwgY2xvc2VcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gY2xvc2VzIHN0cmVhbWApXG4gICAgaWYgKCFpc3N1ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgICAgY2xvc2U6IHsgY2hhbm5lbDogdGhpcy51cmkgfSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IHJlc29sdmUgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgd2hpbGUgKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUoKVxuICAgICAgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBtZXNzYWdlIGlzIGhhbmRsZWQsIGxldCdzIG5vdGlmeSB0aGUgZmlmbyB7QGxpbmsgYXdhaXRQcm9jZXNzZWR9XG4gICAqL1xuICBoYW5kbGVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0V4cGVjdGVkIHRvIGJlIHdhaXRpbmcgZm9yIGEgbWVzc2FnZSB0byBiZSBwcm9jZXNzZWQsIGJ1dCB0aGlzIGlzIG5vdCB0aGUgY2FzZSAnICtcbiAgICAgICAgICB0aGlzLnVyaSxcbiAgICAgIClcbiAgICB9XG4gIH1cbn1cbiJdfQ==
200
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBeUJoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBR3ZCLGlCQUFpQixHQUdwQixFQUFFLENBQUE7SUFFQyxXQUFXLEdBQVcsQ0FBQyxDQUFBO0lBRXZCLFdBQVcsR0FBc0IsRUFBRSxDQUFBO0lBQ25DLE1BQU0sR0FBRyxLQUFLLENBQUE7SUFDZCxTQUFTLEdBQUcsS0FBSyxDQUFBO0lBR1IsWUFBWSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUE7SUFFcEMsY0FBYyxHQUFHLElBQUksR0FBRyxFQUFXLENBQUE7SUFFbkMsUUFBUSxDQUFRO0lBRWpDLFlBQ0UsR0FBVyxFQUNYLE1BQW9CLEVBQ3BCLGtCQUE0QixFQUM1QixRQUFnQixFQUNoQixNQUFjO1FBRWQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFBO1FBQzVDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO1FBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7SUFDMUIsQ0FBQztJQUVELElBQUksUUFBUTtRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQTtJQUN2QixDQUFDO0lBRUQsRUFBRSxDQUFDLEtBQWUsRUFBRSxRQUFpQjtRQUNuQyxJQUFJLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN2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RUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtTQUM3QixDQUFDLENBQUE7UUFFRixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQ3BDLE9BQU8sT0FBTyxFQUFFLENBQUM7WUFDZixPQUFPLEVBQUUsQ0FBQTtZQUNULE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQ2xDLENBQUM7SUFDSCxDQUFDO0lBS0QsT0FBTztRQUNMLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFHLENBQUMsT0FBTyxFQUFFLENBQUE7UUFDM0MsQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFFekMsT0FBTTtRQUNSLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsaUZBQWlGO2dCQUMvRSxJQUFJLENBQUMsR0FBRyxDQUNYLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IHR5cGUgSGFuZGxlcjxUID0gdm9pZD4gPSBbVF0gZXh0ZW5kcyBbdm9pZF1cbiAgPyAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICA6ICh2YWx1ZTogVCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD5cblxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICByZWFkb25seSBjYW5jZWxlZDogYm9vbGVhblxuICBvbihldmVudDogJ2NhbmNlbCcsIGxpc3RlbmVyOiBIYW5kbGVyKTogdGhpc1xuICBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG4gIHN0cmVhbTxUPihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtOiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cbiAgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPlxuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+XG59XG5jb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKClcbmV4cG9ydCBjbGFzcyBXcml0ZXJJbnN0YW5jZSBpbXBsZW1lbnRzIFdyaXRlciB7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nXG4gIGxvY2FsU2VxdWVuY2VOdW1iZXI6IG51bWJlciA9IDFcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJ1bm5lckNsaWVudFxuICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGVcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IExvZ2dlclxuXG4gIC8vIEZJRk8gb2YgbWVzc2FnZS1sZXZlbCBhY2tub3dsZWRnZW1lbnRzIGNvbWluZyBiYWNrIGZyb20gdGhlIG9yY2hlc3RyYXRvci5cbiAgcHJpdmF0ZSBhd2FpdGluZ1Byb2Nlc3NlZDogQXJyYXk8e1xuICAgIHJlc29sdmU6ICgpID0+IHZvaWRcbiAgICByZWplY3Q6IChyZWFzb246IEVycm9yKSA9PiB2b2lkXG4gIH0+ID0gW11cblxuICBwcml2YXRlIG9wZW5TdHJlYW1zOiBudW1iZXIgPSAwXG4gIC8vIENsb3NlIGNhbGxlcnMgd2FpdCBoZXJlIHdoaWxlIGFjdGl2ZSBzdHJlYW1zIGFyZSBzdGlsbCBmbHVzaGluZy5cbiAgcHJpdmF0ZSBzaG91bGRDbG9zZTogQXJyYXk8KCkgPT4gdm9pZD4gPSBbXVxuICBwcml2YXRlIGNsb3NlZCA9IGZhbHNlXG4gIHByaXZhdGUgX2NhbmNlbGVkID0gZmFsc2VcblxuICAvLyBTaGFyZWQgY2FuY2VsbGF0aW9uIHNpZ25hbCB0byBhYm9ydCBpbi1mbGlnaHQgd2FpdHMgd2hlbiB0aGUgcmVtb3RlIGNsb3Nlcy5cbiAgcHJpdmF0ZSByZWFkb25seSBjYW5jZWxTaWduYWwgPSBuZXcgQWJvcnRDb250cm9sbGVyKClcbiAgLy8gUHJvY2Vzc29ycyBjYW4gc3Vic2NyaWJlIGhlcmUgdG8gc3RvcCB1cHN0cmVhbSB3b3JrIHdoZW4gZG93bnN0cmVhbSBjYW5jZWxzLlxuICBwcml2YXRlIHJlYWRvbmx5IGNhbmNlbEhhbmRsZXJzID0gbmV3IFNldDxIYW5kbGVyPigpXG5cbiAgcHJpdmF0ZSByZWFkb25seSBydW5uZXJJZDogc3RyaW5nXG5cbiAgY29uc3RydWN0b3IoXG4gICAgdXJpOiBzdHJpbmcsXG4gICAgY2xpZW50OiBSdW5uZXJDbGllbnQsXG4gICAgbm90aWZ5T3JjaGVzdHJhdG9yOiBXcml0YWJsZSxcbiAgICBydW5uZXJJZDogc3RyaW5nLFxuICAgIGxvZ2dlcjogTG9nZ2VyLFxuICApIHtcbiAgICB0aGlzLmNsaWVudCA9IGNsaWVudFxuICAgIHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yID0gbm90aWZ5T3JjaGVzdHJhdG9yXG4gICAgdGhpcy51cmkgPSB1cmlcbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlclxuICAgIHRoaXMucnVubmVySWQgPSBydW5uZXJJZFxuICB9XG5cbiAgZ2V0IGNhbmNlbGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9jYW5jZWxlZFxuICB9XG5cbiAgb24oZXZlbnQ6ICdjYW5jZWwnLCBsaXN0ZW5lcjogSGFuZGxlcik6IHRoaXMge1xuICAgIGlmIChldmVudCA9PT0gJ2NhbmNlbCcpIHtcbiAgICAgIHRoaXMuY2FuY2VsSGFuZGxlcnMuYWRkKGxpc3RlbmVyKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBwcml2YXRlIGNhbmNlbGxhdGlvbkVycm9yKCk6IEVycm9yIHtcbiAgICByZXR1cm4gbmV3IEVycm9yKFxuICAgICAgYFdyaXRlciBmb3IgY2hhbm5lbCAke3RoaXMudXJpfSB3YXMgY2FuY2VsZWQgYnkgdGhlIGNvbm5lY3RlZCByZWFkZXJgLFxuICAgIClcbiAgfVxuXG4gIHByaXZhdGUgZW1pdENhbmNlbCgpIHtcbiAgICBmb3IgKGNvbnN0IGhhbmRsZXIgb2YgdGhpcy5jYW5jZWxIYW5kbGVycykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKGhhbmRsZXIoKSkuY2F0Y2goKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICBgQ2FuY2VsIGxpc3RlbmVyIGZvciBjaGFubmVsICR7dGhpcy51cml9IGZhaWxlZDogJHtTdHJpbmcoZXJyb3IpfWAsXG4gICAgICAgICAgKVxuICAgICAgICB9KVxuICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXG4gICAgICAgICAgYENhbmNlbCBsaXN0ZW5lciBmb3IgY2hhbm5lbCAke3RoaXMudXJpfSBmYWlsZWQ6ICR7U3RyaW5nKGVycm9yKX1gLFxuICAgICAgICApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnRDYW5Xcml0ZSgpIHtcbiAgICBpZiAodGhpcy5fY2FuY2VsZWQpIHtcbiAgICAgIHRocm93IHRoaXMuY2FuY2VsbGF0aW9uRXJyb3IoKVxuICAgIH1cblxuICAgIGlmICh0aGlzLmNsb3NlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBXcml0ZXIgZm9yIGNoYW5uZWwgJHt0aGlzLnVyaX0gaXMgY2xvc2VkYClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJhY2VXaXRoQ2FuY2VsbGF0aW9uPFQ+KHByb21pc2U6IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICB0aGlzLmFzc2VydENhbldyaXRlKClcblxuICAgIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBvbkFib3J0ID0gKCkgPT4gcmVqZWN0KHRoaXMuY2FuY2VsbGF0aW9uRXJyb3IoKSlcbiAgICAgIHRoaXMuY2FuY2VsU2lnbmFsLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uQWJvcnQsIHtcbiAgICAgICAgb25jZTogdHJ1ZSxcbiAgICAgIH0pXG5cbiAgICAgIHByb21pc2UudGhlbihcbiAgICAgICAgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgLy8gQ2xlYW4gdXAgdGhlIGFib3J0IGxpc3RlbmVyIGlmIHRoZSBvcmlnaW5hbCBvcGVyYXRpb24gZmluaXNoZWQgZmlyc3QuXG4gICAgICAgICAgdGhpcy5jYW5jZWxTaWduYWwuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0Jywgb25BYm9ydClcbiAgICAgICAgICByZXNvbHZlKHZhbHVlKVxuICAgICAgICB9LFxuICAgICAgICAoZXJyb3IpID0+IHtcbiAgICAgICAgICB0aGlzLmNhbmNlbFNpZ25hbC5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBvbkFib3J0KVxuICAgICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSByZWplY3RQZW5kaW5nUHJvY2Vzc2VkKGVycm9yOiBFcnJvcikge1xuICAgIC8vIFJlamVjdCBhbGwgcXVldWVkIG1lc3NhZ2Ugd2FpdHMgc28gY2FsbGVycyBkbyBub3QgaGFuZyBkdXJpbmcgY2FuY2VsbGF0aW9uLlxuICAgIHdoaWxlICh0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEucmVqZWN0KGVycm9yKVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXdhaXRQcm9jZXNzZWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hc3NlcnRDYW5Xcml0ZSgpXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICB0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLnB1c2goeyByZXNvbHZlLCByZWplY3QgfSksXG4gICAgKVxuICB9XG5cbiAgYXN5bmMgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCdzdHJlYW0nIGluIGFueSkge1xuICAgICAgYXdhaXQgdGhpcy5zdHJlYW0oYW55LnN0cmVhbSlcbiAgICB9XG4gICAgaWYgKCdidWZmZXInIGluIGFueSkge1xuICAgICAgYXdhaXQgdGhpcy5idWZmZXIoYW55LmJ1ZmZlcilcbiAgICB9XG4gICAgaWYgKCdzdHJpbmcnIGluIGFueSkge1xuICAgICAgYXdhaXQgdGhpcy5zdHJpbmcoYW55LnN0cmluZylcbiAgICB9XG4gIH1cblxuICBhc3luYyBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hc3NlcnRDYW5Xcml0ZSgpXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYCR7dGhpcy51cml9IHNlbmRzIGJ1ZmZlciAke2J1ZmZlci5sZW5ndGh9IGJ5dGVzYClcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoKVxuXG4gICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgbXNnOiB7IGRhdGE6IGJ1ZmZlciwgY2hhbm5lbDogdGhpcy51cmksIGxvY2FsU2VxdWVuY2VOdW1iZXIgfSxcbiAgICB9KVxuICAgIGF3YWl0IGhhbmRsZWRQcm9taXNlXG4gIH1cblxuICBhc3luYyBzdHJlYW08VCA9IFVpbnQ4QXJyYXk+KFxuICAgIGJ1ZmZlcjogQXN5bmNJdGVyYWJsZTxUPixcbiAgICB0cmFuc2Zvcm0/OiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKSB7XG4gICAgdGhpcy5hc3NlcnRDYW5Xcml0ZSgpXG4gICAgdGhpcy5vcGVuU3RyZWFtcyArPSAxXG4gICAgY29uc3QgdCA9IHRyYW5zZm9ybSB8fCAoKHg6IHVua25vd24pID0+IDxVaW50OEFycmF5PngpXG4gICAgY29uc3Qgc3RyZWFtID0gdGhpcy5jbGllbnQuc2VuZFN0cmVhbU1lc3NhZ2UoKVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIE1lc3NhZ2UtbGV2ZWwgYWNrIHRoYXQgc2lnbmFscyB0aGUgd2hvbGUgc3RyZWFtIG1lc3NhZ2UgaXMgZnVsbHkgaGFuZGxlZC5cbiAgICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG4gICAgICBjb25zdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayA9IHByb21pc2lmeShzdHJlYW0ud3JpdGUuYmluZChzdHJlYW0pKVxuICAgICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgICBhd2FpdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayh7XG4gICAgICAgIGlkOiB7XG4gICAgICAgICAgY2hhbm5lbDogdGhpcy51cmksXG4gICAgICAgICAgbG9jYWxTZXF1ZW5jZU51bWJlcixcbiAgICAgICAgICBydW5uZXI6IHRoaXMucnVubmVySWQsXG4gICAgICAgIH0sXG4gICAgICB9KVxuXG4gICAgICAvLyBGaXJzdCByZXNwb25zZSBjb25maXJtcyBzdHJlYW0gaWQgcmVnaXN0cmF0aW9uIG9uIHRoZSByZW1vdGUgc2lkZS5cbiAgICAgIGNvbnN0IGlkID0gYXdhaXQgdGhpcy5yYWNlV2l0aENhbmNlbGxhdGlvbihcbiAgICAgICAgbmV3IFByb21pc2UoKHJlcykgPT4gc3RyZWFtLm9uY2UoJ2RhdGEnLCByZXMpKSxcbiAgICAgIClcblxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgIGAke3RoaXMudXJpfSBzdHJlYW1zIG1lc3NhZ2Ugd2l0aCBpZCAke0pTT04uc3RyaW5naWZ5KGlkKX1gLFxuICAgICAgKVxuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IG1zZyBvZiBidWZmZXIpIHtcbiAgICAgICAgY29uc3QgcHJvY2Vzc2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcbiAgICAgICAgYXdhaXQgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsoeyBkYXRhOiB7IGRhdGE6IHQobXNnKSB9IH0pXG4gICAgICAgIC8vIEF3YWl0IGEgbWVzc2FnZSBvbiB0aGUgc3RyZWFtLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGNodW5rIGhhcyBiZWVuIHByb2Nlc3NlZFxuICAgICAgICBhd2FpdCBwcm9jZXNzZWRQcm9taXNlXG4gICAgICB9XG5cbiAgICAgIHN0cmVhbS5lbmQoKVxuXG4gICAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm9wZW5TdHJlYW1zIC09IDFcblxuICAgICAgaWYgKCFzdHJlYW0ud3JpdGFibGVFbmRlZCkge1xuICAgICAgICBzdHJlYW0uZW5kKClcbiAgICAgIH1cblxuICAgICAgLy8gSWYgYSBjbG9zZSBjYWxsIHdhcyBkZWZlcnJlZCB3aGlsZSBzdHJlYW1pbmcsIGNvbXBsZXRlIGl0IG5vdy5cbiAgICAgIGlmICh0aGlzLnNob3VsZENsb3NlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jbG9zZSgpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc3RyaW5nKG1zZzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hc3NlcnRDYW5Xcml0ZSgpXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYCR7dGhpcy51cml9IHNlbmRzIHN0cmluZyAke21zZy5sZW5ndGh9IGNoYXJhY3RlcnNgKVxuICAgIGNvbnN0IGxvY2FsU2VxdWVuY2VOdW1iZXIgPSB0aGlzLmxvY2FsU2VxdWVuY2VOdW1iZXIrK1xuICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG5cbiAgICBhd2FpdCB0aGlzLm5vdGlmeU9yY2hlc3RyYXRvcih7XG4gICAgICBtc2c6IHtcbiAgICAgICAgZGF0YTogZW5jb2Rlci5lbmNvZGUobXNnKSxcbiAgICAgICAgY2hhbm5lbDogdGhpcy51cmksXG4gICAgICAgIGxvY2FsU2VxdWVuY2VOdW1iZXIsXG4gICAgICB9LFxuICAgIH0pXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIEdyYWNlZnVsbHkgY2xvc2VzIHRoaXMgY2hhbm5lbC5cbiAgICpcbiAgICogQmVoYXZpb3I6XG4gICAqIC0gSWYgdGhlcmUgYXJlIHN0aWxsIGFjdGl2ZSBzdHJlYW1zLCBjbG9zaW5nIGlzIGRlZmVycmVkIHVudGlsIHRoZXkgY29tcGxldGUuXG4gICAqIC0gSWYgbXVsdGlwbGUgY2FsbGVycyBpbnZva2UgYGNsb3NlKClgIHdoaWxlIHdhaXRpbmcsIHRoZWlyIFByb21pc2VzIGFyZSBxdWV1ZWQgYW5kXG4gICAqICAgcmVzb2x2ZWQgb25jZSB0aGUgY2hhbm5lbCBhY3R1YWxseSBjbG9zZXMuXG4gICAqIC0gSWYgdGhpcyBzaWRlIGluaXRpYXRlZCB0aGUgY2xvc2UgKGBpc3N1ZWQgPSBmYWxzZWApLCBhIGNsb3NlIG1lc3NhZ2UgaXMgc2VudCB0byB0aGUgcmVtb3RlLlxuICAgKlxuICAgKiBAcGFyYW0gaXNzdWVkIC0gSWYgdHJ1ZSwgaW5kaWNhdGVzIHRoZSBjbG9zZSByZXF1ZXN0IG9yaWdpbmF0ZWQgcmVtb3RlbHlcbiAgICovXG4gIGFzeW5jIGNsb3NlKGlzc3VlZCA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKGlzc3VlZCkge1xuICAgICAgaWYgKCF0aGlzLmNsb3NlZCkge1xuICAgICAgICAvLyBSZW1vdGUgaW5pdGlhdGVkIGNsb3NlOiBtYXJrIHdyaXRlciBjYW5jZWxlZCB0byBmYWlsIGZ1dHVyZSB3cml0ZXMuXG4gICAgICAgIHRoaXMuX2NhbmNlbGVkID0gdHJ1ZVxuXG4gICAgICAgIC8vIE5vdGlmeSBwcm9jZXNzb3JzIHNvIHRoZXkgY2FuIHN0b3AgcHJvZHVjaW5nIHVwc3RyZWFtIHdvcmsgYXMgd2VsbC5cbiAgICAgICAgdGhpcy5lbWl0Q2FuY2VsKClcbiAgICAgIH1cbiAgICAgIHRoaXMuY2xvc2VkID0gdHJ1ZVxuXG4gICAgICBjb25zdCBjYW5jZWxFcnJvciA9IHRoaXMuY2FuY2VsbGF0aW9uRXJyb3IoKVxuICAgICAgdGhpcy5yZWplY3RQZW5kaW5nUHJvY2Vzc2VkKGNhbmNlbEVycm9yKVxuICAgICAgdGhpcy5jYW5jZWxTaWduYWwuYWJvcnQoY2FuY2VsRXJyb3IpXG5cbiAgICAgIC8vIFVuYmxvY2sgYW55IGxvY2FsIGNsb3NlKCkgY2FsbGVycyB3YWl0aW5nIGZvciBzdHJlYW1zIHRvIHNldHRsZS5cbiAgICAgIGxldCB3YWl0aW5nID0gdGhpcy5zaG91bGRDbG9zZS5wb3AoKVxuICAgICAgd2hpbGUgKHdhaXRpbmcpIHtcbiAgICAgICAgd2FpdGluZygpXG4gICAgICAgIHdhaXRpbmcgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgICB9XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIENhc2UgMTogQWN0aXZlIHN0cmVhbXMgc3RpbGwgcnVubmluZyDihpIgd2FpdCB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBObyBhY3RpdmUgc3RyZWFtcyDihpIgcGVyZm9ybSBhY3R1YWwgY2xvc2VcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gY2xvc2VzIHN0cmVhbWApXG4gICAgdGhpcy5jbG9zZWQgPSB0cnVlXG4gICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgY2xvc2U6IHsgY2hhbm5lbDogdGhpcy51cmkgfSxcbiAgICB9KVxuXG4gICAgbGV0IHJlc29sdmUgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgd2hpbGUgKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUoKVxuICAgICAgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBtZXNzYWdlIGlzIGhhbmRsZWQsIGxldCdzIG5vdGlmeSB0aGUgZmlmbyB7QGxpbmsgYXdhaXRQcm9jZXNzZWR9XG4gICAqL1xuICBoYW5kbGVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEucmVzb2x2ZSgpXG4gICAgfSBlbHNlIGlmICh0aGlzLmNsb3NlZCB8fCB0aGlzLl9jYW5jZWxlZCkge1xuICAgICAgLy8gQSBsYXRlIGFjayBjYW4gYXJyaXZlIGFmdGVyIGEgY2xvc2UvY2FuY2VsIHJhY2U7IG5vdGhpbmcgdG8gcmVzb2x2ZSBhbnltb3JlLlxuICAgICAgcmV0dXJuXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICAnRXhwZWN0ZWQgdG8gYmUgd2FpdGluZyBmb3IgYSBtZXNzYWdlIHRvIGJlIHByb2Nlc3NlZCwgYnV0IHRoaXMgaXMgbm90IHRoZSBjYXNlICcgK1xuICAgICAgICAgIHRoaXMudXJpLFxuICAgICAgKVxuICAgIH1cbiAgfVxufVxuIl19
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rdfc/js-runner",
3
- "version": "3.0.3",
3
+ "version": "3.1.0-alpha.1",
4
4
  "main": "lib/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -37,21 +37,21 @@
37
37
  "@rdfjs/types": "^2.0.1",
38
38
  "@types/jsonld": "^1.5.15",
39
39
  "@types/n3": "^1.26.1",
40
- "@types/node": "^25.3.3",
41
- "@typescript-eslint/eslint-plugin": "^8.56.1",
42
- "@typescript-eslint/parser": "^8.56.1",
43
- "@vitest/coverage-v8": "^4.0.18",
40
+ "@types/node": "^25.5.0",
41
+ "@typescript-eslint/eslint-plugin": "^8.57.2",
42
+ "@typescript-eslint/parser": "^8.57.2",
43
+ "@vitest/coverage-v8": "^4.1.1",
44
44
  "eslint": "^10.0.2",
45
45
  "eslint-config-prettier": "^10.1.8",
46
46
  "eslint-plugin-prettier": "^5.5.5",
47
- "globals": "^17.3.0",
47
+ "globals": "^17.4.0",
48
48
  "husky": "^9.1.7",
49
- "lint-staged": "^16.3.0",
49
+ "lint-staged": "^16.4.0",
50
50
  "prettier": "^3.8.1",
51
51
  "tsc-alias": "^1.8.16",
52
52
  "typescript": "^5.9.3",
53
- "typescript-eslint": "^8.56.1",
54
- "vitest": "^4.0.18"
53
+ "typescript-eslint": "^8.57.2",
54
+ "vitest": "^4.1.1"
55
55
  },
56
56
  "dependencies": {
57
57
  "@grpc/grpc-js": "^1.14.3",
@@ -59,8 +59,8 @@
59
59
  "@treecg/types": "^0.4.6",
60
60
  "jsonld": "^9.0.0",
61
61
  "jsonld-streaming-parser": "^5.0.1",
62
- "n3": "^2.0.1",
63
- "rdf-lens": "^1.3.6",
62
+ "n3": "^2.0.3",
63
+ "rdf-lens": "^1.3.7",
64
64
  "winston": "^3.19.0",
65
65
  "winston-transport": "^4.9.0"
66
66
  }
package/src/reader.ts CHANGED
@@ -33,6 +33,7 @@ export interface Reader {
33
33
  streams(): AsyncIterable<AsyncGenerator<Uint8Array>>
34
34
  buffers(): AsyncIterable<Uint8Array>
35
35
  anys(): AsyncIterable<Any>
36
+ cancel(): Promise<void>
36
37
  }
37
38
 
38
39
  type Todo<T> = {
@@ -44,12 +45,18 @@ class MyIter<T> implements AsyncIterable<T> {
44
45
  private convertor: Convertor<T>
45
46
  private queue: Todo<T | undefined>[] = []
46
47
  private resolveNext: ((value: undefined) => void) | null = null
48
+ private closed = false
47
49
 
48
50
  constructor(convertor: Convertor<T>) {
49
51
  this.convertor = convertor
50
52
  }
51
53
 
52
54
  push(buffer: Uint8Array, onComplete: () => void) {
55
+ if (this.closed) {
56
+ onComplete()
57
+ return
58
+ }
59
+
53
60
  const item = this.convertor.from(buffer)
54
61
  this.queue.push({ item, onComplete })
55
62
  if (this.resolveNext) {
@@ -59,6 +66,12 @@ class MyIter<T> implements AsyncIterable<T> {
59
66
  }
60
67
 
61
68
  close(onComplete: () => void) {
69
+ if (this.closed) {
70
+ onComplete()
71
+ return
72
+ }
73
+
74
+ this.closed = true
62
75
  this.queue.push({ item: undefined, onComplete })
63
76
  if (this.resolveNext) {
64
77
  this.resolveNext(undefined)
@@ -67,6 +80,11 @@ class MyIter<T> implements AsyncIterable<T> {
67
80
  }
68
81
 
69
82
  async pushStream(chunks: AsyncIterable<DataChunk>, onComplete: () => void) {
83
+ if (this.closed) {
84
+ onComplete()
85
+ return
86
+ }
87
+
70
88
  // This is an async generator that transforms DataChunks to Buffers
71
89
  const stream = (async function* (stream) {
72
90
  for await (const chunk of stream) {
@@ -108,6 +126,8 @@ export class ReaderInstance implements Reader {
108
126
  private readonly notifyOrchestrator: Writable
109
127
 
110
128
  private consumers: MyIter<unknown>[] = []
129
+ private closed = false
130
+ private canceled = false
111
131
 
112
132
  constructor(
113
133
  uri: string,
@@ -148,6 +168,16 @@ export class ReaderInstance implements Reader {
148
168
  handleMsg(msg: ReceivingMessage) {
149
169
  this.logger.debug(`${this.uri} handling message`)
150
170
 
171
+ if (this.closed) {
172
+ this.notifyOrchestrator({
173
+ processed: {
174
+ globalSequenceNumber: msg.globalSequenceNumber,
175
+ channel: this.uri,
176
+ },
177
+ })
178
+ return
179
+ }
180
+
151
181
  const promises = []
152
182
  for (const iter of this.consumers) {
153
183
  promises.push(new Promise((res) => iter.push(msg.data, () => res(null))))
@@ -164,11 +194,28 @@ export class ReaderInstance implements Reader {
164
194
  }
165
195
 
166
196
  close() {
197
+ if (this.closed) {
198
+ return
199
+ }
200
+
201
+ this.closed = true
167
202
  for (const iter of this.consumers) {
168
203
  iter.close(() => {})
169
204
  }
170
205
  }
171
206
 
207
+ async cancel(): Promise<void> {
208
+ if (this.canceled) {
209
+ return
210
+ }
211
+
212
+ this.canceled = true
213
+ this.close()
214
+ await this.notifyOrchestrator({
215
+ close: { channel: this.uri },
216
+ })
217
+ }
218
+
172
219
  // There is a stream message available for this reader
173
220
  async handleStreamingMessage({
174
221
  channel,
@@ -176,6 +223,13 @@ export class ReaderInstance implements Reader {
176
223
  }: ReceivingStreamMessage) {
177
224
  this.logger.debug(`${this.uri} handling streaming message`)
178
225
 
226
+ if (this.closed) {
227
+ await this.notifyOrchestrator({
228
+ processed: { globalSequenceNumber, channel },
229
+ })
230
+ return
231
+ }
232
+
179
233
  const chunks = this.client.receiveStreamMessage()
180
234
  const writeControlMessage = promisify(chunks.write.bind(chunks))
181
235
  const consumersConsumed = []