'use strict'; const common = require('../common'); const Countdown = require('../common/countdown'); const assert = require('assert'); const { AsyncLocalStorage } = require('async_hooks'); const http = require('http'); const cls = new AsyncLocalStorage(); const NUM_CLIENTS = 10; // Run multiple clients that receive data from a server // in multiple chunks, in a single non-closure function. // Use the AsyncLocalStorage (ALS) APIs to maintain the context // and data download. Make sure that individual clients // receive their respective data, with no conflicts. // Set up a server that sends large buffers of data, filled // with cardinal numbers, increasing per request let index = 0; const server = http.createServer((q, r) => { // Send a large chunk as response, otherwise the data // may be sent in a single chunk, and the callback in the // client may be called only once, defeating the purpose of test r.end((index++ % 10).toString().repeat(1024 * 1024)); }); const countdown = new Countdown(NUM_CLIENTS, () => { server.close(); }); server.listen(0, common.mustCall(() => { for (let i = 0; i < NUM_CLIENTS; i++) { cls.run(new Map(), common.mustCall(() => { const options = { port: server.address().port }; const req = http.get(options, common.mustCall((res) => { const store = cls.getStore(); store.set('data', ''); // Make ondata and onend non-closure // functions and fully dependent on ALS res.setEncoding('utf8'); res.on('data', ondata); res.on('end', common.mustCall(onend)); })); req.end(); })); } })); // Accumulate the current data chunk with the store data function ondata(d) { const store = cls.getStore(); assert.notStrictEqual(store, undefined); let chunk = store.get('data'); chunk += d; store.set('data', chunk); } // Retrieve the store data, and test for homogeneity function onend() { const store = cls.getStore(); assert.notStrictEqual(store, undefined); const data = store.get('data'); assert.strictEqual(data, data[0].repeat(data.length)); countdown.dec(); }