comq 0.26.0 → 0.27.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/features/shards.virtual.feature +0 -5
- package/features/steps/names.js +0 -10
- package/package.json +1 -1
- package/readme.md +0 -12
- package/source/connect.js +1 -1
- package/source/shards/index.js +0 -2
- package/test/connect.test.js +0 -17
- package/types/connection.d.ts +0 -1
- package/source/shards/expand.js +0 -57
- package/test/shards/expand.test.js +0 -58
|
@@ -8,11 +8,6 @@ Feature: Virtual shards
|
|
|
8
8
|
When I connect to the names
|
|
9
9
|
Then 1 connection is open to each broker
|
|
10
10
|
|
|
11
|
-
Scenario: Names given as a range
|
|
12
|
-
Given 4 names, half of them standing for each broker
|
|
13
|
-
When I connect to the range of the names
|
|
14
|
-
Then 1 connection is open to each broker
|
|
15
|
-
|
|
16
11
|
Scenario: Requests over the names of one broker
|
|
17
12
|
Given 4 names standing for the first broker
|
|
18
13
|
And an active connection to the names
|
package/features/steps/names.js
CHANGED
|
@@ -58,16 +58,6 @@ Given('an active connection to the names', connectNames)
|
|
|
58
58
|
|
|
59
59
|
When('I connect to the names', connectNames)
|
|
60
60
|
|
|
61
|
-
When('I connect to the range of the names',
|
|
62
|
-
/**
|
|
63
|
-
* @this {comq.features.Context}
|
|
64
|
-
*/
|
|
65
|
-
async function () {
|
|
66
|
-
const amount = Object.keys(this.names).length
|
|
67
|
-
|
|
68
|
-
await this.connectNames([name(`[0..${amount}]`)], PORT)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
61
|
When('half of the names move to the {broker} broker',
|
|
72
62
|
/**
|
|
73
63
|
* @param {number} n
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -522,15 +522,6 @@ addresses are two connections.
|
|
|
522
522
|
const io = await connect('amqp://rmq0.example.com', 'amqp://rmq1.example.com', /* ... */)
|
|
523
523
|
```
|
|
524
524
|
|
|
525
|
-
A range in a host is as many URLs. Its end is exclusive, so a range that starts at zero names as
|
|
526
|
-
many hosts as its end says, and a start written with leading zeros pads every number to its
|
|
527
|
-
width:
|
|
528
|
-
|
|
529
|
-
```javascript
|
|
530
|
-
await connect('amqp://developer:secret@rmq[0..32].example.com') // rmq0 … rmq31
|
|
531
|
-
await connect('amqp://developer:secret@rmq[00..32].example.com') // rmq00 … rmq31
|
|
532
|
-
```
|
|
533
|
-
|
|
534
525
|
This is what lets the number of brokers change without anyone being reconfigured: the names stay,
|
|
535
526
|
and what they resolve to moves.
|
|
536
527
|
|
|
@@ -592,9 +583,6 @@ and says nothing of records being updated one by one. A name that is not found i
|
|
|
592
583
|
from the hosts file, or one completed by the resolver's search list) has no TTL, and makes them
|
|
593
584
|
60 seconds.
|
|
594
585
|
|
|
595
|
-
A single URL is one connection made by its name, as it always was, and nothing here applies to
|
|
596
|
-
it.
|
|
597
|
-
|
|
598
586
|
## Singleton connection
|
|
599
587
|
|
|
600
588
|
`async assert(url: string): IO`
|
package/source/connect.js
CHANGED
|
@@ -28,7 +28,7 @@ const split = (args) => {
|
|
|
28
28
|
const urls = /** @type {string[]} */ (typeof last === 'object' ? args.slice(0, -1) : args)
|
|
29
29
|
const { resolution, ...overrides } = /** @type {comq.Options} */ (typeof last === 'object' ? last : {})
|
|
30
30
|
|
|
31
|
-
return [urls
|
|
31
|
+
return [urls, overrides, resolution]
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
/**
|
package/source/shards/index.js
CHANGED
package/test/connect.test.js
CHANGED
|
@@ -77,23 +77,6 @@ describe('sharded connection', () => {
|
|
|
77
77
|
})
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
-
describe('ranges', () => {
|
|
81
|
-
it('should expand a range into the urls of a sharded connection', async () => {
|
|
82
|
-
await connect('amqp://rmq[0..3].example.com')
|
|
83
|
-
|
|
84
|
-
const expanded = ['amqp://rmq0.example.com', 'amqp://rmq1.example.com', 'amqp://rmq2.example.com']
|
|
85
|
-
|
|
86
|
-
expect(shards.Connection).toHaveBeenCalledWith(expanded, expect.any(Function), undefined)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('should connect to a range of one as to a single url', async () => {
|
|
90
|
-
await connect('amqp://rmq[0..1].example.com')
|
|
91
|
-
|
|
92
|
-
expect(Connection).toHaveBeenCalledWith('amqp://rmq0.example.com', {})
|
|
93
|
-
expect(shards.Connection).not.toHaveBeenCalled()
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
|
|
97
80
|
describe('resolution', () => {
|
|
98
81
|
it('should pass how the names are followed, apart from the overrides', async () => {
|
|
99
82
|
const urls = [generate(), generate()]
|
package/types/connection.d.ts
CHANGED
|
@@ -30,7 +30,6 @@ declare namespace comq {
|
|
|
30
30
|
|
|
31
31
|
type Connect = {
|
|
32
32
|
/**
|
|
33
|
-
* A range in a host is as many URLs: `amqp://rmq[0..32].example.com` is `rmq0` to `rmq31`.
|
|
34
33
|
* Several URLs are the names of the shards, and a connection is made to each broker they
|
|
35
34
|
* stand for.
|
|
36
35
|
*/
|
package/source/shards/expand.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Expands the ranges in the host of a URL into a URL per number: `amqp://rmq[0..3].example.com`
|
|
5
|
-
* is `rmq0`, `rmq1` and `rmq2`. The end is exclusive, so a range starting at zero names as many
|
|
6
|
-
* hosts as its end says. A start written with leading zeros pads every number to its width.
|
|
7
|
-
*
|
|
8
|
-
* Only the host is looked at: credentials, a path and a query are free to contain anything, and
|
|
9
|
-
* an IPv6 literal, which is bracketed as well, has no `..` in it.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} url
|
|
12
|
-
* @return {string[]}
|
|
13
|
-
*/
|
|
14
|
-
function expand (url) {
|
|
15
|
-
const parts = url.match(AUTHORITY)
|
|
16
|
-
|
|
17
|
-
if (parts === null) return [url]
|
|
18
|
-
|
|
19
|
-
const [, head, host, tail] = parts
|
|
20
|
-
|
|
21
|
-
return hosts(host).map((host) => head + host + tail)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {string} host
|
|
26
|
-
* @return {string[]}
|
|
27
|
-
*/
|
|
28
|
-
function hosts (host) {
|
|
29
|
-
const range = host.match(RANGE)
|
|
30
|
-
|
|
31
|
-
if (range === null) return [host]
|
|
32
|
-
|
|
33
|
-
const [expression, from, to] = range
|
|
34
|
-
const start = Number(from)
|
|
35
|
-
const end = Number(to)
|
|
36
|
-
|
|
37
|
-
if (end <= start) throw new RangeError(`Range ${expression} names no hosts: its end is exclusive`)
|
|
38
|
-
|
|
39
|
-
const width = from.length > 1 && from.startsWith('0') ? from.length : 0
|
|
40
|
-
const before = host.slice(0, range.index)
|
|
41
|
-
const after = host.slice(range.index + expression.length)
|
|
42
|
-
const expanded = []
|
|
43
|
-
|
|
44
|
-
for (let n = start; n < end; n++) {
|
|
45
|
-
// whatever follows may hold a range of its own
|
|
46
|
-
for (const rest of hosts(after)) expanded.push(before + String(n).padStart(width, '0') + rest)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return expanded
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** What precedes the host, the host with its port, and what follows. */
|
|
53
|
-
const AUTHORITY = /^([a-z][a-z0-9+.-]*:\/\/(?:[^@/?#]*@)?)([^/?#]*)(.*)$/i
|
|
54
|
-
|
|
55
|
-
const RANGE = /\[(\d+)\.\.(\d+)]/
|
|
56
|
-
|
|
57
|
-
exports.expand = expand
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { expand } = require('../../source/shards/expand')
|
|
4
|
-
|
|
5
|
-
it('should leave a url without a range as it is', async () => {
|
|
6
|
-
expect(expand('amqp://user:secret@rmq.example.com:5672/vhost?heartbeat=5'))
|
|
7
|
-
.toStrictEqual(['amqp://user:secret@rmq.example.com:5672/vhost?heartbeat=5'])
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
it('should expand a range, its end being exclusive', async () => {
|
|
11
|
-
expect(expand('amqp://rmq[0..3].example.com')).toStrictEqual([
|
|
12
|
-
'amqp://rmq0.example.com',
|
|
13
|
-
'amqp://rmq1.example.com',
|
|
14
|
-
'amqp://rmq2.example.com'
|
|
15
|
-
])
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('should name as many hosts as the end of a range that starts at zero', async () => {
|
|
19
|
-
expect(expand('amqp://rmq[0..32].example.com')).toHaveLength(32)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('should keep what surrounds the host', async () => {
|
|
23
|
-
expect(expand('amqps://user:secret@rmq-[1..3].example.com:5671/vhost?heartbeat=5')).toStrictEqual([
|
|
24
|
-
'amqps://user:secret@rmq-1.example.com:5671/vhost?heartbeat=5',
|
|
25
|
-
'amqps://user:secret@rmq-2.example.com:5671/vhost?heartbeat=5'
|
|
26
|
-
])
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('should pad to the width the start is written with', async () => {
|
|
30
|
-
expect(expand('amqp://rmq[08..11]')).toStrictEqual(['amqp://rmq08', 'amqp://rmq09', 'amqp://rmq10'])
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should expand every range', async () => {
|
|
34
|
-
expect(expand('amqp://rmq[0..2].zone[0..2]')).toStrictEqual([
|
|
35
|
-
'amqp://rmq0.zone0',
|
|
36
|
-
'amqp://rmq0.zone1',
|
|
37
|
-
'amqp://rmq1.zone0',
|
|
38
|
-
'amqp://rmq1.zone1'
|
|
39
|
-
])
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should leave an IPv6 literal alone', async () => {
|
|
43
|
-
expect(expand('amqp://[::1]:5672')).toStrictEqual(['amqp://[::1]:5672'])
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('should look at the host only', async () => {
|
|
47
|
-
const url = 'amqp://user:[0..2]@rmq.example.com/[0..2]?name=[0..2]'
|
|
48
|
-
|
|
49
|
-
expect(expand(url)).toStrictEqual([url])
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('should leave what is not a url as it is', async () => {
|
|
53
|
-
expect(expand('whatever')).toStrictEqual(['whatever'])
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it.each(['[3..3]', '[3..1]'])('should refuse a range that names no hosts: %s', async (range) => {
|
|
57
|
-
expect(() => expand(`amqp://rmq${range}`)).toThrow(RangeError)
|
|
58
|
-
})
|