question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Resume-Pause in stream is not working as expected

See original GitHub issue

I am trying to export Database having 3 million records to CSV file. Writing to CSV is slow compared to reading from database so it was continue fetching and storing all the rows into memory so it was causing memory exhaustion. So I used pause-resume feature released latest version. I had lots of hope on that, but it didn’t work 😦

Here is my code what I tried:

	const sql = require('mssql')
	const fs = require('fs')
	const { Writable, Readable } = require('stream')

	let request, pool1
	let count = 0;
	let write = 0;
	let isRequestPaused = false;

	let fsWrite = fs.createWriteStream('./output', {flags: 'a'});

	let fields;
	let opts;

	console.log('Start => ', new Date());

	const config = {
	    user: '...',
	    password: '...',
	    server: '...',
	    database: '...',
	    options: {
		encrypt: true
	    }
	}

	class MyReadableStream extends Readable {
	    constructor(options) {
		super(options);

		this._request = getRequest();

		this._request.on('row', row => {
		    count++;
		    if (count % 100000 === 0) {
		        console.log('Now => ', new Date());
		        console.log('Row => ', count);
		    }
		    if (!this.push(row)) {
		        isRequestPaused = true;
		        console.log('Request Paused =>');
		        this._request.pause();
		    }
		})
	    
		this._request.on('done', result => {
		    console.log('Done');
		    this.push(null);
		    console.log('End => ', new Date());
		})
	    }

	    _read () {
		if (count % 100000 === 0) {
		    console.log('Read row =>');
		}
		if (isRequestPaused) {
		    console.log('Request Resumed =>');
		    this._request.resume();
		    isRequestPaused = false;
		}
	    }
	}

	class MyWritableStream extends Writable {
	    constructor(options) {
		super(options);
	    }

	    _write (chunk, encoding, callback) {
		write++
		if (write % 100000 === 0) {
		    console.log('Write Row => ', write);
		}
		fsWrite.write(JSON.stringify(chunk), null, callback);
	    }

	    _final () {
		console.log('Done writing');
	    }
	}

	function getRequest () {
	    request = pool1.request()
	    
	    request.stream = true

	    request.query('SELECT * FROM largeTable')

	    return request
	}

	async function main () {
	    pool1 = await new sql.ConnectionPool(config).connect()
	    
	    pool1.on('error', error => {
		console.error('Error in connection pool => ', error)
	    })

	    const myReadableStream = new MyReadableStream({
		objectMode: true
	    });
	    const myWritableStream = new MyWritableStream({
		objectMode: true
	    });

	    myReadableStream.pipe(myWritableStream);
	}

	main();

This is what I expected:

Whenever this.push() returns false, request should pause and no more data should fetched until request.resume has been called.

But this is what I observed:

After some data fetched request.pause() has been called and after some time request.resume() has been called at regular interval but it was fetching data even though request was paused.

Here is the video of execution of my program: https://filebin.net/yuwq0j27ki05ajwz

You can notice that request.pause() and request.resume() are triggered at regular interval. At starting point, network speed was vary between 100Mbps t o 500Mbps. So it was fetching too many records and meanwhile memory utilisation increases rapidly. And then after some point network speed dropped around 1Mbps at that point of time memory utilisation by Node is around 2 GB. So what it did was even though I have called request.pause() it continued to fetch record and store in memory.

So my memory exhaustion problem still persist.

Can anyone please help? Thanks in advance.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
arthurschreibercommented, Mar 16, 2019

The fix for this is part of the tedious@6.0.1 release. 🎉

0reactions
dhensbycommented, May 7, 2019

There’s no timeline currently defined for moving 6.0 into stable.

I could move it into beta in the coming days

Read more comments on GitHub >

github_iconTop Results From Across the Web

ReadableStream.pause() not working when stream is piped.
You've piped the stream to stdout, so every time stdout drains, it's going to .resume() it.
Read more >
javascript - NodeJS stream pausing/resuming does not work ...
A very useful use-case of pause is within a proxy: you read from upstream, and write to the client. If the write to...
Read more >
When is pause / resume more efficient then stop? - Forum
I am planning to have requests with interest open for many items. I expect for high volume / high popularity items the streams...
Read more >
RTP Stream Pause and Resume RFC 7728 - IETF Datatracker
Request Retransmission When the stream is not affected as expected by a PAUSE or RESUME request, the request may have been lost and...
Read more >
How to pause and resume streams periodically - Kafka Streams
Hi I have a question. I have 2 topics. I want to periodically transfer a message from one topic to another. For example...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found