comq 0.15.5 → 0.15.6

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,3 +1,11 @@
1
+ ## [0.15.6](https://github.com/toa-io/comq/compare/v0.15.5...v0.15.6) (2026-08-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * do not report shards as lost on shutdown ([abbe0e8](https://github.com/toa-io/comq/commit/abbe0e8e1048509ff2c981b7aa33659c0829e821))
7
+ * do not report shards as lost on shutdown ([#248](https://github.com/toa-io/comq/issues/248)) ([b269a5c](https://github.com/toa-io/comq/commit/b269a5cc78d8ca74036290abec234a1e87056e9c))
8
+
1
9
  ## [0.15.5](https://github.com/toa-io/comq/compare/v0.15.4...v0.15.5) (2026-08-25)
2
10
 
3
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comq",
3
- "version": "0.15.5",
3
+ "version": "0.15.6",
4
4
  "description": "ComQ",
5
5
  "author": {
6
6
  "name": "Artem Gurtovoi",
@@ -60,6 +60,10 @@ class Connection {
60
60
  return this.#connection !== undefined
61
61
  }
62
62
 
63
+ get closed () {
64
+ return this.#closed
65
+ }
66
+
63
67
  async open () {
64
68
  this.#closed = false
65
69
 
@@ -111,6 +111,7 @@ class Channel {
111
111
  * when it actually fails to publish, otherwise a lost connection would
112
112
  * interrupt the streams it is carrying. Losing a shard is reported instead,
113
113
  * since a request awaiting its reply on it will never be answered.
114
+ * A connection closed on purpose is not a loss.
114
115
  *
115
116
  * @param {comq.Connection} connection
116
117
  * @param {number} index
@@ -121,10 +122,13 @@ class Channel {
121
122
 
122
123
  if (connection.connected === false) this.#down[index].resolve()
123
124
 
124
- connection.diagnose('close', () => {
125
+ connection.diagnose('close', (error) => {
125
126
  this.#alive[index] = false
126
127
  this.#down[index].resolve()
127
- this.#diagnostics.emit(LOST, index)
128
+
129
+ if (error !== undefined && connection.closed !== true) {
130
+ this.#diagnostics.emit(LOST, index)
131
+ }
128
132
  })
129
133
 
130
134
  connection.diagnose('open', () => {
@@ -20,6 +20,7 @@ const channel = /** @type {jest.MockedFunction<(sharded?: boolean, index?: numbe
20
20
  */
21
21
  const connection = (sharded = false) => (/** @type {jest.MockedObject<comq.Connection>} */ {
22
22
  connected: true,
23
+ closed: false,
23
24
  createChannel: jest.fn(async (type, index) => channel(sharded, index)),
24
25
  open: jest.fn(async () => undefined),
25
26
  close: jest.fn(async () => undefined),
@@ -402,6 +402,7 @@ describe('close', () => {
402
402
  const amqp = await amqplib.connect.mock.results[0].value
403
403
 
404
404
  expect(amqp.close).toHaveBeenCalled()
405
+ expect(connection.closed).toStrictEqual(true)
405
406
  })
406
407
 
407
408
  it('should close after connection is (re)established', async () => {
@@ -40,11 +40,45 @@ it('should report a lost shard', async () => {
40
40
 
41
41
  expect(calls.length).toBeGreaterThan(0)
42
42
 
43
- for (const call of calls) call[1]()
43
+ for (const call of calls) call[1](new Error('gone'))
44
44
 
45
45
  expect(lost).toHaveBeenCalledWith(1)
46
46
  })
47
47
 
48
+ it('should not report a lost shard when the connection is closed', async () => {
49
+ channel = await create(connections, type)
50
+
51
+ const lost = /** @type {jest.MockedFunction} */ jest.fn()
52
+
53
+ channel.diagnose('lost', lost)
54
+
55
+ connections[1].closed = true
56
+
57
+ const calls = connections[1].diagnose.mock.calls.filter((call) => call[0] === 'close')
58
+
59
+ expect(calls.length).toBeGreaterThan(0)
60
+
61
+ for (const call of calls) call[1](new Error('gone'))
62
+
63
+ expect(lost).not.toHaveBeenCalled()
64
+ })
65
+
66
+ it('should not report a lost shard when the connection is closed cleanly', async () => {
67
+ channel = await create(connections, type)
68
+
69
+ const lost = /** @type {jest.MockedFunction} */ jest.fn()
70
+
71
+ channel.diagnose('lost', lost)
72
+
73
+ const calls = connections[1].diagnose.mock.calls.filter((call) => call[0] === 'close')
74
+
75
+ expect(calls.length).toBeGreaterThan(0)
76
+
77
+ for (const call of calls) call[1]()
78
+
79
+ expect(lost).not.toHaveBeenCalled()
80
+ })
81
+
48
82
  it('should not publish to a lost shard', async () => {
49
83
  channel = await create(connections, type)
50
84
 
@@ -7,6 +7,7 @@ declare namespace comq {
7
7
 
8
8
  interface Connection {
9
9
  readonly connected?: boolean
10
+ readonly closed?: boolean
10
11
 
11
12
  open(): Promise<void>
12
13