|
|
@ -14,6 +14,28 @@ const readFileBin = require("../stream-file").readFileBin;
|
|
|
|
const BatchRead = require("../batch-read");
|
|
|
|
const BatchRead = require("../batch-read");
|
|
|
|
|
|
|
|
|
|
|
|
const Schedule = require("../schedule");
|
|
|
|
const Schedule = require("../schedule");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Each time you write to a channel it will either use an open file descriptor
|
|
|
|
|
|
|
|
for that channel or open a new descriptor if one is not available. These are
|
|
|
|
|
|
|
|
automatically closed after this window to prevent a file descriptor leak, so
|
|
|
|
|
|
|
|
writes that take longer than this time may be dropped! */
|
|
|
|
|
|
|
|
const CHANNEL_WRITE_WINDOW = 300000;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Each time you read a channel it will have this many milliseconds to complete
|
|
|
|
|
|
|
|
otherwise it will be closed to prevent a file descriptor leak. The server will
|
|
|
|
|
|
|
|
lock up if it uses all available file descriptors, so it's important to close
|
|
|
|
|
|
|
|
them. The tradeoff with this timeout is that some functions, the stream, and
|
|
|
|
|
|
|
|
and the timeout itself are stored in memory. A longer timeout uses more memory
|
|
|
|
|
|
|
|
and running out of memory will also kill the server. */
|
|
|
|
|
|
|
|
const STREAM_CLOSE_TIMEOUT = 300000;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The above timeout closes the stream, but apparently that doesn't always work.
|
|
|
|
|
|
|
|
We set yet another timeout to allow the runtime to gracefully close the stream
|
|
|
|
|
|
|
|
(flushing all pending writes/reads and doing who knows what else). After this timeout
|
|
|
|
|
|
|
|
it will be MERCILESSLY DESTROYED. This isn't graceful, but again, file descriptor
|
|
|
|
|
|
|
|
leaks are bad. */
|
|
|
|
|
|
|
|
const STREAM_DESTROY_TIMEOUT = 30000;
|
|
|
|
|
|
|
|
|
|
|
|
const isValidChannelId = function (id) {
|
|
|
|
const isValidChannelId = function (id) {
|
|
|
|
return typeof(id) === 'string' &&
|
|
|
|
return typeof(id) === 'string' &&
|
|
|
|
id.length >= 32 && id.length < 50 &&
|
|
|
|
id.length >= 32 && id.length < 50 &&
|
|
|
@ -64,7 +86,7 @@ const destroyStream = function (stream) {
|
|
|
|
try { stream.close(); } catch (err) { console.error(err); }
|
|
|
|
try { stream.close(); } catch (err) { console.error(err); }
|
|
|
|
setTimeout(function () {
|
|
|
|
setTimeout(function () {
|
|
|
|
try { stream.destroy(); } catch (err) { console.error(err); }
|
|
|
|
try { stream.destroy(); } catch (err) { console.error(err); }
|
|
|
|
}, 15000);
|
|
|
|
}, STREAM_DESTROY_TIMEOUT);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const ensureStreamCloses = function (stream, id, ms) {
|
|
|
|
const ensureStreamCloses = function (stream, id, ms) {
|
|
|
@ -74,7 +96,7 @@ const ensureStreamCloses = function (stream, id, ms) {
|
|
|
|
// this can only be a timeout error...
|
|
|
|
// this can only be a timeout error...
|
|
|
|
console.log("stream close error:", err, id);
|
|
|
|
console.log("stream close error:", err, id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}), ms || 45000), []);
|
|
|
|
}), ms || STREAM_CLOSE_TIMEOUT), []);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// readMessagesBin asynchronously iterates over the messages in a channel log
|
|
|
|
// readMessagesBin asynchronously iterates over the messages in a channel log
|
|
|
@ -729,7 +751,7 @@ var getChannel = function (env, id, _callback) {
|
|
|
|
delete env.channels[id];
|
|
|
|
delete env.channels[id];
|
|
|
|
destroyStream(channel.writeStream, path);
|
|
|
|
destroyStream(channel.writeStream, path);
|
|
|
|
//console.log("closing writestream");
|
|
|
|
//console.log("closing writestream");
|
|
|
|
}, 120000);
|
|
|
|
}, CHANNEL_WRITE_WINDOW);
|
|
|
|
channel.delayClose();
|
|
|
|
channel.delayClose();
|
|
|
|
env.channels[id] = channel;
|
|
|
|
env.channels[id] = channel;
|
|
|
|
done(void 0, channel);
|
|
|
|
done(void 0, channel);
|
|
|
|