@homebridge-plugins/homebridge-august 3.2.2 → 3.3.0-beta.0
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/.github/copilot-instructions.md +200 -0
- package/.github/npm-version-script-esm.js +97 -0
- package/CHANGELOG.md +44 -9
- package/dist/Platform.Base.d.ts +288 -0
- package/dist/Platform.Base.d.ts.map +1 -0
- package/dist/Platform.Base.js +797 -0
- package/dist/Platform.Base.js.map +1 -0
- package/dist/Platform.HAP.d.ts +27 -0
- package/dist/Platform.HAP.d.ts.map +1 -0
- package/dist/Platform.HAP.js +68 -0
- package/dist/Platform.HAP.js.map +1 -0
- package/dist/connectivity-manager.d.ts +3 -3
- package/dist/connectivity-manager.d.ts.map +1 -1
- package/dist/connectivity-manager.js +57 -14
- package/dist/connectivity-manager.js.map +1 -1
- package/dist/devices/device.d.ts +5 -16
- package/dist/devices/device.d.ts.map +1 -1
- package/dist/devices/device.js +18 -75
- package/dist/devices/device.js.map +1 -1
- package/dist/devices/lock.d.ts +3 -3
- package/dist/devices/lock.d.ts.map +1 -1
- package/dist/devices/lock.js +41 -41
- package/dist/devices/lock.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/package.json +10 -8
- package/dist/platform.matter.d.ts +18 -20
- package/dist/platform.matter.d.ts.map +1 -1
- package/dist/platform.matter.js +74 -80
- package/dist/platform.matter.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +10 -8
- package/test/device.test.ts +384 -0
- package/test/{platform.test.ts → platform.hap.test.ts} +23 -23
- package/test/platform.polling.test.ts +5 -5
- package/.copilot/instructions.md +0 -261
- package/.github/scripts/compute-version-override.cjs +0 -51
- package/.github/scripts/normalize-changelog-header.cjs +0 -86
- package/.github/scripts/npm-version-script-esm-auto.js +0 -201
- package/.github/scripts/resolve-version-bump-esm.js +0 -118
- package/dist/platform.d.ts +0 -146
- package/dist/platform.d.ts.map +0 -1
- package/dist/platform.js +0 -755
- package/dist/platform.js.map +0 -1
- package/test/connectivity-manager.test.ts +0 -590
- package/test/platform.matter.test.ts +0 -660
package/dist/platform.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,590 +0,0 @@
|
|
|
1
|
-
/* Copyright(C) 2026, homebridge-plugins (https://github.com/homebridge-plugins). All rights reserved.
|
|
2
|
-
*
|
|
3
|
-
* connectivity-manager.test.ts: unit tests for ConnectivityManager.
|
|
4
|
-
*
|
|
5
|
-
* The manager is the centerpiece of the connectivity refactor and the
|
|
6
|
-
* piece most likely to regress under future changes (state machine,
|
|
7
|
-
* timer-driven probes, async rebuild coalescing). These tests cover
|
|
8
|
-
* the contract that the rest of the codebase relies on.
|
|
9
|
-
*/
|
|
10
|
-
import type { Logging } from 'homebridge'
|
|
11
|
-
|
|
12
|
-
import type { credentials } from '../src/settings.js'
|
|
13
|
-
|
|
14
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
15
|
-
|
|
16
|
-
import { ConnectivityManager, OfflineError } from '../src/connectivity-manager.js'
|
|
17
|
-
|
|
18
|
-
// Mock the august-yale module. We need:
|
|
19
|
-
// - August: a constructor we can instantiate, with details() and destroy()
|
|
20
|
-
// - The full exception hierarchy that classify() now uses for routing:
|
|
21
|
-
// NetworkError, TimeoutError (subclass), AbortedError, InvalidAuth.
|
|
22
|
-
vi.mock('august-yale', () => {
|
|
23
|
-
class YaleApiError extends Error {
|
|
24
|
-
public originalError?: Error
|
|
25
|
-
constructor(message?: string, originalError?: Error) {
|
|
26
|
-
super(message)
|
|
27
|
-
this.name = 'YaleApiError'
|
|
28
|
-
this.originalError = originalError
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
class NetworkError extends YaleApiError {
|
|
32
|
-
public code?: string
|
|
33
|
-
constructor(message?: string, originalError?: Error, code?: string) {
|
|
34
|
-
super(message, originalError)
|
|
35
|
-
this.name = 'NetworkError'
|
|
36
|
-
this.code = code
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
class TimeoutError extends NetworkError {
|
|
40
|
-
constructor(message?: string, originalError?: Error, code?: string) {
|
|
41
|
-
super(message, originalError, code)
|
|
42
|
-
this.name = 'TimeoutError'
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
class AbortedError extends YaleApiError {
|
|
46
|
-
public code?: string
|
|
47
|
-
constructor(message?: string, originalError?: Error, code?: string) {
|
|
48
|
-
super(message, originalError)
|
|
49
|
-
this.name = 'AbortedError'
|
|
50
|
-
this.code = code
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
class InvalidAuth extends YaleApiError {
|
|
54
|
-
constructor(message?: string, originalError?: Error) {
|
|
55
|
-
super(message, originalError)
|
|
56
|
-
this.name = 'InvalidAuth'
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// Each new August() returns a unique object so tests can assert which
|
|
60
|
-
// client is being used (initial vs. rebuilt). Tests can also override
|
|
61
|
-
// the methods of the NEXT client to be built by setting fields on
|
|
62
|
-
// `nextClientOverride`. After one use the override is cleared.
|
|
63
|
-
let nextId = 0
|
|
64
|
-
// eslint-disable-next-line prefer-arrow-callback
|
|
65
|
-
const MockAugust = vi.fn().mockImplementation(function () {
|
|
66
|
-
const id = ++nextId
|
|
67
|
-
return {
|
|
68
|
-
_id: id,
|
|
69
|
-
details: vi.fn().mockResolvedValue({ ok: true }),
|
|
70
|
-
locks: vi.fn().mockResolvedValue({}),
|
|
71
|
-
lock: vi.fn().mockResolvedValue(undefined),
|
|
72
|
-
unlock: vi.fn().mockResolvedValue(undefined),
|
|
73
|
-
destroy: vi.fn(),
|
|
74
|
-
resetTransport: vi.fn(),
|
|
75
|
-
end: vi.fn(),
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
return {
|
|
79
|
-
default: MockAugust,
|
|
80
|
-
YaleApiError,
|
|
81
|
-
NetworkError,
|
|
82
|
-
TimeoutError,
|
|
83
|
-
AbortedError,
|
|
84
|
-
InvalidAuth,
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// Helper: build a stub Logging object that records calls.
|
|
89
|
-
function makeLog(): Logging & { _calls: { level: string, msg: string }[] } {
|
|
90
|
-
const calls: { level: string, msg: string }[] = []
|
|
91
|
-
const stub = ((..._args: any[]) => {}) as any
|
|
92
|
-
stub._calls = calls
|
|
93
|
-
for (const level of ['info', 'warn', 'error', 'debug', 'success'] as const) {
|
|
94
|
-
stub[level] = (msg: string) => calls.push({ level, msg })
|
|
95
|
-
}
|
|
96
|
-
return stub
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Helper: trivial credentials factory.
|
|
100
|
-
async function fakeCredentials(): Promise<credentials> {
|
|
101
|
-
return { installId: 'test-install', apiKey: 'test-key' } as unknown as credentials
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
describe('ConnectivityManager', () => {
|
|
105
|
-
beforeEach(() => {
|
|
106
|
-
// Use fake timers so probes can be advanced deterministically without
|
|
107
|
-
// waiting for real backoff windows (5s..5min).
|
|
108
|
-
vi.useFakeTimers()
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
afterEach(() => {
|
|
112
|
-
vi.useRealTimers()
|
|
113
|
-
vi.clearAllMocks()
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
describe('init / lifecycle', () => {
|
|
117
|
-
it('init() builds a client and fires onClientChanged exactly once', async () => {
|
|
118
|
-
const onClientChanged = vi.fn()
|
|
119
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
120
|
-
await m.init()
|
|
121
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
122
|
-
// The current client is whatever was passed to onClientChanged.
|
|
123
|
-
expect(m.getClient()).toBe(onClientChanged.mock.calls[0][0])
|
|
124
|
-
expect(m.getState()).toBe('healthy')
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('init() is idempotent — calling twice does not rebuild', async () => {
|
|
128
|
-
const onClientChanged = vi.fn()
|
|
129
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
130
|
-
await m.init()
|
|
131
|
-
await m.init()
|
|
132
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('shutdown() destroys the client, clears state, fires onClientChanged(undefined)', async () => {
|
|
136
|
-
const onClientChanged = vi.fn()
|
|
137
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
138
|
-
await m.init()
|
|
139
|
-
const client = m.getClient() as any
|
|
140
|
-
m.shutdown()
|
|
141
|
-
expect(client.destroy).toHaveBeenCalledTimes(1)
|
|
142
|
-
expect(m.getClient()).toBeUndefined()
|
|
143
|
-
// Last call to onClientChanged was with undefined.
|
|
144
|
-
const lastCall = onClientChanged.mock.calls.at(-1)
|
|
145
|
-
expect(lastCall?.[0]).toBeUndefined()
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
describe('execute() — happy path and routing', () => {
|
|
150
|
-
it('returns the result and stays healthy on success', async () => {
|
|
151
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
152
|
-
await m.init()
|
|
153
|
-
const result = await m.execute('test', async client => (client as any).details('lock-1'))
|
|
154
|
-
expect(result).toEqual({ ok: true })
|
|
155
|
-
expect(m.getState()).toBe('healthy')
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
it('returns undefined and does not invoke fn when offline', async () => {
|
|
159
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
160
|
-
await m.init()
|
|
161
|
-
;(m as any).state = 'offline' // force state for this case
|
|
162
|
-
const fn = vi.fn()
|
|
163
|
-
const result = await m.execute('test', fn)
|
|
164
|
-
expect(result).toBeUndefined()
|
|
165
|
-
expect(fn).not.toHaveBeenCalled()
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
it('throws OfflineError when offline and throwOnOffline:true', async () => {
|
|
169
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
170
|
-
await m.init()
|
|
171
|
-
;(m as any).state = 'offline'
|
|
172
|
-
await expect(
|
|
173
|
-
m.execute('user-action', async () => 'ok', { throwOnOffline: true }),
|
|
174
|
-
).rejects.toBeInstanceOf(OfflineError)
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('returns undefined when init() has not been called', async () => {
|
|
178
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
179
|
-
const result = await m.execute('test', async () => 'never-called')
|
|
180
|
-
expect(result).toBeUndefined()
|
|
181
|
-
})
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
describe('execute() — error classification', () => {
|
|
185
|
-
it('rethrows transient (4xx like 422) errors without changing state', async () => {
|
|
186
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
187
|
-
await m.init()
|
|
188
|
-
const transientErr = Object.assign(new Error('Unprocessable Entity'), { statusCode: 422 })
|
|
189
|
-
await expect(
|
|
190
|
-
m.execute('test', async () => { throw transientErr }),
|
|
191
|
-
).rejects.toBe(transientErr)
|
|
192
|
-
expect(m.getState()).toBe('healthy')
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('rethrows transient errors even with throwOnOffline:true', async () => {
|
|
196
|
-
// throwOnOffline only governs the offline branch; transient errors
|
|
197
|
-
// are always rethrown regardless of that option.
|
|
198
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
199
|
-
await m.init()
|
|
200
|
-
const err = Object.assign(new Error('rate limited'), { statusCode: 429 })
|
|
201
|
-
await expect(
|
|
202
|
-
m.execute('user', async () => { throw err }, { throwOnOffline: true }),
|
|
203
|
-
).rejects.toBe(err)
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
it('rebuilds the client on 401 without changing connectivity state', async () => {
|
|
207
|
-
const onClientChanged = vi.fn()
|
|
208
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
209
|
-
await m.init()
|
|
210
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
211
|
-
const authErr = Object.assign(new Error('Unauthorized'), { statusCode: 401 })
|
|
212
|
-
const result = await m.execute('test', async () => { throw authErr })
|
|
213
|
-
expect(result).toBeUndefined()
|
|
214
|
-
// Allow the rebuild promise to resolve.
|
|
215
|
-
await vi.runAllTimersAsync()
|
|
216
|
-
expect(onClientChanged).toHaveBeenCalledTimes(2)
|
|
217
|
-
expect(m.getState()).toBe('healthy')
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
it('treats TimeoutError as network and transitions to degraded', async () => {
|
|
221
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
222
|
-
await m.init()
|
|
223
|
-
const { TimeoutError } = await import('august-yale')
|
|
224
|
-
const result = await m.execute('test', async () => { throw new TimeoutError('timed out') })
|
|
225
|
-
expect(result).toBeUndefined()
|
|
226
|
-
expect(m.getState()).toBe('degraded')
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
it('treats NetworkError as network and transitions to degraded', async () => {
|
|
230
|
-
// NetworkError covers all transport-level failures from august-yale —
|
|
231
|
-
// socket reset, DNS failure, malformed response, etc. — without us
|
|
232
|
-
// having to enumerate undici's 24 error classes.
|
|
233
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
234
|
-
await m.init()
|
|
235
|
-
const { NetworkError } = await import('august-yale')
|
|
236
|
-
const result = await m.execute('test', async () => { throw new NetworkError('socket hang up', undefined, 'ECONNRESET') })
|
|
237
|
-
expect(result).toBeUndefined()
|
|
238
|
-
expect(m.getState()).toBe('degraded')
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
it('treats InvalidAuth as auth and rebuilds without changing state', async () => {
|
|
242
|
-
const onClientChanged = vi.fn()
|
|
243
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
244
|
-
await m.init()
|
|
245
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
246
|
-
const { InvalidAuth } = await import('august-yale')
|
|
247
|
-
const result = await m.execute('test', async () => { throw new InvalidAuth('session expired') })
|
|
248
|
-
expect(result).toBeUndefined()
|
|
249
|
-
await vi.runAllTimersAsync()
|
|
250
|
-
expect(onClientChanged).toHaveBeenCalledTimes(2)
|
|
251
|
-
expect(m.getState()).toBe('healthy')
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
it('treats AbortedError as transient and does NOT change connectivity state', async () => {
|
|
255
|
-
// AbortedError reflects a request racing with our own teardown
|
|
256
|
-
// (e.g. inside rebuildClient). Treating it as 'network' would
|
|
257
|
-
// make the state machine fight itself: every rebuild produces
|
|
258
|
-
// ClientDestroyedError -> degraded -> probe -> rebuild ->
|
|
259
|
-
// ClientDestroyedError -> ...
|
|
260
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
261
|
-
await m.init()
|
|
262
|
-
const { AbortedError } = await import('august-yale')
|
|
263
|
-
const err = new AbortedError('client destroyed', undefined, 'UND_ERR_DESTROYED')
|
|
264
|
-
await expect(
|
|
265
|
-
m.execute('test', async () => { throw err }),
|
|
266
|
-
).rejects.toBe(err)
|
|
267
|
-
// State stays healthy — no probe scheduled.
|
|
268
|
-
expect(m.getState()).toBe('healthy')
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
it('treats 502/503/504 as network errors (HTTP-level fallback)', async () => {
|
|
272
|
-
// Most transport failures are now wrapped upstream as NetworkError,
|
|
273
|
-
// but if august-yale ever surfaces a clean HTTP 5xx response, we
|
|
274
|
-
// still want to recognize 502/503/504 as network-class and probe.
|
|
275
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
276
|
-
await m.init()
|
|
277
|
-
const err = Object.assign(new Error('Bad Gateway'), { statusCode: 502 })
|
|
278
|
-
await m.execute('test', async () => { throw err })
|
|
279
|
-
expect(m.getState()).toBe('degraded')
|
|
280
|
-
})
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
describe('probe-driven recovery', () => {
|
|
284
|
-
it('schedules a probe on first network failure and recovers when probe succeeds', async () => {
|
|
285
|
-
const onClientChanged = vi.fn()
|
|
286
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
287
|
-
await m.init()
|
|
288
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
289
|
-
|
|
290
|
-
// Network failure: degrades and schedules probe.
|
|
291
|
-
const { TimeoutError } = await import('august-yale')
|
|
292
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
293
|
-
expect(m.getState()).toBe('degraded')
|
|
294
|
-
|
|
295
|
-
// Probe calls resetTransport() on the existing client and then its
|
|
296
|
-
// .locks(). Default mock = locks resolves, so probe succeeds.
|
|
297
|
-
|
|
298
|
-
// Advance time past the first backoff slot (~5s plus jitter).
|
|
299
|
-
await vi.advanceTimersByTimeAsync(7_000)
|
|
300
|
-
|
|
301
|
-
// Probe success → healthy. onClientChanged was called only once
|
|
302
|
-
// (at init). The resetTransport-based design does NOT swap the
|
|
303
|
-
// client instance on recovery; it just recycles its transport.
|
|
304
|
-
expect(m.getState()).toBe('healthy')
|
|
305
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
it('escalates from degraded to offline when probe fails, with longer backoff', async () => {
|
|
309
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
310
|
-
await m.init()
|
|
311
|
-
const client = m.getClient() as any
|
|
312
|
-
|
|
313
|
-
const { TimeoutError } = await import('august-yale')
|
|
314
|
-
|
|
315
|
-
// Make the existing client's .locks() always fail. With the
|
|
316
|
-
// resetTransport-based design, probes reuse this client, so a
|
|
317
|
-
// single mockImplementation is sufficient for every probe attempt.
|
|
318
|
-
client.locks = vi.fn().mockImplementation(() => new Promise((_resolve, reject) => {
|
|
319
|
-
setTimeout(() => reject(new TimeoutError('still down')), 100)
|
|
320
|
-
}))
|
|
321
|
-
|
|
322
|
-
// Trigger degraded.
|
|
323
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
324
|
-
expect(m.getState()).toBe('degraded')
|
|
325
|
-
|
|
326
|
-
// Advance past first backoff + probe timeout.
|
|
327
|
-
await vi.advanceTimersByTimeAsync(15_000)
|
|
328
|
-
expect(m.getState()).toBe('offline')
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
it('execute() after entering offline returns undefined without calling fn', async () => {
|
|
332
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
333
|
-
await m.init()
|
|
334
|
-
;(m as any).state = 'offline'
|
|
335
|
-
const fn = vi.fn()
|
|
336
|
-
const result = await m.execute('test', fn)
|
|
337
|
-
expect(result).toBeUndefined()
|
|
338
|
-
expect(fn).not.toHaveBeenCalled()
|
|
339
|
-
})
|
|
340
|
-
|
|
341
|
-
it('successful execute() call recovers state from degraded to healthy', async () => {
|
|
342
|
-
// This case covers the natural-recovery path: a network blip that
|
|
343
|
-
// resolves before the probe fires. The next real execute() call
|
|
344
|
-
// succeeds and the manager reports healthy.
|
|
345
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
346
|
-
await m.init()
|
|
347
|
-
const { TimeoutError } = await import('august-yale')
|
|
348
|
-
await m.execute('test', async () => { throw new TimeoutError('blip') })
|
|
349
|
-
expect(m.getState()).toBe('degraded')
|
|
350
|
-
// Next call succeeds.
|
|
351
|
-
const result = await m.execute('test', async () => 'recovered')
|
|
352
|
-
expect(result).toBe('recovered')
|
|
353
|
-
expect(m.getState()).toBe('healthy')
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
it('probes call resetTransport() on the existing client (sheds stale sockets)', async () => {
|
|
357
|
-
// Regression test for the production bug: the original
|
|
358
|
-
// implementation probed against the existing client without
|
|
359
|
-
// resetting its socket pool. The pool kept stale half-open sockets
|
|
360
|
-
// from before the outage, probes failed on those sockets, system
|
|
361
|
-
// stayed offline.
|
|
362
|
-
//
|
|
363
|
-
// The fix: probe still uses the existing client (so we keep auth
|
|
364
|
-
// state), but resetTransport() is called first to throw away the
|
|
365
|
-
// dispatcher and its stale connections. New transport, same auth.
|
|
366
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
367
|
-
await m.init()
|
|
368
|
-
const client = m.getClient() as any
|
|
369
|
-
|
|
370
|
-
// Sanity: the mock client has a resetTransport method.
|
|
371
|
-
expect(typeof client.resetTransport).toBe('function')
|
|
372
|
-
|
|
373
|
-
// Trigger degraded.
|
|
374
|
-
const { TimeoutError } = await import('august-yale')
|
|
375
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
376
|
-
expect(m.getState()).toBe('degraded')
|
|
377
|
-
|
|
378
|
-
// Advance past the first backoff: probe runs, default mock has
|
|
379
|
-
// .locks() resolving, recovery completes.
|
|
380
|
-
await vi.advanceTimersByTimeAsync(7_000)
|
|
381
|
-
expect(m.getState()).toBe('healthy')
|
|
382
|
-
|
|
383
|
-
// The probe must have called resetTransport on the existing
|
|
384
|
-
// client. This is the structural assertion that locks in the fix.
|
|
385
|
-
expect(client.resetTransport).toHaveBeenCalled()
|
|
386
|
-
// The same client instance is still in place (we did NOT
|
|
387
|
-
// construct a new client — this distinguishes the resetTransport
|
|
388
|
-
// approach from the previous fresh-client approach).
|
|
389
|
-
expect(m.getClient()).toBe(client)
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
it('failed probe leaves the existing client in place (no leak, no rotation)', async () => {
|
|
393
|
-
// With resetTransport(), failed probes don't construct a temp
|
|
394
|
-
// client, so there's nothing to leak. The existing client stays
|
|
395
|
-
// the current client throughout the offline period — only its
|
|
396
|
-
// transport gets recycled, not the August instance itself.
|
|
397
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
398
|
-
await m.init()
|
|
399
|
-
const client = m.getClient() as any
|
|
400
|
-
|
|
401
|
-
const { TimeoutError } = await import('august-yale')
|
|
402
|
-
|
|
403
|
-
// Make the client's .locks() always fail.
|
|
404
|
-
client.locks = vi.fn().mockImplementation(() => new Promise((_, reject) =>
|
|
405
|
-
setTimeout(() => reject(new TimeoutError('still down')), 100),
|
|
406
|
-
))
|
|
407
|
-
|
|
408
|
-
// Trigger degraded.
|
|
409
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
410
|
-
expect(m.getState()).toBe('degraded')
|
|
411
|
-
|
|
412
|
-
// Advance past first probe → offline.
|
|
413
|
-
await vi.advanceTimersByTimeAsync(15_000)
|
|
414
|
-
expect(m.getState()).toBe('offline')
|
|
415
|
-
|
|
416
|
-
// The existing client is still the current client; nothing got
|
|
417
|
-
// destroyed or replaced.
|
|
418
|
-
expect(m.getClient()).toBe(client)
|
|
419
|
-
expect(client.destroy).not.toHaveBeenCalled()
|
|
420
|
-
// resetTransport was called for each probe attempt.
|
|
421
|
-
expect(client.resetTransport).toHaveBeenCalled()
|
|
422
|
-
})
|
|
423
|
-
})
|
|
424
|
-
|
|
425
|
-
describe('onPubNubReconnect — fast recovery', () => {
|
|
426
|
-
it('triggers an immediate probe when degraded', async () => {
|
|
427
|
-
const onClientChanged = vi.fn()
|
|
428
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
429
|
-
await m.init()
|
|
430
|
-
|
|
431
|
-
const { TimeoutError } = await import('august-yale')
|
|
432
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
433
|
-
expect(m.getState()).toBe('degraded')
|
|
434
|
-
|
|
435
|
-
// PubNub reconnect → immediate probe. Default mock has .locks()
|
|
436
|
-
// resolving, so the probe (which calls resetTransport on the
|
|
437
|
-
// existing client and then locks()) succeeds.
|
|
438
|
-
m.onPubNubReconnect()
|
|
439
|
-
|
|
440
|
-
// Probe runs synchronously inside onPubNubReconnect's microtask;
|
|
441
|
-
// need to flush promises but no timer advance required.
|
|
442
|
-
await vi.runAllTimersAsync()
|
|
443
|
-
expect(m.getState()).toBe('healthy')
|
|
444
|
-
// onClientChanged was only called once (at init). Recovery via
|
|
445
|
-
// resetTransport does not swap the client instance.
|
|
446
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
it('is a no-op when already healthy', async () => {
|
|
450
|
-
const onClientChanged = vi.fn()
|
|
451
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
452
|
-
await m.init()
|
|
453
|
-
const callsAfterInit = onClientChanged.mock.calls.length
|
|
454
|
-
m.onPubNubReconnect()
|
|
455
|
-
await vi.runAllTimersAsync()
|
|
456
|
-
// No probe, no rebuild.
|
|
457
|
-
expect(onClientChanged).toHaveBeenCalledTimes(callsAfterInit)
|
|
458
|
-
expect(m.getState()).toBe('healthy')
|
|
459
|
-
})
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
describe('rebuild coalescing', () => {
|
|
463
|
-
it('two concurrent 401s produce one rebuild, not two', async () => {
|
|
464
|
-
const onClientChanged = vi.fn()
|
|
465
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials, onClientChanged)
|
|
466
|
-
await m.init()
|
|
467
|
-
expect(onClientChanged).toHaveBeenCalledTimes(1)
|
|
468
|
-
|
|
469
|
-
const authErr = Object.assign(new Error('Unauthorized'), { statusCode: 401 })
|
|
470
|
-
|
|
471
|
-
// Fire two execute()s concurrently — each will see a 401, each will
|
|
472
|
-
// request a rebuild. The manager must coalesce these into one rebuild.
|
|
473
|
-
await Promise.all([
|
|
474
|
-
m.execute('a', async () => { throw authErr }),
|
|
475
|
-
m.execute('b', async () => { throw authErr }),
|
|
476
|
-
])
|
|
477
|
-
await vi.runAllTimersAsync()
|
|
478
|
-
|
|
479
|
-
// Initial build + exactly one rebuild = 2 total.
|
|
480
|
-
expect(onClientChanged).toHaveBeenCalledTimes(2)
|
|
481
|
-
})
|
|
482
|
-
})
|
|
483
|
-
|
|
484
|
-
describe('state-change listeners', () => {
|
|
485
|
-
it('onStateChange fires on transitions and not on no-op transitions', async () => {
|
|
486
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
487
|
-
await m.init()
|
|
488
|
-
const listener = vi.fn()
|
|
489
|
-
m.onStateChange(listener)
|
|
490
|
-
|
|
491
|
-
const { TimeoutError } = await import('august-yale')
|
|
492
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
493
|
-
// healthy -> degraded fires once.
|
|
494
|
-
expect(listener).toHaveBeenCalledWith('degraded', 'healthy')
|
|
495
|
-
expect(listener).toHaveBeenCalledTimes(1)
|
|
496
|
-
|
|
497
|
-
// A second network error while already degraded should NOT fire
|
|
498
|
-
// again (no transition).
|
|
499
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
500
|
-
expect(listener).toHaveBeenCalledTimes(1)
|
|
501
|
-
})
|
|
502
|
-
|
|
503
|
-
it('unsubscribe stops further notifications', async () => {
|
|
504
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
505
|
-
await m.init()
|
|
506
|
-
const listener = vi.fn()
|
|
507
|
-
const unsubscribe = m.onStateChange(listener)
|
|
508
|
-
unsubscribe()
|
|
509
|
-
|
|
510
|
-
const { TimeoutError } = await import('august-yale')
|
|
511
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
512
|
-
expect(listener).not.toHaveBeenCalled()
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
it('a throwing listener does not block other listeners', async () => {
|
|
516
|
-
const m = new ConnectivityManager(makeLog(), fakeCredentials)
|
|
517
|
-
await m.init()
|
|
518
|
-
const good = vi.fn()
|
|
519
|
-
m.onStateChange(() => { throw new Error('listener bug') })
|
|
520
|
-
m.onStateChange(good)
|
|
521
|
-
|
|
522
|
-
const { TimeoutError } = await import('august-yale')
|
|
523
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
524
|
-
expect(good).toHaveBeenCalledTimes(1)
|
|
525
|
-
})
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
describe('offline heartbeat', () => {
|
|
529
|
-
// Helper: drive the manager into offline state and capture the log.
|
|
530
|
-
async function getOfflineWithLog() {
|
|
531
|
-
const log = makeLog()
|
|
532
|
-
const m = new ConnectivityManager(log, fakeCredentials)
|
|
533
|
-
await m.init()
|
|
534
|
-
const client = m.getClient() as any
|
|
535
|
-
|
|
536
|
-
const { TimeoutError } = await import('august-yale')
|
|
537
|
-
|
|
538
|
-
// Make every probe fail by making the existing client's .locks
|
|
539
|
-
// always reject. With the resetTransport-based design, probes
|
|
540
|
-
// reuse this client across attempts, so a single mockImplementation
|
|
541
|
-
// covers every probe in the offline period.
|
|
542
|
-
client.locks = vi.fn().mockImplementation(() => new Promise((_resolve, reject) =>
|
|
543
|
-
setTimeout(() => reject(new TimeoutError('still down')), 100),
|
|
544
|
-
))
|
|
545
|
-
|
|
546
|
-
// Trigger degraded.
|
|
547
|
-
await m.execute('test', async () => { throw new TimeoutError('boom') })
|
|
548
|
-
|
|
549
|
-
// Drive past first probe so we land in offline.
|
|
550
|
-
await vi.advanceTimersByTimeAsync(15_000)
|
|
551
|
-
return { m, log, client }
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
it('emits a heartbeat after one hour of being offline', async () => {
|
|
555
|
-
const { log } = await getOfflineWithLog()
|
|
556
|
-
|
|
557
|
-
// Less than an hour: no heartbeat yet.
|
|
558
|
-
await vi.advanceTimersByTimeAsync(30 * 60_000)
|
|
559
|
-
const beforeHour = log._calls.filter(c => c.msg.includes('still offline')).length
|
|
560
|
-
expect(beforeHour).toBe(0)
|
|
561
|
-
|
|
562
|
-
// Past one hour: heartbeat fires. Probes are still failing in the
|
|
563
|
-
// background, so we filter for the heartbeat-specific message.
|
|
564
|
-
await vi.advanceTimersByTimeAsync(35 * 60_000)
|
|
565
|
-
const afterHour = log._calls.filter(c => c.msg.includes('still offline')).length
|
|
566
|
-
expect(afterHour).toBeGreaterThan(0)
|
|
567
|
-
// Heartbeat content includes attempt count and last failure.
|
|
568
|
-
const heartbeatLine = log._calls.find(c => c.msg.includes('still offline'))
|
|
569
|
-
expect(heartbeatLine?.msg).toMatch(/\d+ probe attempts?/)
|
|
570
|
-
expect(heartbeatLine?.msg).toContain('last failure')
|
|
571
|
-
})
|
|
572
|
-
|
|
573
|
-
it('stops emitting heartbeats after recovery', async () => {
|
|
574
|
-
const { m, log, client } = await getOfflineWithLog()
|
|
575
|
-
|
|
576
|
-
// Allow recovery on the next probe by making .locks resolve again.
|
|
577
|
-
client.locks = vi.fn().mockResolvedValue({})
|
|
578
|
-
|
|
579
|
-
// Skip ahead enough for a probe to fire and succeed.
|
|
580
|
-
await vi.advanceTimersByTimeAsync(60 * 1000)
|
|
581
|
-
expect(m.getState()).toBe('healthy')
|
|
582
|
-
|
|
583
|
-
const beforeIdle = log._calls.filter(c => c.msg.includes('still offline')).length
|
|
584
|
-
// Advance two more hours — should NOT see new heartbeat lines.
|
|
585
|
-
await vi.advanceTimersByTimeAsync(2 * 60 * 60_000)
|
|
586
|
-
const afterIdle = log._calls.filter(c => c.msg.includes('still offline')).length
|
|
587
|
-
expect(afterIdle).toBe(beforeIdle)
|
|
588
|
-
})
|
|
589
|
-
})
|
|
590
|
-
})
|