@devgrid/netron
Version:
Event bus, streams and remote object invocation.
96 lines • 3.1 kB
JavaScript
import { ListBuffer } from '@devgrid/common';
export class ReadableStream {
constructor(peer, id, isLive = false) {
this.peer = peer;
this.id = id;
this.isLive = isLive;
this.queue = new ListBuffer();
this.resolvers = new ListBuffer();
this.closed = false;
this.buffer = new Map();
this.expectedIndex = 0;
this.isComplete = false;
if (!isLive) {
this.timeout = setTimeout(() => {
console.warn(`Stream is inactive, deleting: ${this.id}`);
this.onEnd();
}, this.peer.netron.options?.streamTimeout ?? 60000);
}
}
onPacket(packet) {
if (!this.isLive && this.timeout) {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
console.warn(`Stream is inactive, deleting: ${this.id}`);
this.onEnd();
}, 60000);
}
this.buffer.set(packet.streamIndex, packet.data);
while (this.buffer.has(this.expectedIndex)) {
const chunk = this.buffer.get(this.expectedIndex);
this.buffer.delete(this.expectedIndex);
this.expectedIndex++;
this.enqueue(chunk);
}
if (packet.isLastChunk()) {
this.isComplete = true;
this.onEnd();
}
}
onEnd(force = false) {
if (this.isLive && !force) {
console.warn(`Attempt to delete live stream, but it is active: ${this.id}`);
return;
}
if (this.timeout)
clearTimeout(this.timeout);
this.isComplete = true;
this.peer.readableStreams.delete(this.id);
}
async read() {
while (this.resolvers.length > 0 && this.queue.length > 0) {
const resolve = this.resolvers.shift();
resolve?.(this.queue.shift());
}
if (this.resolvers.length === 0 && this.queue.length > 0) {
return this.queue.shift();
}
if (this.closed) {
this.flush();
return null;
}
return new Promise((resolve) => this.resolvers.push(resolve));
}
close() {
this.closed = true;
this.flush();
}
enqueue(chunk) {
if (this.closed)
return;
if (this.queue.length > 0) {
this.queue.push(chunk);
return;
}
if (this.resolvers.length > 0) {
const resolve = this.resolvers.shift();
resolve?.(chunk);
}
else {
this.queue.push(chunk);
}
}
flush() {
while (this.resolvers.length > 0) {
const resolve = this.resolvers.shift();
resolve?.(this.queue.length > 0 ? this.queue.shift() : null);
}
this.queue.clear();
}
static create(peer, streamId, isLive = false) {
const stream = new ReadableStream(peer, streamId, isLive);
peer.readableStreams.set(stream.id, stream);
return stream;
}
}
//# sourceMappingURL=readable-stream.js.map