@ancon/wildcat-utils 1.50.18 → 1.50.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { APIHeaders } from '@ancon/wildcat-types';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
2
3
|
declare type HangfirePollerConfig = {
|
|
3
4
|
/** Poller interval in milliseconds */
|
|
4
5
|
pollerInterval: number;
|
|
@@ -17,8 +18,10 @@ declare type HangfirePollerConfig = {
|
|
|
17
18
|
getIsNetworkOnline: () => boolean;
|
|
18
19
|
/** Async function returning any API headers for the request */
|
|
19
20
|
getRequestHeaders: () => Promise<APIHeaders>;
|
|
20
|
-
/**
|
|
21
|
+
/** Development debug logging callback */
|
|
21
22
|
debug: (...args: any[]) => void;
|
|
23
|
+
/** Optional logger implementation for real logs */
|
|
24
|
+
logger?: Logger;
|
|
22
25
|
};
|
|
23
26
|
declare class HangfirePoller {
|
|
24
27
|
/** Workers currently executing a request */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var x=Object.defineProperty;var W=(i,e,r)=>e in i?x(i,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):i[e]=r;var o=(i,e,r)=>(W(i,typeof e!="symbol"?e+"":e,r),r);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const y=require("axios"),l=require("@ancon/wildcat-types"),d=require("../error/createCodedError.js"),I=require("../error/isNotFoundError.js"),f=require("../error/serializeError.js"),w=require("../error/isErrorWithStatusCode.js"),q=require("../api/isNoContentResponse.js"),b=require("../shared/wait.js");require("../error/isCodedError.js");require("../error/isAPIError.js");class m{constructor(e){o(this,"busyWorkers",new Set);o(this,"enabledGroups",new Set);o(this,"groups",new Map);o(this,"workerByIdMap",new Map);o(this,"timer",null);o(this,"config",{pollerInterval:5e3,maxGroupsSize:50,maxWorkersSize:20,responseInterceptor:void 0,responseRejectionInterceptor:void 0,getIsNetworkOnline(){return!0},async getRequestHeaders(){return{}},debug(...e){console.log(...e)}});o(this,"axiosInstance");this.config={...this.config,...e??null},this.axiosInstance=y.create(),(this.config.responseInterceptor||this.config.responseRejectionInterceptor)&&this.axiosInstance.interceptors.response.use(this.config.responseInterceptor,this.config.responseRejectionInterceptor)}stopTimer(){this.timer!=null&&(this.config.debug("*stop timer*"),clearInterval(this.timer),this.timer=null)}startTimer(){if(this.timer!=null)throw d(new Error("Timer already started"),l.ErrorCode.GenericUnexpectedHangfireError);this.config.debug("*start timer*"),this.timer=setInterval(()=>{this.config.debug("*tick*",{busyWorkers:this.busyWorkers.size,enabledGroups:this.enabledGroups.size,groups:this.groups}),this.enabledGroups.forEach(e=>{const r=this.groups.get(e);r&&r.forEach(t=>this.executeWorkerRequest(t))}),this.groups.size<1&&this.stopTimer()},this.config.pollerInterval)}async waitForNetworkOnline(e=5){let r=0;for(;!this.config.getIsNetworkOnline()&&r<e+1;)r+=1,await b(1e3)}async executeWorkerRequest(e,r=!1){var a,u,h,c;const t=r!==!0&&this.busyWorkers.has(e.workerId);if(this.config.debug("*executeWorkerRequest*",{workerId:e.workerId,isBusy:t,force:r}),t){this.config.debug("*executeWorkerRequest* worker is busy",e.workerId);return}this.busyWorkers.add(e.workerId),await this.waitForNetworkOnline(),this.config.debug("*executeWorkerRequest* request",{isNetworkOnline:this.config.getIsNetworkOnline()});const g={...await this.config.getRequestHeaders(),...e.headers},p=2;let s=0;for(;s<=p;)try{const n=await this.axiosInstance({url:e.url,method:"get",timeout:this.config.pollerInterval,headers:g});q(n)?this.busyWorkers.delete(e.workerId):(e.resolve(n),(a=e.onFinished)==null||a.call(e,r),this.deleteWorker(e.groupId,e.workerId));break}catch(n){if(w(n)){if(I(n)){this.config.debug("*executeWorkerRequest* worker is expired or invalid",e.workerId);const k=f(d(new Error("The Hangfire worker is expired or invalid"),l.ErrorCode.HangfireWorkerExpiredOrInvalid));e.reject(k),(u=e.onFinished)==null||u.call(e,r)}else e.reject(n),(h=e.onFinished)==null||h.call(e,r);this.deleteWorker(e.groupId,e.workerId);break}else if(this.config.debug("*executeWorkerRequest* not an api error"),(c=this.config.logger)==null||c.warn(`Hangfire worker request error: ${JSON.stringify({attempt:s,groupId:e.groupId,workerId:e.workerId,error:f(n)})}`,{CorrelationId:g["x-correlation-id"]}),r&&s<p)s+=1,this.config.debug(`*executeWorkerRequest* retrying non-API error (attempt ${s})`),await b(500);else{this.busyWorkers.delete(e.workerId);break}}}deleteWorker(e,r){const t=this.groups.get(e);t&&(this.config.debug("*delete worker*",t.size,t),t.delete(r),this.workerByIdMap.delete(r),this.busyWorkers.delete(r),t.size<1&&(this.groups.delete(e),this.enabledGroups.delete(e),this.enabledGroups.size<1&&this.stopTimer()))}createWorker(e,{workerId:r,url:t,headers:g,onFinished:p}){if(!this.groups.has(e)){if(this.groups.size>=this.config.maxGroupsSize){const a=d(new Error("Max number of Hangfire groups exceeded"),l.ErrorCode.GenericUnexpectedHangfireError,{count:this.groups.size});throw this.destroy(),a}this.groups.set(e,new Map)}const s=this.groups.get(e);return new Promise((a,u)=>{if(s.has(r))throw d(new Error("Duplicate Hangfire worker ID"),l.ErrorCode.GenericUnexpectedHangfireError);if(s.size>=this.config.maxWorkersSize){const c=d(new Error("Max number of Hangfire workers in group exceeded"),l.ErrorCode.GenericUnexpectedHangfireError,{groupId:e,count:s.size});throw u(c),this.destroy(),c}const h={workerId:r,groupId:e,url:t,resolve:a,reject:u,headers:g,onFinished:p};s.set(r,h),this.workerByIdMap.set(r,h),this.enabledGroups.has(e)||this.enabledGroups.add(e),this.timer==null&&this.enabledGroups.size>0&&this.startTimer()})}triggerWorker(e){this.config.debug("*triggerWorker*");const r=this.workerByIdMap.get(e);r?this.executeWorkerRequest(r,!0):this.config.debug("*triggerWorker* worker not found",e)}triggerAllWorkers(){this.config.debug("*triggerAllWorkers*");for(const e of this.workerByIdMap.values())this.executeWorkerRequest(e)}enableWorkers(e){this.config.debug("*enable*",e),this.enabledGroups.add(e),this.groups.has(e)&&this.timer==null&&this.startTimer()}disableWorkers(e){this.config.debug("*disable*",e),this.enabledGroups.delete(e),this.enabledGroups.size<1&&this.stopTimer()}destroy(){this.config.debug("*destroy*"),this.groups.clear(),this.stopTimer()}}function E(i){return new m(i)}exports.HangfirePoller=m;exports.default=E;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var o = (
|
|
4
|
-
import
|
|
5
|
-
import { ErrorCode as
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
1
|
+
var x = Object.defineProperty;
|
|
2
|
+
var k = (s, e, r) => e in s ? x(s, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : s[e] = r;
|
|
3
|
+
var o = (s, e, r) => (k(s, typeof e != "symbol" ? e + "" : e, r), r);
|
|
4
|
+
import W from "axios";
|
|
5
|
+
import { ErrorCode as g } from "@ancon/wildcat-types";
|
|
6
|
+
import l from "../error/createCodedError.mjs";
|
|
7
|
+
import y from "../error/isNotFoundError.mjs";
|
|
8
|
+
import f from "../error/serializeError.mjs";
|
|
9
|
+
import I from "../error/isErrorWithStatusCode.mjs";
|
|
10
|
+
import w from "../api/isNoContentResponse.mjs";
|
|
11
|
+
import m from "../shared/wait.mjs";
|
|
12
12
|
import "../error/isCodedError.mjs";
|
|
13
13
|
import "../error/isAPIError.mjs";
|
|
14
|
-
class
|
|
14
|
+
class E {
|
|
15
15
|
constructor(e) {
|
|
16
16
|
/** Workers currently executing a request */
|
|
17
17
|
o(this, "busyWorkers", /* @__PURE__ */ new Set());
|
|
@@ -42,7 +42,7 @@ class I {
|
|
|
42
42
|
this.config = {
|
|
43
43
|
...this.config,
|
|
44
44
|
...e ?? null
|
|
45
|
-
}, this.axiosInstance =
|
|
45
|
+
}, this.axiosInstance = W.create(), (this.config.responseInterceptor || this.config.responseRejectionInterceptor) && this.axiosInstance.interceptors.response.use(
|
|
46
46
|
this.config.responseInterceptor,
|
|
47
47
|
this.config.responseRejectionInterceptor
|
|
48
48
|
);
|
|
@@ -52,9 +52,9 @@ class I {
|
|
|
52
52
|
}
|
|
53
53
|
startTimer() {
|
|
54
54
|
if (this.timer != null)
|
|
55
|
-
throw
|
|
55
|
+
throw l(
|
|
56
56
|
new Error("Timer already started"),
|
|
57
|
-
|
|
57
|
+
g.GenericUnexpectedHangfireError
|
|
58
58
|
);
|
|
59
59
|
this.config.debug("*start timer*"), this.timer = setInterval(() => {
|
|
60
60
|
this.config.debug("*tick*", {
|
|
@@ -62,113 +62,139 @@ class I {
|
|
|
62
62
|
enabledGroups: this.enabledGroups.size,
|
|
63
63
|
groups: this.groups
|
|
64
64
|
}), this.enabledGroups.forEach((e) => {
|
|
65
|
-
const
|
|
66
|
-
|
|
65
|
+
const r = this.groups.get(e);
|
|
66
|
+
r && r.forEach((t) => this.executeWorkerRequest(t));
|
|
67
67
|
}), this.groups.size < 1 && this.stopTimer();
|
|
68
68
|
}, this.config.pollerInterval);
|
|
69
69
|
}
|
|
70
70
|
async waitForNetworkOnline(e = 5) {
|
|
71
|
-
let
|
|
72
|
-
for (; !this.config.getIsNetworkOnline() &&
|
|
73
|
-
|
|
71
|
+
let r = 0;
|
|
72
|
+
for (; !this.config.getIsNetworkOnline() && r < e + 1; )
|
|
73
|
+
r += 1, await m(1e3);
|
|
74
74
|
}
|
|
75
|
-
async executeWorkerRequest(e,
|
|
76
|
-
|
|
77
|
-
this.
|
|
75
|
+
async executeWorkerRequest(e, r = !1) {
|
|
76
|
+
var a, h, u, c;
|
|
77
|
+
const t = r !== !0 && this.busyWorkers.has(e.workerId);
|
|
78
|
+
if (this.config.debug("*executeWorkerRequest*", {
|
|
78
79
|
workerId: e.workerId,
|
|
79
|
-
isBusy:
|
|
80
|
-
force:
|
|
81
|
-
}),
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
isBusy: t,
|
|
81
|
+
force: r
|
|
82
|
+
}), t) {
|
|
83
|
+
this.config.debug(
|
|
84
|
+
"*executeWorkerRequest* worker is busy",
|
|
85
|
+
e.workerId
|
|
86
|
+
);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.busyWorkers.add(e.workerId), await this.waitForNetworkOnline(), this.config.debug("*executeWorkerRequest* request", {
|
|
85
90
|
isNetworkOnline: this.config.getIsNetworkOnline()
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
});
|
|
92
|
+
const d = {
|
|
93
|
+
...await this.config.getRequestHeaders(),
|
|
94
|
+
...e.headers
|
|
95
|
+
}, p = 2;
|
|
96
|
+
let i = 0;
|
|
97
|
+
for (; i <= p; )
|
|
98
|
+
try {
|
|
99
|
+
const n = await this.axiosInstance({
|
|
100
|
+
url: e.url,
|
|
101
|
+
method: "get",
|
|
102
|
+
timeout: this.config.pollerInterval,
|
|
103
|
+
headers: d
|
|
104
|
+
});
|
|
105
|
+
w(n) ? this.busyWorkers.delete(e.workerId) : (e.resolve(n), (a = e.onFinished) == null || a.call(e, r), this.deleteWorker(e.groupId, e.workerId));
|
|
106
|
+
break;
|
|
107
|
+
} catch (n) {
|
|
108
|
+
if (I(n)) {
|
|
109
|
+
if (y(n)) {
|
|
110
|
+
this.config.debug(
|
|
111
|
+
"*executeWorkerRequest* worker is expired or invalid",
|
|
112
|
+
e.workerId
|
|
113
|
+
);
|
|
114
|
+
const b = f(
|
|
115
|
+
l(
|
|
116
|
+
new Error("The Hangfire worker is expired or invalid"),
|
|
117
|
+
g.HangfireWorkerExpiredOrInvalid
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
e.reject(b), (h = e.onFinished) == null || h.call(e, r);
|
|
121
|
+
} else
|
|
122
|
+
e.reject(n), (u = e.onFinished) == null || u.call(e, r);
|
|
123
|
+
this.deleteWorker(e.groupId, e.workerId);
|
|
124
|
+
break;
|
|
125
|
+
} else if (this.config.debug("*executeWorkerRequest* not an api error"), (c = this.config.logger) == null || c.warn(
|
|
126
|
+
`Hangfire worker request error: ${JSON.stringify({
|
|
127
|
+
attempt: i,
|
|
128
|
+
groupId: e.groupId,
|
|
129
|
+
workerId: e.workerId,
|
|
130
|
+
error: f(n)
|
|
131
|
+
})}`,
|
|
132
|
+
{
|
|
133
|
+
CorrelationId: d["x-correlation-id"]
|
|
134
|
+
}
|
|
135
|
+
), r && i < p)
|
|
136
|
+
i += 1, this.config.debug(
|
|
137
|
+
`*executeWorkerRequest* retrying non-API error (attempt ${i})`
|
|
138
|
+
), await m(500);
|
|
139
|
+
else {
|
|
140
|
+
this.busyWorkers.delete(e.workerId);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
93
143
|
}
|
|
94
|
-
}).then((s) => {
|
|
95
|
-
var n;
|
|
96
|
-
s && !k(s) ? (e.resolve(s), (n = e.onFinished) == null || n.call(e, t), this.deleteWorker(e.groupId, e.workerId)) : this.busyWorkers.delete(e.workerId);
|
|
97
|
-
}).catch((s) => {
|
|
98
|
-
var n, a;
|
|
99
|
-
if (x(s)) {
|
|
100
|
-
if (b(s)) {
|
|
101
|
-
this.config.debug(
|
|
102
|
-
"*executeWorkerRequest* worker is expired or invalid",
|
|
103
|
-
e.workerId
|
|
104
|
-
);
|
|
105
|
-
const h = W(
|
|
106
|
-
c(
|
|
107
|
-
new Error("The Hangfire worker is expired or invalid"),
|
|
108
|
-
u.HangfireWorkerExpiredOrInvalid
|
|
109
|
-
)
|
|
110
|
-
);
|
|
111
|
-
e.reject(h), (n = e.onFinished) == null || n.call(e, t);
|
|
112
|
-
} else
|
|
113
|
-
e.reject(s), (a = e.onFinished) == null || a.call(e, t);
|
|
114
|
-
this.deleteWorker(e.groupId, e.workerId);
|
|
115
|
-
} else
|
|
116
|
-
this.config.debug("*executeWorkerRequest* not an api error"), this.busyWorkers.delete(e.workerId);
|
|
117
|
-
}));
|
|
118
144
|
}
|
|
119
|
-
deleteWorker(e,
|
|
120
|
-
const
|
|
121
|
-
|
|
145
|
+
deleteWorker(e, r) {
|
|
146
|
+
const t = this.groups.get(e);
|
|
147
|
+
t && (this.config.debug("*delete worker*", t.size, t), t.delete(r), this.workerByIdMap.delete(r), this.busyWorkers.delete(r), t.size < 1 && (this.groups.delete(e), this.enabledGroups.delete(e), this.enabledGroups.size < 1 && this.stopTimer()));
|
|
122
148
|
}
|
|
123
149
|
createWorker(e, {
|
|
124
|
-
workerId:
|
|
125
|
-
url:
|
|
126
|
-
headers:
|
|
127
|
-
onFinished:
|
|
150
|
+
workerId: r,
|
|
151
|
+
url: t,
|
|
152
|
+
headers: d,
|
|
153
|
+
onFinished: p
|
|
128
154
|
}) {
|
|
129
155
|
if (!this.groups.has(e)) {
|
|
130
156
|
if (this.groups.size >= this.config.maxGroupsSize) {
|
|
131
|
-
const
|
|
157
|
+
const a = l(
|
|
132
158
|
new Error("Max number of Hangfire groups exceeded"),
|
|
133
|
-
|
|
159
|
+
g.GenericUnexpectedHangfireError,
|
|
134
160
|
{ count: this.groups.size }
|
|
135
161
|
);
|
|
136
|
-
throw this.destroy(),
|
|
162
|
+
throw this.destroy(), a;
|
|
137
163
|
}
|
|
138
164
|
this.groups.set(e, /* @__PURE__ */ new Map());
|
|
139
165
|
}
|
|
140
|
-
const
|
|
141
|
-
return new Promise((
|
|
142
|
-
if (
|
|
143
|
-
throw
|
|
166
|
+
const i = this.groups.get(e);
|
|
167
|
+
return new Promise((a, h) => {
|
|
168
|
+
if (i.has(r))
|
|
169
|
+
throw l(
|
|
144
170
|
new Error("Duplicate Hangfire worker ID"),
|
|
145
|
-
|
|
171
|
+
g.GenericUnexpectedHangfireError
|
|
146
172
|
);
|
|
147
|
-
if (
|
|
148
|
-
const
|
|
173
|
+
if (i.size >= this.config.maxWorkersSize) {
|
|
174
|
+
const c = l(
|
|
149
175
|
new Error("Max number of Hangfire workers in group exceeded"),
|
|
150
|
-
|
|
151
|
-
{ groupId: e, count:
|
|
176
|
+
g.GenericUnexpectedHangfireError,
|
|
177
|
+
{ groupId: e, count: i.size }
|
|
152
178
|
);
|
|
153
|
-
throw
|
|
179
|
+
throw h(c), this.destroy(), c;
|
|
154
180
|
}
|
|
155
|
-
const
|
|
156
|
-
workerId:
|
|
181
|
+
const u = {
|
|
182
|
+
workerId: r,
|
|
157
183
|
groupId: e,
|
|
158
|
-
url:
|
|
159
|
-
resolve:
|
|
160
|
-
reject:
|
|
161
|
-
headers:
|
|
162
|
-
onFinished:
|
|
184
|
+
url: t,
|
|
185
|
+
resolve: a,
|
|
186
|
+
reject: h,
|
|
187
|
+
headers: d,
|
|
188
|
+
onFinished: p
|
|
163
189
|
};
|
|
164
|
-
|
|
190
|
+
i.set(r, u), this.workerByIdMap.set(r, u), this.enabledGroups.has(e) || this.enabledGroups.add(e), this.timer == null && this.enabledGroups.size > 0 && this.startTimer();
|
|
165
191
|
});
|
|
166
192
|
}
|
|
167
193
|
/** Trigger a worker to execute immediately, ignoring busy state */
|
|
168
194
|
triggerWorker(e) {
|
|
169
195
|
this.config.debug("*triggerWorker*");
|
|
170
|
-
const
|
|
171
|
-
|
|
196
|
+
const r = this.workerByIdMap.get(e);
|
|
197
|
+
r ? this.executeWorkerRequest(r, !0) : this.config.debug("*triggerWorker* worker not found", e);
|
|
172
198
|
}
|
|
173
199
|
/** Trigger all workers to execute immediately */
|
|
174
200
|
triggerAllWorkers() {
|
|
@@ -187,10 +213,10 @@ class I {
|
|
|
187
213
|
this.config.debug("*destroy*"), this.groups.clear(), this.stopTimer();
|
|
188
214
|
}
|
|
189
215
|
}
|
|
190
|
-
function
|
|
191
|
-
return new
|
|
216
|
+
function B(s) {
|
|
217
|
+
return new E(s);
|
|
192
218
|
}
|
|
193
219
|
export {
|
|
194
|
-
|
|
195
|
-
|
|
220
|
+
E as HangfirePoller,
|
|
221
|
+
B as default
|
|
196
222
|
};
|