-
Notifications
You must be signed in to change notification settings - Fork 470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NodeJs - Pause/Resume stream request #471
Comments
Use-case: backpressure from async-iterable usage: type Deferred<T> = {
promise: Promise<T>,
resolve: (result: T) => void,
reject: (reason: any) => void,
};
function createDeferred<T>(): Deferred<T> {
const result = {} as Deferred<T>;
result.promise = new Promise<T>((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
function streamQuery<T>(query: TemplateStringsArray, ...interpolations: any[]): AsyncIterable<T> {
return { [Symbol.asyncIterator]: asyncIterator };
function asyncIterator(): AsyncIterator<any> {
const request = pool.request();
request.stream = true;
// Reproduce pool.query but for request.
// This is equivalent to request._template('query', query, interpolations);
const command = [query[0]];
for (let i = 0; i !== interpolations.length; i++) {
request.input(`p${i}`, interpolations[i]);
command.push(`@p${i}`, query[i + 1]);
}
request.query(command.join('')); // ignoring query result.
request.on('row', row);
request.on('error', error);
request.on('done', done);
// Note this will buffer without bound, mssql doesn't let us apply backpressure (suspend streaming).
// Results received, but not requested, in the order received
const buffer: Array<Promise<IteratorResult<T>>> = [];
let bufferDone = false;
// Results requested, but not received, in the order requested
const pending: Array<Deferred<IteratorResult<T>>> = [];
// At least one of the above should always be empty.
return { next };
function next(): Promise<IteratorResult<T>> {
// if (buffer.length === LOW) request.resume();
if (buffer.length) {
return buffer.shift()!;
}
if (bufferDone) {
return Promise.resolve({ value: undefined as any as T, done: true });
}
const deferred = createDeferred<IteratorResult<T>>();
pending.push(deferred);
return deferred.promise;
}
function row(row: T) {
const result = { value: row, done: false };
if (!pending.length) {
buffer.push(Promise.resolve(result));
// if (buffer.length === FULL) request.pause();
} else {
pending.shift()!.resolve(result);
}
}
function error(reason: any) {
if (!pending.length) {
buffer.push(Promise.reject(reason));
// if (buffer.length === FULL) request.pause();
} else {
pending.shift()!.reject(reason);
}
}
function done() {
bufferDone = true;
while (pending.length) {
pending.shift()!.resolve({ value: undefined as any as T, done: true });
}
}
}
} (note that this code is not terribly well tested, sorry!) |
@simonbuchan, do you have an example which does not use TypeScript? |
If you can't be bothered to strip the types yourself, you can paste it in the typescript playground |
Hello!
|
pause/resume of streams is now added |
OH MY GOD...After about 2 years solved this issue.
|
Thanks!!!!!! |
I fetch n millions records from SqlServer (streaming) and process over every record. I want to call nested functions into request.on('row', row => { }) and pause streaming until end of latest nested functions.
#NodeJs
#SqlServer
I want this:
Notice: I road tediousjs/tedious#181 and other issue about pause/pesume stream request but I didn't get any idea!
thanks
The text was updated successfully, but these errors were encountered: