@flowcore/data-pump 0.21.3 → 0.21.4
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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.21.4](https://github.com/flowcore-io/data-pump/compare/v0.21.3...v0.21.4) (2026-06-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **notifier:** arm timeout/abort before connect() to prevent hung-reconnect wedge ([#78](https://github.com/flowcore-io/data-pump/issues/78)) ([0fe4bbb](https://github.com/flowcore-io/data-pump/commit/0fe4bbbbda38ff58804403765832f41d2950a6df))
|
|
9
|
+
|
|
3
10
|
## [0.21.3](https://github.com/flowcore-io/data-pump/compare/v0.21.2...v0.21.3) (2026-06-02)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,+CAA+C,CAAA;AAG1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAetD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAoCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;
|
|
1
|
+
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,+CAA+C,CAAA;AAG1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAetD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAoCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAyD3B,OAAO,CAAC,aAAa;CAiBtB;AAqBD;;;;;GAKG;AAEH,KAAK,yBAAyB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,kBAAkB,CAAA;AACvE,eAAO,MAAM,UAAU,EAAE;IAAE,wBAAwB,EAAE,yBAAyB,CAAA;CAG7E,CAAA"}
|
|
@@ -124,6 +124,15 @@ export class FlowcoreNotifier {
|
|
|
124
124
|
this.eventResolver?.();
|
|
125
125
|
},
|
|
126
126
|
});
|
|
127
|
+
// Arm the timeout + abort listener BEFORE connect(). A reconnect whose
|
|
128
|
+
// connect() never resolves (half-open / black-holed socket) must not wedge
|
|
129
|
+
// the pump: the timer then resolves the wait at timeoutMs and the fetch loop
|
|
130
|
+
// re-polls (catching up any backlog) and attempts a fresh connect next cycle.
|
|
131
|
+
// The moment a connect() succeeds, that cycle waits on real WS events again —
|
|
132
|
+
// there is no sticky poll-mode state, so recovery to push mode is automatic.
|
|
133
|
+
clearTimeout(this.timer);
|
|
134
|
+
this.timer = setTimeout(() => this.eventResolver?.(), this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
135
|
+
signal?.addEventListener("abort", () => this.eventResolver?.());
|
|
127
136
|
this.notificationClient = _internals.createNotificationClient(this.subject, this.webSocketAuth(), {
|
|
128
137
|
tenant: this.dataSource.tenant,
|
|
129
138
|
dataCore: this.dataSource.dataCore,
|
|
@@ -132,14 +141,18 @@ export class FlowcoreNotifier {
|
|
|
132
141
|
logger: createNotificationClientLogger(this.options.logger ?? noOpLogger),
|
|
133
142
|
reconnectInterval: 1000,
|
|
134
143
|
});
|
|
144
|
+
const connectPromise = this.notificationClient.connect();
|
|
135
145
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
// Race connect() against the resolution promise so a hung connect can't
|
|
147
|
+
// block. A connect REJECTION still surfaces (preserving the main-loop
|
|
148
|
+
// self-heal that restarts on a thrown error).
|
|
149
|
+
await Promise.race([connectPromise, promise]);
|
|
140
150
|
await promise;
|
|
141
151
|
}
|
|
142
152
|
finally {
|
|
153
|
+
// Swallow a late connect() rejection that may arrive after we already
|
|
154
|
+
// moved on via the timeout, so it never surfaces as an unhandledRejection.
|
|
155
|
+
connectPromise.catch(() => { });
|
|
143
156
|
clearTimeout(this.timer);
|
|
144
157
|
this.eventResolver = undefined;
|
|
145
158
|
this.notificationClient.disconnect();
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,+CAA+C,CAAA;AAG1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAetD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAoCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;
|
|
1
|
+
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/data-pump/notifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA0B,MAAM,+CAA+C,CAAA;AAG1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKlG,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAA;IACtC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,WAAW,CAAC,CAAuB;IAC3C,OAAO,CAAC,OAAO,CAAC,CAA4B;IAC5C,OAAO,CAAC,kBAAkB,CAAC,CAAoB;IAC/C,OAAO,CAAC,aAAa,CAAC,CAAY;IAElC,OAAO,CAAC,KAAK,CAAC,CAAK;gBAEU,OAAO,EAAE,uBAAuB;IAetD,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW;YASlB,UAAU;YAUV,QAAQ;IAoCtB,OAAO,CAAC,gBAAgB;YAMV,aAAa;IAyD3B,OAAO,CAAC,aAAa;CAiBtB;AAqBD;;;;;GAKG;AAEH,KAAK,yBAAyB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,kBAAkB,CAAA;AACvE,eAAO,MAAM,UAAU,EAAE;IAAE,wBAAwB,EAAE,yBAAyB,CAAA;CAG7E,CAAA"}
|
|
@@ -127,6 +127,15 @@ class FlowcoreNotifier {
|
|
|
127
127
|
this.eventResolver?.();
|
|
128
128
|
},
|
|
129
129
|
});
|
|
130
|
+
// Arm the timeout + abort listener BEFORE connect(). A reconnect whose
|
|
131
|
+
// connect() never resolves (half-open / black-holed socket) must not wedge
|
|
132
|
+
// the pump: the timer then resolves the wait at timeoutMs and the fetch loop
|
|
133
|
+
// re-polls (catching up any backlog) and attempts a fresh connect next cycle.
|
|
134
|
+
// The moment a connect() succeeds, that cycle waits on real WS events again —
|
|
135
|
+
// there is no sticky poll-mode state, so recovery to push mode is automatic.
|
|
136
|
+
clearTimeout(this.timer);
|
|
137
|
+
this.timer = setTimeout(() => this.eventResolver?.(), this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
138
|
+
signal?.addEventListener("abort", () => this.eventResolver?.());
|
|
130
139
|
this.notificationClient = exports._internals.createNotificationClient(this.subject, this.webSocketAuth(), {
|
|
131
140
|
tenant: this.dataSource.tenant,
|
|
132
141
|
dataCore: this.dataSource.dataCore,
|
|
@@ -135,14 +144,18 @@ class FlowcoreNotifier {
|
|
|
135
144
|
logger: createNotificationClientLogger(this.options.logger ?? no_op_logger_js_1.noOpLogger),
|
|
136
145
|
reconnectInterval: 1000,
|
|
137
146
|
});
|
|
147
|
+
const connectPromise = this.notificationClient.connect();
|
|
138
148
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
// Race connect() against the resolution promise so a hung connect can't
|
|
150
|
+
// block. A connect REJECTION still surfaces (preserving the main-loop
|
|
151
|
+
// self-heal that restarts on a thrown error).
|
|
152
|
+
await Promise.race([connectPromise, promise]);
|
|
143
153
|
await promise;
|
|
144
154
|
}
|
|
145
155
|
finally {
|
|
156
|
+
// Swallow a late connect() rejection that may arrive after we already
|
|
157
|
+
// moved on via the timeout, so it never surfaces as an unhandledRejection.
|
|
158
|
+
connectPromise.catch(() => { });
|
|
146
159
|
clearTimeout(this.timer);
|
|
147
160
|
this.eventResolver = undefined;
|
|
148
161
|
this.notificationClient.disconnect();
|