Repository navigation
Expand file tree
/
Copy pathex2_3.js
More file actions
40 lines (34 loc) · 1.4 KB
/
Copy pathex2_3.js
File metadata and controls
40 lines (34 loc) · 1.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ## Example 2.3: Truncated binary exponential backoff (retry with graceful failure)
import { setTimeout } from 'node:timers/promises';
import { CSVReader, CSVTransformer, CSVWriter } from '../src/index.js';
// Simple implementation of exponential backoff with graceful failure at a given termination point
// https://en.wikipedia.org/wiki/Exponential_backoff
async function backoff(row, fn, truncate = 4) {
for (let n = 0; n < truncate; n++) {
const duration = (2 ** n) * 1000; // 1s, 2s, 4s, 8s, 16s, ...
const jitter = Math.random() * 1000;
// Reducing sleep by 1000x to avoid slowing down tests, comment out to use real time backoff
const timeout = (duration + jitter) / 1000;
await setTimeout(timeout);
try { return await fn(row); }
catch { }
}
return row.map(() => 'n/a'); // If tried `truncate` number of times, set row to "n/a" and proceed
}
// Each row will fail the number of times indicated in the mapping
// All rows should be retried until passed, except for "b" which gracefully fails to "n/a"
const fails = {
a: 1,
b: 8,
c: 4,
d: 0
};
function willFail(row) {
if (fails[row[0]]--) {
throw new Error();
}
return row;
}
await new CSVReader(new URL('./data/ex2_3-in.csv', import.meta.url))
.pipeThrough(new CSVTransformer(willFail, { onError: (row, e, fn) => backoff(row, fn, 4) }))
.pipeTo(new CSVWriter(new URL('./data/ex2_3-out.csv', import.meta.url)));