@rdfc/js-runner 3.0.3 → 3.1.0

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,9 @@ export class WriterInstance {
9
9
  awaitingProcessed = [];
10
10
  openStreams = 0;
11
11
  shouldClose = [];
12
+ closed = false;
13
+ _canceled = false;
14
+ cancelHandlers = new Set();
12
15
  runnerId;
13
16
  constructor(uri, client, notifyOrchestrator, runnerId, logger) {
14
17
  this.client = client;
@@ -17,8 +20,17 @@ export class WriterInstance {
17
20
  this.logger = logger;
18
21
  this.runnerId = runnerId;
19
22
  }
20
- awaitProcessed() {
21
- return new Promise((res) => this.awaitingProcessed.push(res));
23
+ get canceled() {
24
+ return this._canceled;
25
+ }
26
+ on(event, listener) {
27
+ if (event === 'cancel') {
28
+ this.cancelHandlers.add(listener);
29
+ }
30
+ return this;
31
+ }
32
+ cancellationError() {
33
+ return new Error(`Writer for channel ${this.uri} was canceled by the connected reader`);
22
34
  }
23
35
  async any(any) {
24
36
  if ('stream' in any) {
@@ -31,7 +43,16 @@ export class WriterInstance {
31
43
  await this.string(any.string);
32
44
  }
33
45
  }
46
+ assertCanWrite() {
47
+ if (this._canceled) {
48
+ throw this.cancellationError();
49
+ }
50
+ if (this.closed) {
51
+ throw new Error(`Writer for channel ${this.uri} is closed`);
52
+ }
53
+ }
34
54
  async buffer(buffer) {
55
+ this.assertCanWrite();
35
56
  this.logger.debug(`${this.uri} sends buffer ${buffer.length} bytes`);
36
57
  const localSequenceNumber = this.localSequenceNumber++;
37
58
  const handledPromise = this.awaitProcessed();
@@ -41,33 +62,43 @@ export class WriterInstance {
41
62
  await handledPromise;
42
63
  }
43
64
  async stream(buffer, transform) {
65
+ this.assertCanWrite();
44
66
  this.openStreams += 1;
45
67
  const t = transform || ((x) => x);
46
68
  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;
69
+ try {
70
+ const handledPromise = this.awaitProcessed();
71
+ const writeStreamMessageChunk = promisify(stream.write.bind(stream));
72
+ const localSequenceNumber = this.localSequenceNumber++;
73
+ await writeStreamMessageChunk({
74
+ id: {
75
+ channel: this.uri,
76
+ localSequenceNumber,
77
+ runner: this.runnerId,
78
+ },
79
+ });
80
+ const id = await new Promise((res) => stream.once('data', res));
81
+ this.logger.debug(`${this.uri} streams message with id ${JSON.stringify(id)}`);
82
+ for await (const msg of buffer) {
83
+ const processedPromise = new Promise((res) => stream.once('data', res));
84
+ await writeStreamMessageChunk({ data: { data: t(msg) } });
85
+ await processedPromise;
86
+ }
87
+ stream.end();
88
+ await handledPromise;
89
+ }
90
+ finally {
91
+ this.openStreams -= 1;
92
+ if (!stream.writableEnded) {
93
+ stream.end();
94
+ }
95
+ if (this.shouldClose.length > 0) {
96
+ await this.close();
97
+ }
63
98
  }
64
- stream.end();
65
- await handledPromise;
66
- this.openStreams -= 1;
67
- if (this.shouldClose.length > 0)
68
- await this.close();
69
99
  }
70
100
  async string(msg) {
101
+ this.assertCanWrite();
71
102
  this.logger.debug(`${this.uri} sends string ${msg.length} characters`);
72
103
  const localSequenceNumber = this.localSequenceNumber++;
73
104
  const handledPromise = this.awaitProcessed();
@@ -81,6 +112,11 @@ export class WriterInstance {
81
112
  await handledPromise;
82
113
  }
83
114
  async close(issued = false) {
115
+ this.closed = true;
116
+ if (issued && !this._canceled) {
117
+ this._canceled = true;
118
+ await this.emitCancel();
119
+ }
84
120
  if (this.openStreams !== 0) {
85
121
  await new Promise((resolve) => this.shouldClose.push(resolve));
86
122
  return;
@@ -97,14 +133,35 @@ export class WriterInstance {
97
133
  resolve = this.shouldClose.pop();
98
134
  }
99
135
  }
100
- handled() {
136
+ handled(error) {
101
137
  if (this.awaitingProcessed.length > 0) {
102
- this.awaitingProcessed.shift()();
138
+ if (error) {
139
+ this.awaitingProcessed.shift().reject(new Error(error));
140
+ }
141
+ else {
142
+ this.awaitingProcessed.shift().resolve();
143
+ }
144
+ }
145
+ else if (this.closed || this._canceled) {
146
+ return;
103
147
  }
104
148
  else {
105
149
  this.logger.error('Expected to be waiting for a message to be processed, but this is not the case ' +
106
150
  this.uri);
107
151
  }
108
152
  }
153
+ async emitCancel() {
154
+ await Promise.all(Array.from(this.cancelHandlers).map(async (handler) => {
155
+ try {
156
+ await handler();
157
+ }
158
+ catch (error) {
159
+ this.logger.error(`Cancel listener for channel ${this.uri} failed: ${String(error)}`);
160
+ }
161
+ }));
162
+ }
163
+ awaitProcessed() {
164
+ return new Promise((resolve, reject) => this.awaitingProcessed.push({ resolve, reject }));
165
+ }
109
166
  }
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBbUJoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBRXZCLGlCQUFpQixHQUFzQixFQUFFLENBQUE7SUFFekMsV0FBVyxHQUFXLENBQUMsQ0FBQTtJQUN2QixXQUFXLEdBQXNCLEVBQUUsQ0FBQTtJQUUxQixRQUFRLENBQVE7SUFFakMsWUFDRSxHQUFXLEVBQ1gsTUFBb0IsRUFDcEIsa0JBQTRCLEVBQzVCLFFBQWdCLEVBQ2hCLE1BQWM7UUFFZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsa0JBQWtCLEdBQUcsa0JBQWtCLENBQUE7UUFDNUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUE7UUFDZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtJQUMxQixDQUFDO0lBRU8sY0FBYztRQUNwQixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDL0QsQ0FBQztJQUVELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBUTtRQUNoQixJQUFJLFFBQVEsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNwQixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FB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R0FBRyxFQUFFLENBQUE7UUFDcEMsT0FBTyxPQUFPLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxDQUFBO1lBQ1QsT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDbEMsQ0FBQztJQUNILENBQUM7SUFLRCxPQUFPO1FBQ0wsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEVBQUcsRUFBRSxDQUFBO1FBQ25DLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsaUZBQWlGO2dCQUMvRSxJQUFJLENBQUMsR0FBRyxDQUNYLENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICBidWZmZXIoYnVmZmVyOiBVaW50OEFycmF5KTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG4gIHN0cmVhbTxUPihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtOiAoeDogVCkgPT4gVWludDhBcnJheSxcbiAgKTogUHJvbWlzZTx2b2lkPlxuXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cbiAgYW55KGFueTogQW55KTogUHJvbWlzZTx2b2lkPlxuICBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+XG59XG5jb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKClcbmV4cG9ydCBjbGFzcyBXcml0ZXJJbnN0YW5jZSBpbXBsZW1lbnRzIFdyaXRlciB7XG4gIHJlYWRvbmx5IHVyaTogc3RyaW5nXG4gIGxvY2FsU2VxdWVuY2VOdW1iZXI6IG51bWJlciA9IDFcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IFJ1bm5lckNsaWVudFxuICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGVcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IExvZ2dlclxuXG4gIHByaXZhdGUgYXdhaXRpbmdQcm9jZXNzZWQ6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIG9wZW5TdHJlYW1zOiBudW1iZXIgPSAwXG4gIHByaXZhdGUgc2hvdWxkQ2xvc2U6IEFycmF5PCgpID0+IHZvaWQ+ID0gW11cblxuICBwcml2YXRlIHJlYWRvbmx5IHJ1bm5lcklkOiBzdHJpbmdcblxuICBjb25zdHJ1Y3RvcihcbiAgICB1cmk6IHN0cmluZyxcbiAgICBjbGllbnQ6IFJ1bm5lckNsaWVudCxcbiAgICBub3RpZnlPcmNoZXN0cmF0b3I6IFdyaXRhYmxlLFxuICAgIHJ1bm5lcklkOiBzdHJpbmcsXG4gICAgbG9nZ2VyOiBMb2dnZXIsXG4gICkge1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50XG4gICAgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3IgPSBub3RpZnlPcmNoZXN0cmF0b3JcbiAgICB0aGlzLnVyaSA9IHVyaVxuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyXG4gICAgdGhpcy5ydW5uZXJJZCA9IHJ1bm5lcklkXG4gIH1cblxuICBwcml2YXRlIGF3YWl0UHJvY2Vzc2VkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzKSA9PiB0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLnB1c2gocmVzKSlcbiAgfVxuXG4gIGFzeW5jIGFueShhbnk6IEFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICgnc3RyZWFtJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyZWFtKGFueS5zdHJlYW0pXG4gICAgfVxuICAgIGlmICgnYnVmZmVyJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuYnVmZmVyKGFueS5idWZmZXIpXG4gICAgfVxuICAgIGlmICgnc3RyaW5nJyBpbiBhbnkpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RyaW5nKGFueS5zdHJpbmcpXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBidWZmZXIgJHtidWZmZXIubGVuZ3RofSBieXRlc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgaGFuZGxlZFByb21pc2UgPSB0aGlzLmF3YWl0UHJvY2Vzc2VkKClcblxuICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgIG1zZzogeyBkYXRhOiBidWZmZXIsIGNoYW5uZWw6IHRoaXMudXJpLCBsb2NhbFNlcXVlbmNlTnVtYmVyIH0sXG4gICAgfSlcbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgYXN5bmMgc3RyZWFtPFQgPSBVaW50OEFycmF5PihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtPzogKHg6IFQpID0+IFVpbnQ4QXJyYXksXG4gICkge1xuICAgIHRoaXMub3BlblN0cmVhbXMgKz0gMVxuICAgIGNvbnN0IHQgPSB0cmFuc2Zvcm0gfHwgKCh4OiB1bmtub3duKSA9PiA8VWludDhBcnJheT54KVxuICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuY2xpZW50LnNlbmRTdHJlYW1NZXNzYWdlKClcblxuICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG4gICAgY29uc3Qgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsgPSBwcm9taXNpZnkoc3RyZWFtLndyaXRlLmJpbmQoc3RyZWFtKSlcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBhd2FpdCB3cml0ZVN0cmVhbU1lc3NhZ2VDaHVuayh7XG4gICAgICBpZDoge1xuICAgICAgICBjaGFubmVsOiB0aGlzLnVyaSxcbiAgICAgICAgbG9jYWxTZXF1ZW5jZU51bWJlcixcbiAgICAgICAgcnVubmVyOiB0aGlzLnJ1bm5lcklkLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgY29uc3QgaWQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzKSA9PiBzdHJlYW0ub25jZSgnZGF0YScsIHJlcykpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgIGAke3RoaXMudXJpfSBzdHJlYW1zIG1lc3NhZ2Ugd2l0aCBpZCAke0pTT04uc3RyaW5naWZ5KGlkKX1gLFxuICAgIClcblxuICAgIGZvciBhd2FpdCAoY29uc3QgbXNnIG9mIGJ1ZmZlcikge1xuICAgICAgY29uc3QgcHJvY2Vzc2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcbiAgICAgIGF3YWl0IHdyaXRlU3RyZWFtTWVzc2FnZUNodW5rKHsgZGF0YTogeyBkYXRhOiB0KG1zZykgfSB9KVxuICAgICAgLy8gQXdhaXQgYSBtZXNzYWdlIG9uIHRoZSBzdHJlYW0sIGluZGljYXRpbmcgdGhhdCB0aGUgY2h1bmsgaGFzIGJlZW4gcHJvY2Vzc2VkXG4gICAgICBhd2FpdCBwcm9jZXNzZWRQcm9taXNlXG4gICAgfVxuXG4gICAgc3RyZWFtLmVuZCgpXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuXG4gICAgdGhpcy5vcGVuU3RyZWFtcyAtPSAxXG5cbiAgICBpZiAodGhpcy5zaG91bGRDbG9zZS5sZW5ndGggPiAwKSBhd2FpdCB0aGlzLmNsb3NlKClcbiAgfVxuXG4gIGFzeW5jIHN0cmluZyhtc2c6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBzdHJpbmcgJHttc2cubGVuZ3RofSBjaGFyYWN0ZXJzYClcbiAgICBjb25zdCBsb2NhbFNlcXVlbmNlTnVtYmVyID0gdGhpcy5sb2NhbFNlcXVlbmNlTnVtYmVyKytcbiAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoKVxuXG4gICAgYXdhaXQgdGhpcy5ub3RpZnlPcmNoZXN0cmF0b3Ioe1xuICAgICAgbXNnOiB7XG4gICAgICAgIGRhdGE6IGVuY29kZXIuZW5jb2RlKG1zZyksXG4gICAgICAgIGNoYW5uZWw6IHRoaXMudXJpLFxuICAgICAgICBsb2NhbFNlcXVlbmNlTnVtYmVyLFxuICAgICAgfSxcbiAgICB9KVxuXG4gICAgYXdhaXQgaGFuZGxlZFByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFjZWZ1bGx5IGNsb3NlcyB0aGlzIGNoYW5uZWwuXG4gICAqXG4gICAqIEJlaGF2aW9yOlxuICAgKiAtIElmIHRoZXJlIGFyZSBzdGlsbCBhY3RpdmUgc3RyZWFtcywgY2xvc2luZyBpcyBkZWZlcnJlZCB1bnRpbCB0aGV5IGNvbXBsZXRlLlxuICAgKiAtIElmIG11bHRpcGxlIGNhbGxlcnMgaW52b2tlIGBjbG9zZSgpYCB3aGlsZSB3YWl0aW5nLCB0aGVpciBQcm9taXNlcyBhcmUgcXVldWVkIGFuZFxuICAgKiAgIHJlc29sdmVkIG9uY2UgdGhlIGNoYW5uZWwgYWN0dWFsbHkgY2xvc2VzLlxuICAgKiAtIElmIHRoaXMgc2lkZSBpbml0aWF0ZWQgdGhlIGNsb3NlIChgaXNzdWVkID0gZmFsc2VgKSwgYSBjbG9zZSBtZXNzYWdlIGlzIHNlbnQgdG8gdGhlIHJlbW90ZS5cbiAgICpcbiAgICogQHBhcmFtIGlzc3VlZCAtIElmIHRydWUsIGluZGljYXRlcyB0aGUgY2xvc2UgcmVxdWVzdCBvcmlnaW5hdGVkIHJlbW90ZWx5XG4gICAqL1xuICBhc3luYyBjbG9zZShpc3N1ZWQgPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIENhc2UgMTogQWN0aXZlIHN0cmVhbXMgc3RpbGwgcnVubmluZyDihpIgd2FpdCB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBObyBhY3RpdmUgc3RyZWFtcyDihpIgcGVyZm9ybSBhY3R1YWwgY2xvc2VcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gY2xvc2VzIHN0cmVhbWApXG4gICAgaWYgKCFpc3N1ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgICAgY2xvc2U6IHsgY2hhbm5lbDogdGhpcy51cmkgfSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IHJlc29sdmUgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgd2hpbGUgKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUoKVxuICAgICAgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBtZXNzYWdlIGlzIGhhbmRsZWQsIGxldCdzIG5vdGlmeSB0aGUgZmlmbyB7QGxpbmsgYXdhaXRQcm9jZXNzZWR9XG4gICAqL1xuICBoYW5kbGVkKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0V4cGVjdGVkIHRvIGJlIHdhaXRpbmcgZm9yIGEgbWVzc2FnZSB0byBiZSBwcm9jZXNzZWQsIGJ1dCB0aGlzIGlzIG5vdCB0aGUgY2FzZSAnICtcbiAgICAgICAgICB0aGlzLnVyaSxcbiAgICAgIClcbiAgICB9XG4gIH1cbn1cbiJdfQ==
167
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3dyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFBO0FBK0VoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFBO0FBQ2pDLE1BQU0sT0FBTyxjQUFjO0lBQ2hCLEdBQUcsQ0FBUTtJQUNwQixtQkFBbUIsR0FBVyxDQUFDLENBQUE7SUFDZCxNQUFNLENBQWM7SUFDcEIsa0JBQWtCLENBQVU7SUFDNUIsTUFBTSxDQUFRO0lBR3ZCLGlCQUFpQixHQUdwQixFQUFFLENBQUE7SUFFQyxXQUFXLEdBQVcsQ0FBQyxDQUFBO0lBRXZCLFdBQVcsR0FBc0IsRUFBRSxDQUFBO0lBQ25DLE1BQU0sR0FBRyxLQUFLLENBQUE7SUFDZCxTQUFTLEdBQUcsS0FBSyxDQUFBO0lBR1IsY0FBYyxHQUFHLElBQUksR0FBRyxFQUFXLENBQUE7SUFFbkMsUUFBUSxDQUFRO0lBRWpDLFlBQ0UsR0FBVyxFQUNYLE1BQW9CLEVBQ3BCLGtCQUE0QixFQUM1QixRQUFnQixFQUNoQixNQUFjO1FBRWQsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFBO1FBQzVDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFBO1FBQ2QsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7SUFDMUIsQ0FBQztJQUVELElBQUksUUFBUTtRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQTtJQUN2QixDQUFDO0lBRUQsRUFBRSxDQUFDLEtBQWUsRUFBRSxRQUFpQjtRQUNuQyxJQUFJLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxRQUFR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Q25FLENBQUE7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQTtJQUNILENBQUM7SUFFTyxjQUFjO1FBQ3BCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FDckMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUNqRCxDQUFBO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRnJvbVJ1bm5lciwgUnVubmVyQ2xpZW50IH0gZnJvbSAnQHJkZmMvcHJvdG8nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICd1dGlsJ1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnd2luc3RvbidcbmltcG9ydCB7IEFueSB9IGZyb20gJy4vcmVhZGVyJ1xuXG50eXBlIFdyaXRhYmxlID0gKG1zZzogRnJvbVJ1bm5lcikgPT4gUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IHR5cGUgSGFuZGxlcjxUID0gdm9pZD4gPSBbVF0gZXh0ZW5kcyBbdm9pZF1cbiAgPyAoKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPlxuICA6ICh2YWx1ZTogVCkgPT4gdm9pZCB8IFByb21pc2U8dm9pZD5cblxuZXhwb3J0IGludGVyZmFjZSBXcml0ZXIge1xuICByZWFkb25seSB1cmk6IHN0cmluZ1xuICByZWFkb25seSBjYW5jZWxlZDogYm9vbGVhblxuICBvbihldmVudDogJ2NhbmNlbCcsIGxpc3RlbmVyOiBIYW5kbGVyKTogdGhpc1xuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSBjb21wbGV0ZSBidWZmZXIgdG8gdGhlIGNoYW5uZWwuIFRoZSBQcm9taXNlIHJlc29sdmVzIG9uY2UgdGhlIG1lc3NhZ2UgaXMgZnVsbHkgcHJvY2Vzc2VkIGJ5IHRoZSByZW1vdGUuXG4gICAqXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGNoYW5uZWwgaXMgY2xvc2VkIG9yIGNhbmNlbGVkIGF0IHRoZSBtb21lbnQgb2YgdGhlIHdyaXRlIG9wZXJhdGlvbi5cbiAgICogQHBhcmFtIGJ1ZmZlciAtIFRoZSBkYXRhIHRvIHNlbmQgYXMgYSBVaW50OEFycmF5XG4gICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG1lc3NhZ2UgaXMgYWNrbm93bGVkZ2VkIGFzIHByb2Nlc3NlZCBieSB0aGUgcmVtb3RlLlxuICAgKi9cbiAgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD5cblxuICAvKipcbiAgICogV3JpdGVzIGEgc3RyZWFtIG9mIGRhdGEgdG8gYSBzZXBhcmF0ZSBzdHJlYW0tc3BlY2lmaWMgY2hhbm5lbC5cbiAgICogVGhlIFByb21pc2UgcmVzb2x2ZXMgb25jZSB0aGUgZW50aXJlIHN0cmVhbSBpcyBmdWxseSBwcm9jZXNzZWQgYnkgdGhlIHJlbW90ZS5cbiAgICpcbiAgICogQHRocm93cyBFcnJvciBpZiB0aGUgY2hhbm5lbCBpcyBjbG9zZWQgb3IgY2FuY2VsZWQgYXQgdGhlIG1vbWVudCBvZiBpbml0aWF0aW5nIGEgc3RyZWFtLXNwZWNpZmljIGNoYW5uZWwuXG4gICAqIEBwYXJhbSBidWZmZXIgLSBBbiBBc3luY0l0ZXJhYmxlIHRoYXQgcHJvZHVjZXMgdGhlIGRhdGEgdG8gc2VuZCBhcyBVaW50OEFycmF5c1xuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBlbnRpcmUgc3RyZWFtIGlzIGFja25vd2xlZGdlZCBhcyBwcm9jZXNzZWQgYnkgdGhlIHJlbW90ZS5cbiAgICovXG4gIHN0cmVhbShidWZmZXI6IEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pOiBQcm9taXNlPHZvaWQ+XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBhIHN0cmVhbSBvZiBkYXRhIHRvIGEgc2VwYXJhdGUgc3RyZWFtLXNwZWNpZmljIGNoYW5uZWwuXG4gICAqIFRoZSBQcm9taXNlIHJlc29sdmVzIG9uY2UgdGhlIGVudGlyZSBzdHJlYW0gaXMgZnVsbHkgcHJvY2Vzc2VkIGJ5IHRoZSByZW1vdGUuXG4gICAqXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgdGhlIGNoYW5uZWwgaXMgY2xvc2VkIG9yIGNhbmNlbGVkIGF0IHRoZSBtb21lbnQgb2YgaW5pdGlhdGluZyBhIHN0cmVhbS1zcGVjaWZpYyBjaGFubmVsLlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gQW4gQXN5bmNJdGVyYWJsZSB0aGF0IHByb2R1Y2VzIHRoZSBkYXRhIHRvIHNlbmQsIHdoaWNoIHdpbGwgYmUgdHJhbnNmb3JtZWQgaW50byBVaW50OEFycmF5cyB1c2luZyB0aGUgcHJvdmlkZWQgdHJhbnNmb3JtIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB0cmFuc2Zvcm0gLSBBIGZ1bmN0aW9uIHRoYXQgdHJhbnNmb3JtcyBpdGVtcyBmcm9tIHRoZSBidWZmZXIgQXN5bmNJdGVyYWJsZSBpbnRvIFVpbnQ4QXJyYXlzIGZvciBzZW5kaW5nLiBJZiBub3QgcHJvdmlkZWQsIGl0ZW1zIGFyZSBhc3N1bWVkIHRvIGFscmVhZHkgYmUgVWludDhBcnJheXMuXG4gICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGVudGlyZSBzdHJlYW0gaXMgYWNrbm93bGVkZ2VkIGFzIHByb2Nlc3NlZCBieSB0aGUgcmVtb3RlLlxuICAgKi9cbiAgc3RyZWFtPFQ+KFxuICAgIGJ1ZmZlcjogQXN5bmNJdGVyYWJsZTxUPixcbiAgICB0cmFuc2Zvcm06ICh4OiBUKSA9PiBVaW50OEFycmF5LFxuICApOiBQcm9taXNlPHZvaWQ+XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBhIHN0cmluZyBtZXNzYWdlIHRvIHRoZSBjaGFubmVsLiBUaGUgUHJvbWlzZSByZXNvbHZlcyBvbmNlIHRoZSBtZXNzYWdlIGlzIGZ1bGx5IHByb2Nlc3NlZCBieSB0aGUgcmVtb3RlLlxuICAgKlxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBjaGFubmVsIGlzIGNsb3NlZCBvciBjYW5jZWxlZCBhdCB0aGUgbW9tZW50IG9mIHRoZSB3cml0ZSBvcGVyYXRpb24uXG4gICAqIEBwYXJhbSBidWZmZXIgLSBUaGUgc3RyaW5nIG1lc3NhZ2UgdG8gc2VuZFxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBtZXNzYWdlIGlzIGFja25vd2xlZGdlZCBhcyBwcm9jZXNzZWQgYnkgdGhlIHJlbW90ZS5cbiAgICovXG4gIHN0cmluZyhidWZmZXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD5cblxuICAvKipcbiAgICogV3JpdGVzIGEgbWVzc2FnZSBvZiBhbnkgc3VwcG9ydGVkIHR5cGUgKHN0cmluZywgYnVmZmVyLCBvciBzdHJlYW0pIHRvIHRoZSBjaGFubmVsLlxuICAgKiBUaGUgUHJvbWlzZSByZXNvbHZlcyBvbmNlIHRoZSBtZXNzYWdlIGlzIGZ1bGx5IHByb2Nlc3NlZCBieSB0aGUgcmVtb3RlLlxuICAgKlxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBjaGFubmVsIGlzIGNsb3NlZCBvciBjYW5jZWxlZCBhdCB0aGUgbW9tZW50IG9mIHRoZSB3cml0ZSBvcGVyYXRpb24uXG4gICAqIEBwYXJhbSBhbnkgLSBBbiBvYmplY3QgY29udGFpbmluZyBvbmUgb2YgdGhlIHN1cHBvcnRlZCBtZXNzYWdlIHR5cGVzIChzdHJpbmcsIGJ1ZmZlciwgb3Igc3RyZWFtKVxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBtZXNzYWdlIGlzIGFja25vd2xlZGdlZCBhcyBwcm9jZXNzZWQgYnkgdGhlIHJlbW90ZS5cbiAgICovXG4gIGFueShhbnk6IEFueSk6IFByb21pc2U8dm9pZD5cblxuICAvKipcbiAgICogR3JhY2VmdWxseSBjbG9zZXMgdGhpcyBjaGFubmVsLlxuICAgKlxuICAgKiBCZWhhdmlvcjpcbiAgICogLSBJZiB0aGVyZSBhcmUgc3RpbGwgYWN0aXZlIHN0cmVhbXMsIGNsb3NpbmcgaXMgZGVmZXJyZWQgdW50aWwgdGhleSBjb21wbGV0ZS5cbiAgICogLSBJZiBtdWx0aXBsZSBjYWxsZXJzIGludm9rZSBgY2xvc2UoKWAgd2hpbGUgd2FpdGluZywgdGhlaXIgUHJvbWlzZXMgYXJlIHF1ZXVlZCBhbmRcbiAgICogICByZXNvbHZlZCBvbmNlIHRoZSBjaGFubmVsIGFjdHVhbGx5IGNsb3Nlcy5cbiAgICogLSBJZiB0aGlzIHNpZGUgaW5pdGlhdGVkIHRoZSBjbG9zZSAoYGlzc3VlZCA9IGZhbHNlYCksIGEgY2xvc2UgbWVzc2FnZSBpcyBzZW50IHRvIHRoZSByZW1vdGUuXG4gICAqXG4gICAqIEBwYXJhbSBpc3N1ZWQgLSBJZiB0cnVlLCBpbmRpY2F0ZXMgdGhlIGNsb3NlIHJlcXVlc3Qgb3JpZ2luYXRlZCByZW1vdGVseVxuICAgKi9cbiAgY2xvc2UoaXNzdWVkPzogYm9vbGVhbik6IFByb21pc2U8dm9pZD5cbn1cbmNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKVxuZXhwb3J0IGNsYXNzIFdyaXRlckluc3RhbmNlIGltcGxlbWVudHMgV3JpdGVyIHtcbiAgcmVhZG9ubHkgdXJpOiBzdHJpbmdcbiAgbG9jYWxTZXF1ZW5jZU51bWJlcjogbnVtYmVyID0gMVxuICBwcml2YXRlIHJlYWRvbmx5IGNsaWVudDogUnVubmVyQ2xpZW50XG4gIHByaXZhdGUgcmVhZG9ubHkgbm90aWZ5T3JjaGVzdHJhdG9yOiBXcml0YWJsZVxuICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlcjogTG9nZ2VyXG5cbiAgLy8gRklGTyBvZiBtZXNzYWdlLWxldmVsIGFja25vd2xlZGdlbWVudHMgY29taW5nIGJhY2sgZnJvbSB0aGUgb3JjaGVzdHJhdG9yLlxuICBwcml2YXRlIGF3YWl0aW5nUHJvY2Vzc2VkOiBBcnJheTx7XG4gICAgcmVzb2x2ZTogKCkgPT4gdm9pZFxuICAgIHJlamVjdDogKHJlYXNvbjogRXJyb3IpID0+IHZvaWRcbiAgfT4gPSBbXVxuXG4gIHByaXZhdGUgb3BlblN0cmVhbXM6IG51bWJlciA9IDBcbiAgLy8gQ2xvc2UgY2FsbGVycyB3YWl0IGhlcmUgd2hpbGUgYWN0aXZlIHN0cmVhbXMgYXJlIHN0aWxsIGZsdXNoaW5nLlxuICBwcml2YXRlIHNob3VsZENsb3NlOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdXG4gIHByaXZhdGUgY2xvc2VkID0gZmFsc2VcbiAgcHJpdmF0ZSBfY2FuY2VsZWQgPSBmYWxzZVxuXG4gIC8vIFByb2Nlc3NvcnMgY2FuIHN1YnNjcmliZSBoZXJlIHRvIHN0b3AgdXBzdHJlYW0gd29yayB3aGVuIGRvd25zdHJlYW0gY2FuY2Vscy5cbiAgcHJpdmF0ZSByZWFkb25seSBjYW5jZWxIYW5kbGVycyA9IG5ldyBTZXQ8SGFuZGxlcj4oKVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgcnVubmVySWQ6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHVyaTogc3RyaW5nLFxuICAgIGNsaWVudDogUnVubmVyQ2xpZW50LFxuICAgIG5vdGlmeU9yY2hlc3RyYXRvcjogV3JpdGFibGUsXG4gICAgcnVubmVySWQ6IHN0cmluZyxcbiAgICBsb2dnZXI6IExvZ2dlcixcbiAgKSB7XG4gICAgdGhpcy5jbGllbnQgPSBjbGllbnRcbiAgICB0aGlzLm5vdGlmeU9yY2hlc3RyYXRvciA9IG5vdGlmeU9yY2hlc3RyYXRvclxuICAgIHRoaXMudXJpID0gdXJpXG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXJcbiAgICB0aGlzLnJ1bm5lcklkID0gcnVubmVySWRcbiAgfVxuXG4gIGdldCBjYW5jZWxlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fY2FuY2VsZWRcbiAgfVxuXG4gIG9uKGV2ZW50OiAnY2FuY2VsJywgbGlzdGVuZXI6IEhhbmRsZXIpOiB0aGlzIHtcbiAgICBpZiAoZXZlbnQgPT09ICdjYW5jZWwnKSB7XG4gICAgICB0aGlzLmNhbmNlbEhhbmRsZXJzLmFkZChsaXN0ZW5lcilcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5jZWxsYXRpb25FcnJvcigpOiBFcnJvciB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICAgIGBXcml0ZXIgZm9yIGNoYW5uZWwgJHt0aGlzLnVyaX0gd2FzIGNhbmNlbGVkIGJ5IHRoZSBjb25uZWN0ZWQgcmVhZGVyYCxcbiAgICApXG4gIH1cblxuICBhc3luYyBhbnkoYW55OiBBbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoJ3N0cmVhbScgaW4gYW55KSB7XG4gICAgICBhd2FpdCB0aGlzLnN0cmVhbShhbnkuc3RyZWFtKVxuICAgIH1cbiAgICBpZiAoJ2J1ZmZlcicgaW4gYW55KSB7XG4gICAgICBhd2FpdCB0aGlzLmJ1ZmZlcihhbnkuYnVmZmVyKVxuICAgIH1cbiAgICBpZiAoJ3N0cmluZycgaW4gYW55KSB7XG4gICAgICBhd2FpdCB0aGlzLnN0cmluZyhhbnkuc3RyaW5nKVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0Q2FuV3JpdGUoKSB7XG4gICAgaWYgKHRoaXMuX2NhbmNlbGVkKSB7XG4gICAgICB0aHJvdyB0aGlzLmNhbmNlbGxhdGlvbkVycm9yKClcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jbG9zZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgV3JpdGVyIGZvciBjaGFubmVsICR7dGhpcy51cml9IGlzIGNsb3NlZGApXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYnVmZmVyKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYXNzZXJ0Q2FuV3JpdGUoKVxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGAke3RoaXMudXJpfSBzZW5kcyBidWZmZXIgJHtidWZmZXIubGVuZ3RofSBieXRlc2ApXG4gICAgY29uc3QgbG9jYWxTZXF1ZW5jZU51bWJlciA9IHRoaXMubG9jYWxTZXF1ZW5jZU51bWJlcisrXG4gICAgY29uc3QgaGFuZGxlZFByb21pc2UgPSB0aGlzLmF3YWl0UHJvY2Vzc2VkKClcblxuICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgIG1zZzogeyBkYXRhOiBidWZmZXIsIGNoYW5uZWw6IHRoaXMudXJpLCBsb2NhbFNlcXVlbmNlTnVtYmVyIH0sXG4gICAgfSlcbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgYXN5bmMgc3RyZWFtPFQgPSBVaW50OEFycmF5PihcbiAgICBidWZmZXI6IEFzeW5jSXRlcmFibGU8VD4sXG4gICAgdHJhbnNmb3JtPzogKHg6IFQpID0+IFVpbnQ4QXJyYXksXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYXNzZXJ0Q2FuV3JpdGUoKVxuICAgIHRoaXMub3BlblN0cmVhbXMgKz0gMVxuICAgIGNvbnN0IHQgPSB0cmFuc2Zvcm0gfHwgKCh4OiB1bmtub3duKSA9PiA8VWludDhBcnJheT54KVxuICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuY2xpZW50LnNlbmRTdHJlYW1NZXNzYWdlKClcblxuICAgIHRyeSB7XG4gICAgICAvLyBNZXNzYWdlLWxldmVsIGFjayB0aGF0IHNpZ25hbHMgdGhlIHdob2xlIHN0cmVhbSBtZXNzYWdlIGlzIGZ1bGx5IGhhbmRsZWQuXG4gICAgICBjb25zdCBoYW5kbGVkUHJvbWlzZSA9IHRoaXMuYXdhaXRQcm9jZXNzZWQoKVxuICAgICAgY29uc3Qgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsgPSBwcm9taXNpZnkoc3RyZWFtLndyaXRlLmJpbmQoc3RyZWFtKSlcbiAgICAgIGNvbnN0IGxvY2FsU2VxdWVuY2VOdW1iZXIgPSB0aGlzLmxvY2FsU2VxdWVuY2VOdW1iZXIrK1xuICAgICAgYXdhaXQgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsoe1xuICAgICAgICBpZDoge1xuICAgICAgICAgIGNoYW5uZWw6IHRoaXMudXJpLFxuICAgICAgICAgIGxvY2FsU2VxdWVuY2VOdW1iZXIsXG4gICAgICAgICAgcnVubmVyOiB0aGlzLnJ1bm5lcklkLFxuICAgICAgICB9LFxuICAgICAgfSlcblxuICAgICAgLy8gRmlyc3QgcmVzcG9uc2UgY29uZmlybXMgc3RyZWFtIGlkIHJlZ2lzdHJhdGlvbiBvbiB0aGUgcmVtb3RlIHNpZGUuXG4gICAgICBjb25zdCBpZCA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcblxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgIGAke3RoaXMudXJpfSBzdHJlYW1zIG1lc3NhZ2Ugd2l0aCBpZCAke0pTT04uc3RyaW5naWZ5KGlkKX1gLFxuICAgICAgKVxuXG4gICAgICAvLyBUT0RPOiBkb24ndCBhd2FpdCB0byBhbGxvdyBjb25zdW1pbmcgcHJvY2Vzc29ycyB0byByZWFkIGFuZCBoYW5kbGUgaW4gcGFyYWxsZWwuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IG1zZyBvZiBidWZmZXIpIHtcbiAgICAgICAgY29uc3QgcHJvY2Vzc2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXMpID0+IHN0cmVhbS5vbmNlKCdkYXRhJywgcmVzKSlcbiAgICAgICAgYXdhaXQgd3JpdGVTdHJlYW1NZXNzYWdlQ2h1bmsoeyBkYXRhOiB7IGRhdGE6IHQobXNnKSB9IH0pXG4gICAgICAgIC8vIEF3YWl0IGEgbWVzc2FnZSBvbiB0aGUgc3RyZWFtLCBpbmRpY2F0aW5nIHRoYXQgdGhlIGNodW5rIGhhcyBiZWVuIHByb2Nlc3NlZFxuICAgICAgICBhd2FpdCBwcm9jZXNzZWRQcm9taXNlXG4gICAgICB9XG5cbiAgICAgIHN0cmVhbS5lbmQoKVxuXG4gICAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLm9wZW5TdHJlYW1zIC09IDFcblxuICAgICAgaWYgKCFzdHJlYW0ud3JpdGFibGVFbmRlZCkge1xuICAgICAgICBzdHJlYW0uZW5kKClcbiAgICAgIH1cblxuICAgICAgLy8gSWYgYSBjbG9zZSBjYWxsIHdhcyBkZWZlcnJlZCB3aGlsZSBzdHJlYW1pbmcsIGNvbXBsZXRlIGl0IG5vdy5cbiAgICAgIGlmICh0aGlzLnNob3VsZENsb3NlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jbG9zZSgpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc3RyaW5nKG1zZzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hc3NlcnRDYW5Xcml0ZSgpXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYCR7dGhpcy51cml9IHNlbmRzIHN0cmluZyAke21zZy5sZW5ndGh9IGNoYXJhY3RlcnNgKVxuICAgIGNvbnN0IGxvY2FsU2VxdWVuY2VOdW1iZXIgPSB0aGlzLmxvY2FsU2VxdWVuY2VOdW1iZXIrK1xuICAgIGNvbnN0IGhhbmRsZWRQcm9taXNlID0gdGhpcy5hd2FpdFByb2Nlc3NlZCgpXG5cbiAgICBhd2FpdCB0aGlzLm5vdGlmeU9yY2hlc3RyYXRvcih7XG4gICAgICBtc2c6IHtcbiAgICAgICAgZGF0YTogZW5jb2Rlci5lbmNvZGUobXNnKSxcbiAgICAgICAgY2hhbm5lbDogdGhpcy51cmksXG4gICAgICAgIGxvY2FsU2VxdWVuY2VOdW1iZXIsXG4gICAgICB9LFxuICAgIH0pXG5cbiAgICBhd2FpdCBoYW5kbGVkUHJvbWlzZVxuICB9XG5cbiAgYXN5bmMgY2xvc2UoaXNzdWVkID0gZmFsc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmNsb3NlZCA9IHRydWVcbiAgICBpZiAoaXNzdWVkICYmICF0aGlzLl9jYW5jZWxlZCkge1xuICAgICAgLy8gUmVtb3RlIGluaXRpYXRlZCBjbG9zZTogbWFyayB3cml0ZXIgY2FuY2VsZWQgdG8gZmFpbCBmdXR1cmUgd3JpdGVzLlxuICAgICAgdGhpcy5fY2FuY2VsZWQgPSB0cnVlXG5cbiAgICAgIC8vIE5vdGlmeSBwcm9jZXNzb3JzIHNvIHRoZXkgY2FuIHN0b3AgcHJvZHVjaW5nIHVwc3RyZWFtIHdvcmsgYXMgd2VsbC5cbiAgICAgIGF3YWl0IHRoaXMuZW1pdENhbmNlbCgpXG4gICAgfVxuICAgIC8vIENhc2UgMTogQWN0aXZlIHN0cmVhbXMgc3RpbGwgcnVubmluZyDihpIgd2FpdCB1bnRpbCB0aGV5IGZpbmlzaFxuICAgIGlmICh0aGlzLm9wZW5TdHJlYW1zICE9PSAwKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4gdGhpcy5zaG91bGRDbG9zZS5wdXNoKHJlc29sdmUpKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2FzZSAyOiBObyBhY3RpdmUgc3RyZWFtcyDihpIgcGVyZm9ybSBhY3R1YWwgY2xvc2VcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgJHt0aGlzLnVyaX0gY2xvc2VzIHN0cmVhbWApXG4gICAgaWYgKCFpc3N1ZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMubm90aWZ5T3JjaGVzdHJhdG9yKHtcbiAgICAgICAgY2xvc2U6IHsgY2hhbm5lbDogdGhpcy51cmkgfSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IHJlc29sdmUgPSB0aGlzLnNob3VsZENsb3NlLnBvcCgpXG4gICAgd2hpbGUgKHJlc29sdmUpIHtcbiAgICAgIHJlc29sdmUoKVxuICAgICAgcmVzb2x2ZSA9IHRoaXMuc2hvdWxkQ2xvc2UucG9wKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQSBtZXNzYWdlIGlzIGhhbmRsZWQsIGxldCdzIG5vdGlmeSB0aGUgZmlmbyB7QGxpbmsgYXdhaXRQcm9jZXNzZWR9XG4gICAqL1xuICBoYW5kbGVkKGVycm9yPzogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQuc2hpZnQoKSEucmVqZWN0KG5ldyBFcnJvcihlcnJvcikpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmF3YWl0aW5nUHJvY2Vzc2VkLnNoaWZ0KCkhLnJlc29sdmUoKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy5jbG9zZWQgfHwgdGhpcy5fY2FuY2VsZWQpIHtcbiAgICAgIC8vIEEgbGF0ZSBhY2sgY2FuIGFycml2ZSBhZnRlciBhIGNsb3NlL2NhbmNlbCByYWNlOyBub3RoaW5nIHRvIHJlc29sdmUgYW55bW9yZS5cbiAgICAgIHJldHVyblxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgJ0V4cGVjdGVkIHRvIGJlIHdhaXRpbmcgZm9yIGEgbWVzc2FnZSB0byBiZSBwcm9jZXNzZWQsIGJ1dCB0aGlzIGlzIG5vdCB0aGUgY2FzZSAnICtcbiAgICAgICAgICB0aGlzLnVyaSxcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVtaXRDYW5jZWwoKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBBcnJheS5mcm9tKHRoaXMuY2FuY2VsSGFuZGxlcnMpLm1hcChhc3luYyAoaGFuZGxlcikgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGhhbmRsZXIoKVxuICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgYENhbmNlbCBsaXN0ZW5lciBmb3IgY2hhbm5lbCAke3RoaXMudXJpfSBmYWlsZWQ6ICR7U3RyaW5nKGVycm9yKX1gLFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgKVxuICB9XG5cbiAgcHJpdmF0ZSBhd2FpdFByb2Nlc3NlZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgIHRoaXMuYXdhaXRpbmdQcm9jZXNzZWQucHVzaCh7IHJlc29sdmUsIHJlamVjdCB9KSxcbiAgICApXG4gIH1cbn1cbiJdfQ==
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",
4
4
  "main": "lib/index.js",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -37,30 +37,30 @@
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",
58
- "@rdfc/proto": "^0.1.2",
58
+ "@rdfc/proto": "^0.1.3",
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,18 @@ 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
+ error:
177
+ 'reader is canceled; message has not been processed by the processor',
178
+ },
179
+ })
180
+ return
181
+ }
182
+
151
183
  const promises = []
152
184
  for (const iter of this.consumers) {
153
185
  promises.push(new Promise((res) => iter.push(msg.data, () => res(null))))
@@ -164,11 +196,28 @@ export class ReaderInstance implements Reader {
164
196
  }
165
197
 
166
198
  close() {
199
+ if (this.closed) {
200
+ return
201
+ }
202
+
203
+ this.closed = true
167
204
  for (const iter of this.consumers) {
168
205
  iter.close(() => {})
169
206
  }
170
207
  }
171
208
 
209
+ async cancel(): Promise<void> {
210
+ if (this.canceled) {
211
+ return
212
+ }
213
+
214
+ this.canceled = true
215
+ this.close()
216
+ await this.notifyOrchestrator({
217
+ close: { channel: this.uri },
218
+ })
219
+ }
220
+
172
221
  // There is a stream message available for this reader
173
222
  async handleStreamingMessage({
174
223
  channel,
@@ -176,6 +225,13 @@ export class ReaderInstance implements Reader {
176
225
  }: ReceivingStreamMessage) {
177
226
  this.logger.debug(`${this.uri} handling streaming message`)
178
227
 
228
+ if (this.closed) {
229
+ await this.notifyOrchestrator({
230
+ processed: { globalSequenceNumber, channel },
231
+ })
232
+ return
233
+ }
234
+
179
235
  const chunks = this.client.receiveStreamMessage()
180
236
  const writeControlMessage = promisify(chunks.write.bind(chunks))
181
237
  const consumersConsumed = []
package/src/runner.ts CHANGED
@@ -260,7 +260,7 @@ export class Runner {
260
260
  private handleProcessed(processed: LocalAck) {
261
261
  const writer = this.writers[processed.channel]
262
262
  if (writer) {
263
- writer.handled()
263
+ writer.handled(processed.error)
264
264
  } else {
265
265
  this.logger.error(
266
266
  `Received processed message for channel ${processed.channel}, but no writer was present.`,
@@ -83,9 +83,13 @@ export class OrchestratorMock {
83
83
  // Always bounce processed msgs back to the runner
84
84
  connectStream.register(
85
85
  (msg) => msg.processed,
86
- ({ channel, globalSequenceNumber }, send) => {
86
+ ({ channel, globalSequenceNumber, error }, send) => {
87
87
  send({
88
- processed: { channel, localSequenceNumber: globalSequenceNumber },
88
+ processed: {
89
+ channel,
90
+ localSequenceNumber: globalSequenceNumber,
91
+ error,
92
+ },
89
93
  })
90
94
  },
91
95
  )