-
-
Notifications
You must be signed in to change notification settings - Fork 972
Description
Describe the bug
- Node.js version: 14.14
- OS & version: Ubuntu 18 LTS
We aren't really sure where to start on this one, including with a tighter reproduction, so any pointers on how to proceed / what it might be would be appreciated.
We suspect it is somehow in how we're connecting got <> fastify over a stream, and while we finally got it reproducible, currently on a large test + deep in our app.
Some clues:
-
This seems to appear for bigger buffers, vs smaller, but unclear. Normally I wouldn't file this coarse of an issue, but it's a weird one for us to dig into.
-
On the fastify side, the closest related we saw is Sporadic ERR_STREAM_PREMATURE_CLOSE fastify/fastify-static#116
-
We've had to iterate with
eoshandling this year as that has been changing in various engine/libs, though not in the last ~2 months
Actual behavior
See trace on below got request, including auto-retry also failing (deterministic re-fail is promising..):
// Call got in promise mode so it automatically retries these requests
// The GPU worker socket is volatile, likes to throw `EAGAIN` errors
// when you request things of it while simulating.
// Use timeouts as canaries
const fullNodeCPUTable = readFullNodeCPUTable(sessionId, {timeout: 4042, retry: 10}).then((o) => {
return o.body;
});
let preshapedNodes = Table.from(fullNodeCPUTable);=>
const gotTable = ({ id, name, tableKind = '', headers = {}, ...rest }) => (got.extend({
method: 'POST',
responseType: 'buffer',
searchParams: { id },
headers: {
'Accept': 'application/octet-stream',
'Content-Type':'application/x-www-form-urlencoded',
...headers
},
...rest
})(`${basePath}/${Path.join(...[name, tableKind].filter(Boolean))}`))And on the fastify service side, we're going through https://github.com/apache/arrow/blob/fbb781bcdd15d54c52c71881c5c53d0c68069be6/js/src/ipc/reader.ts#L521 :
=>
const pump = require('stream').pipeline;
const { AsyncIterable } = require('ix');
const { RecordBatchStreamWriter } = require('apache-arrow');
const eos = require('util').promisify(require('stream').finished);
compress = true;
layoutOptions && graph.setLayoutOptions(layoutOptions).commit();
readers = AsyncIterable.as(readEverything(graph, { filtered }));
const stream = pump(
readers.concatAll().toNodeStream({ objectMode: true }),
RecordBatchStreamWriter.throughNode({ autoDestroy: false }),
(error) => error && req.log.error(error)
);
reply.type('application/octet-stream').compress(stream);
await eos(stream);=> Session logs:
streamgl-viz_1 | 2020-12-16T01:19:04.737456537Z {"level":20,"time":1608081544737,"pid":37,"hostname":"c8902bb4fd5f","filename":"/opt/graphistry/apps/lib/instrumentation/got.js","msg":"making got request: POST http://nginx/streamgl/read/edge?id=5a8c492f27f14ce78643763697bf546d"}
streamgl-gpu_1 | 2020-12-16T01:19:04.756894359Z {"level":20,"time":1608081544755,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/services/read.js","msg":"@worker /read handler"}
streamgl-gpu_1 | 2020-12-16T01:19:04.777813111Z {"level":20,"time":1608081544776,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/services/read.js","msg":"@worker /read handler"}
streamgl-gpu_1 | 2020-12-16T01:19:04.876936627Z {"level":50,"time":1608081543975,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/index.js","reqId":5,"payload":{"type":"NodeError","message":"Premature close","stack":"Error: Premature close\n at Duplexify.onclose (/opt/graphistry/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:62:73)\n at Duplexify.emit (events.js:327:22)\n at Duplexify.EventEmitter.emit (domain.js:486:12)\n at Duplexify._destroy (/opt/graphistry/node_modules/duplexify/index.js:199:8)\n at /opt/graphistry/node_modules/duplexify/index.js:182:10\n at processTicksAndRejections (internal/process/task_queues.js:75:11)","name":"Error","code":"ERR_STREAM_PREMATURE_CLOSE"}}
streamgl-gpu_1 | 2020-12-16T01:19:04.877394780Z {"level":50,"time":1608081543976,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/index.js","reqId":5,"payload":{"id":5,"err":{"type":"Error","message":"Something went wrong","stack":"Error: Something went wrong\n at Object.<anonymous> (/opt/graphistry/node_modules/fastify-sensible/index.js:49:20)\n at handleError (/opt/graphistry/node_modules/fastify/lib/reply.js:525:18)\n at onErrorHook (/opt/graphistry/node_modules/fastify/lib/reply.js:496:5)\n at Duplexify.<anonymous> (/opt/graphistry/node_modules/fastify/lib/reply.js:444:9)\n at Duplexify.<anonymous> (/opt/graphistry/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:17:14)\n at Duplexify.onclose (/opt/graphistry/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:63:23)\n at Duplexify.emit (events.js:327:22)\n at Duplexify.EventEmitter.emit (domain.js:486:12)\n at Duplexify._destroy (/opt/graphistry/node_modules/duplexify/index.js:199:8)\n at /opt/graphistry/node_modules/duplexify/index.js:182:10\n at processTicksAndRejections (internal/process/task_queues.js:75:11)"},"req":{"method":"POST","url":"/read/edge?id=5a8c492f27f14ce78643763697bf546d","headers":{"x-forwarded-host":"streamgl-gpu","x-forwarded-proto":"http","x-forwarded-port":"80","x-forwarded-for":"::ffff:172.21.0.15","accept-encoding":"gzip, deflate, br","content-type":"application/x-www-form-urlencoded","accept":"application/octet-stream","user-agent":"@graphistry/viz::@streamgl/gpu-worker","content-length":"55","host":"streamgl-gpu","connection":"close"}},"res":{"statusCode":500,"headers":{"content-security-policy":"default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests","x-dns-prefetch-control":"off","expect-ct":"max-age=0","x-frame-options":"SAMEORIGIN","strict-transport-security":"max-age=15552000; includeSubDomains","x-download-options":"noopen","x-content-type-options":"nosniff","x-permitted-cross-domain-policies":"none","referrer-policy":"no-referrer","x-xss-protection":"0","vary":["Origin","accept-encoding"],"access-control-allow-origin":"","content-type":"application/octet-stream","content-encoding":"br","x-response-time":"24.67"}}},"msg":"Uncaught error in fastify route"}
streamgl-viz_1 | 2020-12-16T01:19:06.045835231Z {"level":20,"time":1608081546045,"pid":37,"hostname":"c8902bb4fd5f","filename":"/opt/graphistry/apps/lib/instrumentation/got.js","msg":"got response 200 :: undefined from http://nginx/streamgl/read/node?id=5a8c492f27f14ce78643763697bf546d"}
streamgl-gpu_1 | 2020-12-16T01:19:08.768667002Z {"level":50,"time":1608081548767,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/graph.js","payload":{"err":{"type":"NodeError","message":"Premature close","stack":"Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close\n at RecordBatchWriterDuplex.onclose (internal/streams/end-of-stream.js:117:38)\n at RecordBatchWriterDuplex.emit (events.js:327:22)\n at RecordBatchWriterDuplex.EventEmitter.emit (domain.js:486:12)\n at emitCloseNT (internal/streams/destroy.js:87:10)\n at processTicksAndRejections (internal/process/task_queues.js:79:21)","code":"ERR_STREAM_PREMATURE_CLOSE"},"id":"5a8c492f27f14ce78643763697bf546d"},"msg":"graph transaction exn"}
streamgl-viz_1 | 2020-12-16T01:19:09.815851381Z {"level":20,"time":1608081549815,"pid":37,"hostname":"c8902bb4fd5f","filename":"/opt/graphistry/apps/lib/instrumentation/got.js","payload":{},"msg":"retry"}
streamgl-viz_1 | 2020-12-16T01:19:09.816972435Z {"level":20,"time":1608081549816,"pid":37,"hostname":"c8902bb4fd5f","filename":"/opt/graphistry/apps/lib/instrumentation/got.js","msg":"making got request: POST http://nginx/streamgl/read/edge?id=5a8c492f27f14ce78643763697bf546d"}
streamgl-gpu_1 | 2020-12-16T01:19:09.829828453Z {"level":20,"time":1608081549828,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/services/read.js","msg":"@worker /read handler"}
streamgl-gpu_1 | 2020-12-16T01:19:10.137158606Z {"level":50,"time":1608081548757,"pid":45,"hostname":"eb60848f7d23","filename":"/opt/graphistry/apps/streamgl/gpu-worker/index.js","reqId":7,"payload":{"type":"NodeError","message":"Premature close","stack":"Error: Premature close\n at Duplexify.onclose (/opt/graphistry/node_modules/fastify/node_modules/readable-stream/lib/internal/streams/end-of-stream.js:62:73)\n at Duplexify.emit (events.js:327:22)\n at Duplexify.EventEmitter.emit (domain.js:486:12)\n at Duplexify._destroy (/opt/graphistry/node_modules/duplexify/index.js:199:8)\n at /opt/graphistry/node_modules/duplexify/index.js:182:10\n at processTicksAndRejections (internal/process/task_queues.js:75:11)","name":"Error","code":"ERR_STREAM_PREMATURE_CLOSE"}}
Checklist
- [x ] I have read the documentation.
- I have tried my code with the latest version of Node.js and Got.