retry-busy.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // note: max backoff is the maximum that any *single* backoff will do
  2. export const MAXBACKOFF = 200;
  3. export const RATE = 1.2;
  4. export const MAXRETRIES = 10;
  5. export const codes = new Set(['EMFILE', 'ENFILE', 'EBUSY']);
  6. export const retryBusy = (fn) => {
  7. const method = async (path, opt, backoff = 1, total = 0) => {
  8. const mbo = opt.maxBackoff || MAXBACKOFF;
  9. const rate = opt.backoff || RATE;
  10. const max = opt.maxRetries || MAXRETRIES;
  11. let retries = 0;
  12. while (true) {
  13. try {
  14. return await fn(path);
  15. }
  16. catch (er) {
  17. const fer = er;
  18. if (fer?.path === path && fer?.code && codes.has(fer.code)) {
  19. backoff = Math.ceil(backoff * rate);
  20. total = backoff + total;
  21. if (total < mbo) {
  22. return new Promise((res, rej) => {
  23. setTimeout(() => {
  24. method(path, opt, backoff, total).then(res, rej);
  25. }, backoff);
  26. });
  27. }
  28. if (retries < max) {
  29. retries++;
  30. continue;
  31. }
  32. }
  33. throw er;
  34. }
  35. }
  36. };
  37. return method;
  38. };
  39. // just retries, no async so no backoff
  40. export const retryBusySync = (fn) => {
  41. const method = (path, opt) => {
  42. const max = opt.maxRetries || MAXRETRIES;
  43. let retries = 0;
  44. while (true) {
  45. try {
  46. return fn(path);
  47. }
  48. catch (er) {
  49. const fer = er;
  50. if (fer?.path === path &&
  51. fer?.code &&
  52. codes.has(fer.code) &&
  53. retries < max) {
  54. retries++;
  55. continue;
  56. }
  57. throw er;
  58. }
  59. }
  60. };
  61. return method;
  62. };
  63. //# sourceMappingURL=retry-busy.js.map