@miso.ai/server-commons 0.6.6-beta.16 → 0.6.6-beta.18
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/package.json +1 -1
- package/src/channel/buffer.js +115 -0
- package/src/channel/channel.js +105 -0
- package/src/channel/component.js +71 -0
- package/src/channel/constants.js +6 -0
- package/src/channel/downgrade.js +27 -0
- package/src/channel/events.js +117 -0
- package/src/channel/index.js +8 -0
- package/src/channel/sink-gate.js +39 -0
- package/src/channel/sink.js +103 -0
- package/src/channel/time.js +105 -0
- package/src/channel/transform.js +83 -0
- package/src/channel/upgrade.js +99 -0
- package/src/channel/write.js +154 -0
- package/src/index.js +1 -0
- package/src/stream/buffered-write.js +9 -1
- package/src/stream/easy-transform.js +66 -0
- package/src/stream/index.js +1 -0
- package/src/stream/misc.js +7 -2
- package/test/channel.test.js +268 -0
- package/test/easy-transform.js +64 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { test } from 'uvu';
|
|
2
|
+
import * as assert from 'uvu/assert';
|
|
3
|
+
import { Channel, WriteChannel, UpgradeChannel, DowngradeChannel, delay } from '../src/index.js';
|
|
4
|
+
import { generateDefaultSinkResponse } from '../src/channel/events.js';
|
|
5
|
+
|
|
6
|
+
function createDataPayload(index) {
|
|
7
|
+
const id = `p${index}`;
|
|
8
|
+
return {
|
|
9
|
+
id,
|
|
10
|
+
text: `text-${index}`,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function createDataEvent(index) {
|
|
15
|
+
const payload = createDataPayload(index);
|
|
16
|
+
const { id } = payload;
|
|
17
|
+
return {
|
|
18
|
+
type: 'data',
|
|
19
|
+
id,
|
|
20
|
+
index,
|
|
21
|
+
payload,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const DATA_PAYLOADS = Array.from({ length: 10 }, (_, i) => createDataPayload(i));
|
|
26
|
+
const DATA_EVENTS = Array.from({ length: 10 }, (_, i) => createDataEvent(i));
|
|
27
|
+
|
|
28
|
+
test('Channel', async () => {
|
|
29
|
+
const data = DATA_EVENTS.slice(0, 5);
|
|
30
|
+
const outputs = [];
|
|
31
|
+
|
|
32
|
+
const channel = new Channel({
|
|
33
|
+
name: 'channel',
|
|
34
|
+
});
|
|
35
|
+
channel.write({ type: 'start' });
|
|
36
|
+
for (const event of data) {
|
|
37
|
+
channel.write(event);
|
|
38
|
+
}
|
|
39
|
+
channel.write({ type: 'end' });
|
|
40
|
+
channel.end();
|
|
41
|
+
|
|
42
|
+
for await (const event of channel) {
|
|
43
|
+
outputs.push(event);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
assert.equal(outputs[0].type, 'start');
|
|
47
|
+
assert.equal(outputs.slice(1, -1), data);
|
|
48
|
+
assert.equal(outputs[outputs.length - 1].type, 'end');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('WriteChannel', async () => {
|
|
52
|
+
const data = DATA_EVENTS;
|
|
53
|
+
const recordCap = 4;
|
|
54
|
+
const outputs = [];
|
|
55
|
+
const writes = [];
|
|
56
|
+
const channel = new WriteChannel({
|
|
57
|
+
name: 'write',
|
|
58
|
+
buffer: {
|
|
59
|
+
recordCap,
|
|
60
|
+
byteCap: 1024 * 1024,
|
|
61
|
+
},
|
|
62
|
+
sink: {
|
|
63
|
+
write: async (event) => {
|
|
64
|
+
//await delay(100);
|
|
65
|
+
writes.push(event.payload);
|
|
66
|
+
return generateDefaultSinkResponse(event);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async transform(event) {
|
|
70
|
+
if (event.type === 'data') {
|
|
71
|
+
await this.writeData(event);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
/*
|
|
75
|
+
sinkGate: {
|
|
76
|
+
writesPerSecond: 10,
|
|
77
|
+
recordsPerSecond: 100000,
|
|
78
|
+
bytesPerSecond: 1024 * 1024,
|
|
79
|
+
},
|
|
80
|
+
*/
|
|
81
|
+
});
|
|
82
|
+
channel.write({ type: 'start' });
|
|
83
|
+
for (const event of data) {
|
|
84
|
+
channel.write(event);
|
|
85
|
+
}
|
|
86
|
+
channel.write({ type: 'end' });
|
|
87
|
+
channel.end();
|
|
88
|
+
|
|
89
|
+
for await (const event of channel) {
|
|
90
|
+
outputs.push(event);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// assert: start & end events
|
|
94
|
+
assert.equal(outputs[0].type, 'start');
|
|
95
|
+
assert.equal(outputs[outputs.length - 1].type, 'end');
|
|
96
|
+
|
|
97
|
+
// assert: n request & response events
|
|
98
|
+
let expectedRequestIndex = 0, responseCount = 0, writeCount = 0;
|
|
99
|
+
for (const event of outputs) {
|
|
100
|
+
switch (event.type) {
|
|
101
|
+
case 'request':
|
|
102
|
+
assert.equal(event.index, expectedRequestIndex++);
|
|
103
|
+
break;
|
|
104
|
+
case 'response':
|
|
105
|
+
responseCount++;
|
|
106
|
+
assert.ok(event.index <= expectedRequestIndex);
|
|
107
|
+
break;
|
|
108
|
+
case 'write':
|
|
109
|
+
writeCount++;
|
|
110
|
+
assert.ok(event.index <= expectedRequestIndex);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const expectedWriteCount = Math.ceil(data.length / recordCap);
|
|
115
|
+
assert.equal(expectedRequestIndex, expectedWriteCount);
|
|
116
|
+
assert.equal(responseCount, expectedWriteCount);
|
|
117
|
+
assert.equal(writeCount, expectedWriteCount);
|
|
118
|
+
|
|
119
|
+
//assert.equal(rest.length, expectedRequestCount);
|
|
120
|
+
// there should be
|
|
121
|
+
//assert.equal(outputs.slice(1, -1), writes);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('UpgradeChannel - object mode', async () => {
|
|
125
|
+
const payloads = DATA_PAYLOADS.slice(0, 5);
|
|
126
|
+
const outputs = [];
|
|
127
|
+
|
|
128
|
+
const channel = new UpgradeChannel({
|
|
129
|
+
name: 'upgrade',
|
|
130
|
+
objectMode: true,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
for (const payload of payloads) {
|
|
134
|
+
channel.write(payload);
|
|
135
|
+
}
|
|
136
|
+
channel.end();
|
|
137
|
+
|
|
138
|
+
for await (const event of channel) {
|
|
139
|
+
outputs.push(event);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// assert: start & end events
|
|
143
|
+
assert.equal(outputs[0].type, 'start');
|
|
144
|
+
assert.equal(outputs[outputs.length - 1].type, 'end');
|
|
145
|
+
|
|
146
|
+
// assert: data events
|
|
147
|
+
const dataEvents = outputs.filter(e => e.type === 'data');
|
|
148
|
+
assert.equal(dataEvents.length, payloads.length);
|
|
149
|
+
for (let i = 0; i < payloads.length; i++) {
|
|
150
|
+
assert.equal(dataEvents[i].id, payloads[i].id);
|
|
151
|
+
assert.equal(dataEvents[i].payload, payloads[i]);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('UpgradeChannel - string mode', async () => {
|
|
156
|
+
const payloads = DATA_PAYLOADS.slice(0, 3);
|
|
157
|
+
const outputs = [];
|
|
158
|
+
|
|
159
|
+
const channel = new UpgradeChannel({
|
|
160
|
+
name: 'upgrade-string',
|
|
161
|
+
objectMode: false,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
for (const payload of payloads) {
|
|
165
|
+
channel.write(JSON.stringify(payload));
|
|
166
|
+
}
|
|
167
|
+
channel.end();
|
|
168
|
+
|
|
169
|
+
for await (const event of channel) {
|
|
170
|
+
outputs.push(event);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// assert: start & end events
|
|
174
|
+
assert.equal(outputs[0].type, 'start');
|
|
175
|
+
assert.equal(outputs[outputs.length - 1].type, 'end');
|
|
176
|
+
|
|
177
|
+
// assert: data events
|
|
178
|
+
const dataEvents = outputs.filter(e => e.type === 'data');
|
|
179
|
+
assert.equal(dataEvents.length, payloads.length);
|
|
180
|
+
for (let i = 0; i < payloads.length; i++) {
|
|
181
|
+
assert.equal(dataEvents[i].id, payloads[i].id);
|
|
182
|
+
assert.equal(dataEvents[i].payload.id, payloads[i].id);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('UpgradeChannel - asId mode', async () => {
|
|
187
|
+
const ids = DATA_PAYLOADS.slice(0, 3).map(p => p.id);
|
|
188
|
+
const outputs = [];
|
|
189
|
+
|
|
190
|
+
const channel = new UpgradeChannel({
|
|
191
|
+
name: 'upgrade-as-id',
|
|
192
|
+
objectMode: false,
|
|
193
|
+
asId: true,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
for (const id of ids) {
|
|
197
|
+
channel.write(id);
|
|
198
|
+
}
|
|
199
|
+
channel.end();
|
|
200
|
+
|
|
201
|
+
for await (const event of channel) {
|
|
202
|
+
outputs.push(event);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// assert: start & end events
|
|
206
|
+
assert.equal(outputs[0].type, 'start');
|
|
207
|
+
assert.equal(outputs[outputs.length - 1].type, 'end');
|
|
208
|
+
|
|
209
|
+
// assert: data events
|
|
210
|
+
const dataEvents = outputs.filter(e => e.type === 'data');
|
|
211
|
+
assert.equal(dataEvents.length, ids.length);
|
|
212
|
+
for (let i = 0; i < ids.length; i++) {
|
|
213
|
+
assert.equal(dataEvents[i].id, ids[i]);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('DowngradeChannel - object mode', async () => {
|
|
218
|
+
const data = DATA_EVENTS.slice(0, 5);
|
|
219
|
+
const outputs = [];
|
|
220
|
+
|
|
221
|
+
const channel = new DowngradeChannel({
|
|
222
|
+
objectMode: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
channel.write({ type: 'start' });
|
|
226
|
+
for (const event of data) {
|
|
227
|
+
channel.write(event);
|
|
228
|
+
}
|
|
229
|
+
channel.write({ type: 'end' });
|
|
230
|
+
channel.end();
|
|
231
|
+
|
|
232
|
+
for await (const output of channel) {
|
|
233
|
+
outputs.push(output);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// assert: only payloads from data events are output
|
|
237
|
+
assert.equal(outputs.length, data.length);
|
|
238
|
+
for (let i = 0; i < data.length; i++) {
|
|
239
|
+
assert.equal(outputs[i], data[i].payload);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('DowngradeChannel - string mode', async () => {
|
|
244
|
+
const data = DATA_EVENTS.slice(0, 3);
|
|
245
|
+
const chunks = [];
|
|
246
|
+
|
|
247
|
+
const channel = new DowngradeChannel({
|
|
248
|
+
objectMode: false,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
channel.write({ type: 'start' });
|
|
252
|
+
for (const event of data) {
|
|
253
|
+
channel.write(event);
|
|
254
|
+
}
|
|
255
|
+
channel.write({ type: 'end' });
|
|
256
|
+
channel.end();
|
|
257
|
+
|
|
258
|
+
for await (const chunk of channel) {
|
|
259
|
+
chunks.push(chunk);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// assert: payloads are stringified (stream may buffer chunks together)
|
|
263
|
+
const output = chunks.join('');
|
|
264
|
+
const expected = data.map(e => JSON.stringify(e.payload)).join('');
|
|
265
|
+
assert.equal(output, expected);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test.run();
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { test } from 'uvu';
|
|
2
|
+
import * as assert from 'uvu/assert';
|
|
3
|
+
import { Writable } from 'stream';
|
|
4
|
+
import { stream, delay } from '../src/index.js';
|
|
5
|
+
|
|
6
|
+
test('EasyTransform', async () => {
|
|
7
|
+
const events = [];
|
|
8
|
+
const output = [];
|
|
9
|
+
const writable = new Writable({
|
|
10
|
+
objectMode: false,
|
|
11
|
+
write(chunk, encoding, next) {
|
|
12
|
+
events.push(`writable:write:${chunk}`);
|
|
13
|
+
output.push(`${chunk}`);
|
|
14
|
+
this._next = next;
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
Object.assign(writable, {
|
|
18
|
+
_next: undefined,
|
|
19
|
+
callNext() {
|
|
20
|
+
const next = this._next;
|
|
21
|
+
if (!next) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this._next = undefined;
|
|
25
|
+
next();
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const transform = new stream.EasyTransform({
|
|
29
|
+
async transform(chunk, encoding) {
|
|
30
|
+
events.push(`transform:transform:${chunk}`);
|
|
31
|
+
this._pushBuffer(chunk, encoding);
|
|
32
|
+
},
|
|
33
|
+
async flush() {
|
|
34
|
+
events.push('transform:flush');
|
|
35
|
+
this._pushBuffer('end');
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
transform.pipe(writable);
|
|
39
|
+
|
|
40
|
+
transform.write('hello');
|
|
41
|
+
transform.write('world');
|
|
42
|
+
transform.end();
|
|
43
|
+
|
|
44
|
+
events.push('writable:next');
|
|
45
|
+
writable.callNext();
|
|
46
|
+
await delay();
|
|
47
|
+
events.push('writable:next');
|
|
48
|
+
writable.callNext();
|
|
49
|
+
await delay();
|
|
50
|
+
|
|
51
|
+
assert.equal(output, ['hello', 'world', 'end']);
|
|
52
|
+
assert.equal(events, [
|
|
53
|
+
'transform:transform:hello',
|
|
54
|
+
'writable:write:hello',
|
|
55
|
+
'writable:next',
|
|
56
|
+
'transform:transform:world',
|
|
57
|
+
'writable:write:world',
|
|
58
|
+
'transform:flush',
|
|
59
|
+
'writable:next',
|
|
60
|
+
'writable:write:end',
|
|
61
|
+
]);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test.run();
|