Skip to content

Commit bd38dd8

Browse files
authored
fix(compass-import-export): handle export flake COMPASS-8839 (#6622)
* early return when signal is aborted * test for delay abort * close the stream
1 parent ba5c36f commit bd38dd8

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

packages/compass-import-export/src/export/export-json.spec.ts

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,52 @@ describe('exportJSON', function () {
274274
expect(result.docsWritten).to.equal(0);
275275
expect(result.aborted).to.be.true;
276276

277-
let resultText;
278277
try {
279-
resultText = await fs.promises.readFile(resultPath, 'utf8');
278+
await fs.promises.readFile(resultPath, 'utf8');
279+
expect.fail('Expected file to not exist');
280280
} catch (err) {
281-
console.log(resultPath);
282-
throw err;
281+
// noop
283282
}
283+
// close the stream so that afterEach hook can clear the tmpdir
284+
// otherwise it will throw an error (for windows)
285+
output.close();
286+
});
284287

285-
const expectedText = '';
286-
expect(resultText).to.deep.equal(expectedText);
288+
it('responds to abortSignal.aborted - with delayed abort', async function () {
289+
const abortController = new AbortController();
290+
291+
const resultPath = path.join(tmpdir, 'test-abort.exported.ejson');
292+
293+
const importedText = await fs.promises.readFile(
294+
fixtures.json.complex,
295+
'utf8'
296+
);
297+
const ejsonToInsert = EJSON.parse(importedText);
298+
await dataService.insertMany(testNS, ejsonToInsert);
299+
300+
const output = fs.createWriteStream(resultPath);
301+
const promise = exportJSONFromQuery({
302+
dataService,
303+
ns: testNS,
304+
output,
305+
variant: 'default',
306+
abortSignal: abortController.signal,
307+
});
308+
abortController.abort();
309+
310+
const result = await promise;
311+
const data = await fs.promises.readFile(resultPath, 'utf8');
312+
313+
try {
314+
JSON.parse(data);
315+
expect.fail('Expected file to not be valid JSON');
316+
} catch (err) {
317+
// With signal part of streams pipeline the file is created and if
318+
// the signal is aborted the stream is destroyed and file is not
319+
// writable anymore and as a result its not able to write trailing ] to the file.
320+
}
321+
expect(result.aborted).to.be.true;
322+
expect(result.docsWritten).to.equal(0);
287323
});
288324

289325
it('exports aggregations', async function () {

packages/compass-import-export/src/export/export-json.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,15 @@ export async function exportJSON({
5252

5353
const ejsonOptions = getEJSONOptionsForVariant(variant);
5454

55-
if (!abortSignal?.aborted) {
56-
output.write('[');
55+
if (abortSignal?.aborted) {
56+
return {
57+
docsWritten,
58+
aborted: true,
59+
};
5760
}
5861

62+
output.write('[');
63+
5964
const docStream = new Transform({
6065
objectMode: true,
6166
transform: function (chunk: any, encoding, callback) {
@@ -88,21 +93,17 @@ export async function exportJSON({
8893
[inputStream, docStream, output],
8994
...(abortSignal ? [{ signal: abortSignal }] : [])
9095
);
91-
output.write(']\n', 'utf8');
9296
} catch (err: any) {
9397
if (err.code === 'ABORT_ERR') {
94-
// Finish the JSON file as the `final` of the docs stream didn't run.
95-
output.write(']\n', 'utf8');
96-
9798
return {
9899
docsWritten,
99100
aborted: true,
100101
};
101102
}
102-
output.write(']\n', 'utf8');
103-
104103
throw err;
105104
} finally {
105+
// Finish the array output
106+
output.write(']\n');
106107
void input.close();
107108
}
108109

0 commit comments

Comments
 (0)