]> git.ardis.lu - csvio/commitdiff
Add initial error strategies
authorArdis Lu <ardisglu@gmail.com>
Thu, 20 Feb 2025 07:49:23 +0000 (23:49 -0800)
committerArdis Lu <ardisglu@gmail.com>
Thu, 20 Feb 2025 07:49:23 +0000 (23:49 -0800)
src/errorStrategies.js [new file with mode: 0644]
src/index.js

diff --git a/src/errorStrategies.js b/src/errorStrategies.js
new file mode 100644 (file)
index 0000000..46dd805
--- /dev/null
@@ -0,0 +1,80 @@
+import { setTimeout } from 'node:timers/promises';
+
+/** @import {TransformationErrorFunction} from './core.js'; */
+
+/**
+ * Create a `TransformationErrorFunction` that handles errors by filling the output row with a given placeholder value.
+ * 
+ * @param {string} value The placeholder value to fill the row with. This value will be used for each field in the row.
+ * @returns {TransformationErrorFunction} A `TransformationErrorFunction` that may be passed to a `CSVTransformer`'s
+ * `onError` option.
+ */
+function placeholder(value) {
+  return (row) => {
+    if (row.length === 0) {
+      return [value];
+    }
+    else {
+      return Array(row.length).fill(value);
+    }
+  }
+}
+
+/**
+ * Create a `TransformationErrorFunction` that handles errors by immediately retrying it `iterations` number of times.
+ * 
+ * @param {number} iterations The number of times to retry the function.
+ * @param {string} [value] If provided, a placeholder value to set if the function still errors after the final iteration.
+ * If `value` is unset, the final error thrown by the function is re-thrown.
+ * @returns {TransformationErrorFunction} A `TransformationErrorFunction` that may be passed to a `CSVTransformer`'s
+ * `onError` option.
+ * @throws If `value` is unset and the function throws an error after the final iteration, the error is re-thrown.
+ */
+function retry(iterations, value) {
+  return async (row, e, fn) => {
+    while (iterations--) {
+      try { return await fn(row); }
+      catch { }
+    }
+    if (value !== undefined) {
+      return placeholder(value)(row, e, fn);
+    }
+    throw e;
+  }
+}
+
+/**
+ * Create a `TransformationErrorFunction` that handles errors by retrying it an `iterations` number of times, with an
+ * exponentially increasing duration in between each retry (i.e., an exponential backoff).
+ * 
+ * @param {number} iterations The number of times to retry the function.
+ * @param {number} [maxExponent] If provided, the maximum exponent used to calculate the retry duration. In other words,
+ * the `iterations` number at which the retry duration stops increasing. If `maxExponent` is unset, the retry duration
+ * is unbounded and will increase after each retry.
+ * @param {string} [value] If provided, a placeholder value to set if the function still errors after the final iteration.
+ * If `value` is unset, the final error thrown by the function is re-thrown.
+ * @returns {TransformationErrorFunction} A `TransformationErrorFunction` that may be passed to a `CSVTransformer`'s
+ * `onError` option.
+ * @throws If `value` is unset and the function throws an error after the final iteration, the error is re-thrown.
+ */
+function backoff(iterations, maxExponent, value) {
+  if (maxExponent === undefined) {
+    maxExponent = Infinity;
+  }
+  return async (row, e, fn) => {
+    for (let n = 0; n < iterations; n++) {
+      const exponent = n > maxExponent ? maxExponent : n;
+      const duration = (2 ** exponent) * 1000; // 1s, 2s, 4s, 8s, 16s, ...
+      const jitter = Math.random() * 1000;
+      await setTimeout(duration + jitter);
+      try { return await fn(row); }
+      catch { }
+    }
+    if (value !== undefined) {
+      return placeholder(value)(row, e, fn);
+    }
+    throw e;
+  }
+}
+
+export const ErrorStrategies = { placeholder, retry, backoff };
\ No newline at end of file
index 22441a5ac65ceff32045d4c826b2da3f59aaf2e4..0e82f90a4532b79dfa6a52e321a09a3b9fae4185 100644 (file)
@@ -1,2 +1,3 @@
 export { CSVReader, CSVTransformer, CSVWriter } from './core.js';
 export { CSVNormalizer, CSVDenormalizer } from './normalization.js';
+export { ErrorStrategies } from './errorStrategies.js';
This page took 0.044958 seconds and 4 git commands to generate.