Stream pooling
parent
451761d589
commit
d0d4fec113
@ -0,0 +1,46 @@
|
||||
"use strict";
|
||||
|
||||
const pipe = require("@promistream/pipe");
|
||||
const propagatePeek = require("@promistream/propagate-peek");
|
||||
const propagateAbort = require("@promistream/propagate-abort");
|
||||
const EndOfStream = require("@promistream/end-of-stream");
|
||||
const unreachable = require("@joepie91/unreachable")("@promistream/dynamic");
|
||||
|
||||
module.exports = function singleValueProcessor(processingStream) {
|
||||
// NOTE: This is *not* compliant with the Promistream spec! It can only be used with code that is specifically written to handle it.
|
||||
|
||||
let streamEnded = true;
|
||||
|
||||
let gateStream = {
|
||||
_promistreamVersion: 0,
|
||||
description: `single-value processor gate stream`,
|
||||
peek: propagatePeek, // FIXME: Is this correct? Should this not be dependent on whether a peek and/or read has already been done for this iteration?
|
||||
abort: propagateAbort,
|
||||
read: function produceValue_singleValueGateStream(source) {
|
||||
if (streamEnded === false) {
|
||||
streamEnded = true;
|
||||
return source.read();
|
||||
} else {
|
||||
throw new EndOfStream;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let wrappedPipeline = pipe([
|
||||
gateStream,
|
||||
processingStream
|
||||
]);
|
||||
|
||||
return {
|
||||
read: function (source) {
|
||||
return wrappedPipeline.read(source);
|
||||
},
|
||||
reset: function () {
|
||||
if (streamEnded === true) {
|
||||
streamEnded = false;
|
||||
} else {
|
||||
throw unreachable("Tried to reset a non-ended stream");
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
const debug = require("debug")("promistream:dynamic:stream-pool");
|
||||
const unreachable = require("@joepie91/unreachable")("@promistream/dynamic");
|
||||
const valueID = require("./value-id");
|
||||
|
||||
// TODO: Separate out into own package + update `unreachable` label accordingly
|
||||
// TODO: Validation
|
||||
|
||||
module.exports = function createStreamPool() {
|
||||
let pool = new WeakMap();
|
||||
let streamTypes = new Map();
|
||||
|
||||
return {
|
||||
acquire: function (streamFactory) {
|
||||
if (!pool.has(streamFactory)) {
|
||||
pool.set(streamFactory, []);
|
||||
}
|
||||
|
||||
let availableStreams = pool.get(streamFactory);
|
||||
|
||||
if (availableStreams.length === 0) {
|
||||
debug(`Ran out of streams for type ${valueID(streamFactory)}, creating a new one...`);
|
||||
let newStream = streamFactory();
|
||||
streamTypes.set(newStream, streamFactory);
|
||||
|
||||
// TODO: Periodic cleanup and activity tracking for instances
|
||||
availableStreams.push(newStream);
|
||||
} else {
|
||||
debug(`Reusing stream from pool for type ${valueID(streamFactory)}`);
|
||||
}
|
||||
|
||||
let acquiredStream = availableStreams.shift();
|
||||
|
||||
if (acquiredStream.reset != null) {
|
||||
acquiredStream.reset();
|
||||
}
|
||||
|
||||
return acquiredStream;
|
||||
},
|
||||
release: function (stream) {
|
||||
let streamFactory = streamTypes.get(stream);
|
||||
|
||||
if (streamFactory != null) {
|
||||
let availableStreams = pool.get(streamFactory);
|
||||
availableStreams.push(stream);
|
||||
} else {
|
||||
throw unreachable(`Specified stream does not belong to the pool`);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue