]> git.ardis.lu - csvio/commitdiff
Add example to combine retry and graceful failure strategies
authorArdis Lu <ardisglu@gmail.com>
Sat, 25 Jan 2025 08:03:47 +0000 (00:03 -0800)
committerArdis Lu <ardisglu@gmail.com>
Sat, 25 Jan 2025 08:03:47 +0000 (00:03 -0800)
examples/README.md
examples/data/ex2_3-in.csv [new file with mode: 0644]
examples/data/ex2_3-out.csv [new file with mode: 0644]
examples/ex2_3.js [new file with mode: 0644]

index dc9abea7201755beb04b3e2fda84d94b3518b00a..2140aa0c12309bc7bc91f2d87e98b23bec0ed23a 100644 (file)
@@ -32,6 +32,8 @@ These examples demonstrate using the `onError` option to handle transformations
 
 [Example 2.2: Graceful failure (placeholder value)](./ex2_2.js)
 
+[Example 2.3: Truncated binary exponential backoff (retry with graceful failure)](./ex2_3.js)
+
 ### Section 3: Batch and concurrent processing
 
 These examples demonstrate using the `maxBatchSize` and `maxConcurrent` options to process more than one CSV row at a time.
diff --git a/examples/data/ex2_3-in.csv b/examples/data/ex2_3-in.csv
new file mode 100644 (file)
index 0000000..247cafd
--- /dev/null
@@ -0,0 +1,5 @@
+values\r
+a\r
+b\r
+c\r
+d\r
diff --git a/examples/data/ex2_3-out.csv b/examples/data/ex2_3-out.csv
new file mode 100644 (file)
index 0000000..104d9b8
--- /dev/null
@@ -0,0 +1,5 @@
+values\r
+a\r
+n/a\r
+c\r
+d\r
diff --git a/examples/ex2_3.js b/examples/ex2_3.js
new file mode 100644 (file)
index 0000000..25284f2
--- /dev/null
@@ -0,0 +1,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)));
\ No newline at end of file
This page took 0.03617 seconds and 4 git commands to generate.