@toa.io/bindings.amqp 0.2.1-dev.2 → 0.2.1-dev.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/package.json +3 -3
- package/readme.md +30 -21
- package/source/broadcast.js +49 -0
- package/source/communication.js +54 -0
- package/source/consumer.js +35 -0
- package/source/emitter.js +36 -0
- package/source/factory.js +62 -0
- package/{src → source}/index.js +5 -2
- package/{src → source}/pointer.js +0 -5
- package/source/producer.js +49 -0
- package/source/queues.js +13 -0
- package/source/receiver.js +42 -0
- package/test/annotations.test.js +1 -0
- package/test/broadcast.test.js +83 -0
- package/test/communication.mock.js +20 -0
- package/test/communication.test.js +97 -0
- package/test/comq.mock.js +21 -0
- package/test/consumer.test.js +51 -0
- package/test/emitter.test.js +54 -0
- package/test/factory.test.js +201 -0
- package/test/pointer.test.js +4 -5
- package/test/producer.test.js +69 -0
- package/test/properties.test.js +7 -0
- package/test/queues.mock.js +7 -0
- package/test/queues.test.js +35 -0
- package/test/receiver.test.js +64 -0
- package/types/communication.d.ts +16 -0
- package/src/broadcaster.js +0 -37
- package/src/channel.js +0 -140
- package/src/connection.js +0 -49
- package/src/consumer.js +0 -28
- package/src/emitter.js +0 -31
- package/src/factory.js +0 -69
- package/src/message.js +0 -7
- package/src/producer.js +0 -38
- package/src/queue.js +0 -7
- package/src/receiver.js +0 -39
- package/types/pointer.d.ts +0 -8
- /package/{src → source}/annotation.js +0 -0
- /package/{src → source}/constants.js +0 -0
- /package/{src → source}/deployment.js +0 -0
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/bindings.amqp",
|
|
3
|
-
"version": "0.2.1-dev.
|
|
3
|
+
"version": "0.2.1-dev.4",
|
|
4
4
|
"description": "Toa AMQP Binding",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
7
|
-
"main": "
|
|
7
|
+
"main": "source/index.js",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/toa-io/toa.git"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@toa.io/core": "*",
|
|
28
28
|
"@toa.io/generic": "*",
|
|
29
29
|
"@toa.io/pointer": "*",
|
|
30
|
-
"
|
|
30
|
+
"comq": "*"
|
|
31
31
|
},
|
|
32
32
|
"gitHead": "2be07592325b2e4dc823e81d882a4e50bf50de24"
|
|
33
33
|
}
|
package/readme.md
CHANGED
|
@@ -1,45 +1,54 @@
|
|
|
1
|
-
# AMQP Binding
|
|
1
|
+
# Toa AMQP Binding
|
|
2
2
|
|
|
3
|
-
AMQP
|
|
4
|
-
See [Bindings](#).
|
|
3
|
+
AMQP asynchronous binding on top of [ComQ](/libraries/comq).
|
|
5
4
|
|
|
6
5
|
## Deployment
|
|
7
6
|
|
|
8
|
-
AMQP
|
|
9
|
-
|
|
7
|
+
AMQP deployment must be declared with
|
|
8
|
+
the [Pointer annotation](/libraries/pointer/readme.md#annotation). Either `system` or `default`
|
|
9
|
+
pointers must be defined.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
AMQP deployment must be declared by [URI Set annotation](#) with a `system` extension, which value
|
|
14
|
-
must be the host of the broker to be used by the runtime. Either `system` or `default` hosts must be
|
|
15
|
-
defined.
|
|
11
|
+
Well-known annotation shortcut `amqp` is available.
|
|
16
12
|
|
|
17
13
|
```yaml
|
|
18
14
|
# context.toa.yaml
|
|
19
15
|
annotations:
|
|
20
|
-
@toa.io/bindings.amqp:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
"@toa.io/bindings.amqp":
|
|
17
|
+
system: url0 # the runtime
|
|
18
|
+
default: url1 # all undeclared
|
|
19
|
+
dummies: url2 # namespace-wide
|
|
20
|
+
dummies.dummy1: url # component exclusive
|
|
25
21
|
```
|
|
26
22
|
|
|
27
23
|
### Concise Declaration
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
Well-known shortcut `amqp` is available. The next two declarations are equivalent:
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
```yaml
|
|
28
|
+
# context.toa.yaml
|
|
29
|
+
annotations:
|
|
30
|
+
"@toa.io/bindings.amqp":
|
|
31
|
+
system: url0
|
|
32
|
+
dummies: url1
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
# context.toa.yaml
|
|
37
|
+
amqp:
|
|
38
|
+
system: url0
|
|
39
|
+
dummies: url1
|
|
40
|
+
```
|
|
32
41
|
|
|
33
|
-
The next two declarations are equivalent
|
|
42
|
+
`string` annotation value is considered as `default`. The next two declarations are equivalent:
|
|
34
43
|
|
|
35
44
|
```yaml
|
|
36
45
|
# context.toa.yaml
|
|
37
46
|
annotations:
|
|
38
|
-
@toa.io/bindings.amqp:
|
|
39
|
-
|
|
47
|
+
"@toa.io/bindings.amqp":
|
|
48
|
+
default: url1
|
|
40
49
|
```
|
|
41
50
|
|
|
42
51
|
```yaml
|
|
43
52
|
# context.toa.yaml
|
|
44
|
-
amqp:
|
|
53
|
+
amqp: url1
|
|
45
54
|
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
const { newid } = require('@toa.io/generic')
|
|
5
|
+
|
|
6
|
+
const { name } = require('./queues')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @implements {toa.core.bindings.Broadcast}
|
|
10
|
+
*/
|
|
11
|
+
class Broadcast extends Connector {
|
|
12
|
+
/** @type {toa.amqp.Communication} */
|
|
13
|
+
#comm
|
|
14
|
+
|
|
15
|
+
/** @type {toa.core.Locator} */
|
|
16
|
+
#locator
|
|
17
|
+
|
|
18
|
+
/** @type {string} */
|
|
19
|
+
#group
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {toa.amqp.Communication} comm
|
|
23
|
+
* @param {toa.core.Locator} locator
|
|
24
|
+
* @param {string} [group]
|
|
25
|
+
*/
|
|
26
|
+
constructor (comm, locator, group) {
|
|
27
|
+
super()
|
|
28
|
+
|
|
29
|
+
this.#comm = comm
|
|
30
|
+
this.#locator = locator
|
|
31
|
+
this.#group = group ?? newid()
|
|
32
|
+
|
|
33
|
+
this.depends(comm)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async transmit (label, payload) {
|
|
37
|
+
const exchange = name(this.#locator, label)
|
|
38
|
+
|
|
39
|
+
await this.#comm.emit(exchange, payload)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async receive (label, callback) {
|
|
43
|
+
const exchange = name(this.#locator, label)
|
|
44
|
+
|
|
45
|
+
await this.#comm.consume(exchange, this.#group, callback)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.Broadcast = Broadcast
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { connect } = require('comq')
|
|
4
|
+
const { Connector } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @implements {toa.amqp.Communication}
|
|
8
|
+
*/
|
|
9
|
+
class Communication extends Connector {
|
|
10
|
+
/** @type {toa.pointer.Pointer} */
|
|
11
|
+
#pointer
|
|
12
|
+
|
|
13
|
+
/** @type {comq.IO} */
|
|
14
|
+
#io
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {toa.pointer.Pointer} pointer
|
|
18
|
+
*/
|
|
19
|
+
constructor (pointer) {
|
|
20
|
+
super()
|
|
21
|
+
|
|
22
|
+
this.#pointer = pointer
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async open () {
|
|
26
|
+
this.#io = await connect(this.#pointer.reference)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async close () {
|
|
30
|
+
await this.#io.seal()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async dispose () {
|
|
34
|
+
await this.#io.close()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async reply (queue, process) {
|
|
38
|
+
await this.#io.reply(queue, process)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async request (queue, request) {
|
|
42
|
+
return this.#io.request(queue, request)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async emit (exchange, message) {
|
|
46
|
+
await this.#io.emit(exchange, message)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async consume (exchange, group, consumer) {
|
|
50
|
+
await this.#io.consume(exchange, group, consumer)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.Communication = Communication
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
const { name } = require('./queues')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @implements {toa.core.bindings.Consumer}
|
|
8
|
+
*/
|
|
9
|
+
class Consumer extends Connector {
|
|
10
|
+
/** @type {string} */
|
|
11
|
+
#queue
|
|
12
|
+
|
|
13
|
+
/** @type {toa.amqp.Communication} */
|
|
14
|
+
#comm
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {toa.amqp.Communication} comm
|
|
18
|
+
* @param {toa.core.Locator} locator
|
|
19
|
+
* @param {string} endpoint
|
|
20
|
+
*/
|
|
21
|
+
constructor (comm, locator, endpoint) {
|
|
22
|
+
super()
|
|
23
|
+
|
|
24
|
+
this.#queue = name(locator, endpoint)
|
|
25
|
+
this.#comm = comm
|
|
26
|
+
|
|
27
|
+
this.depends(comm)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async request (request) {
|
|
31
|
+
return this.#comm.request(this.#queue, request)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.Consumer = Consumer
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
const { name } = require('./queues')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @implements {toa.core.bindings.Emitter}
|
|
9
|
+
*/
|
|
10
|
+
class Emitter extends Connector {
|
|
11
|
+
/** @type {string} */
|
|
12
|
+
#exchange
|
|
13
|
+
|
|
14
|
+
/** @type {toa.amqp.Communication} */
|
|
15
|
+
#comm
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {toa.amqp.Communication} comm
|
|
19
|
+
* @param {toa.core.Locator} locator
|
|
20
|
+
* @param {string} label
|
|
21
|
+
*/
|
|
22
|
+
constructor (comm, locator, label) {
|
|
23
|
+
super()
|
|
24
|
+
|
|
25
|
+
this.#exchange = name(locator, label)
|
|
26
|
+
this.#comm = comm
|
|
27
|
+
|
|
28
|
+
this.depends(comm)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async emit (message) {
|
|
32
|
+
await this.#comm.emit(this.#exchange, message)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.Emitter = Emitter
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Locator } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
const { Pointer } = require('./pointer')
|
|
6
|
+
const { Communication } = require('./communication')
|
|
7
|
+
const { Producer } = require('./producer')
|
|
8
|
+
const { Consumer } = require('./consumer')
|
|
9
|
+
const { Emitter } = require('./emitter')
|
|
10
|
+
const { Receiver } = require('./receiver')
|
|
11
|
+
const { Broadcast } = require('./broadcast')
|
|
12
|
+
|
|
13
|
+
const { SYSTEM } = require('./constants')
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @implements {toa.core.bindings.Factory}
|
|
17
|
+
*/
|
|
18
|
+
class Factory {
|
|
19
|
+
producer (locator, endpoints, component) {
|
|
20
|
+
const comm = this.#getCommunication(locator)
|
|
21
|
+
|
|
22
|
+
return new Producer(comm, locator, endpoints, component)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
consumer (locator, endpoint) {
|
|
26
|
+
const comm = this.#getCommunication(locator)
|
|
27
|
+
|
|
28
|
+
return new Consumer(comm, locator, endpoint)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
emitter (locator, label) {
|
|
32
|
+
const comm = this.#getCommunication(locator)
|
|
33
|
+
|
|
34
|
+
return new Emitter(comm, locator, label)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
receiver (locator, label, group, receiver) {
|
|
38
|
+
const comm = this.#getCommunication(locator)
|
|
39
|
+
|
|
40
|
+
return new Receiver(comm, locator, label, group, receiver)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
broadcast (name, group) {
|
|
44
|
+
const locator = new Locator(name, SYSTEM)
|
|
45
|
+
const comm = this.#getCommunication(locator)
|
|
46
|
+
|
|
47
|
+
return new Broadcast(comm, locator, group)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param {toa.core.Locator} locator
|
|
53
|
+
* @return {toa.amqp.Communication}
|
|
54
|
+
*/
|
|
55
|
+
#getCommunication (locator) {
|
|
56
|
+
const pointer = /** @type {toa.pointer.Pointer} */ new Pointer(locator)
|
|
57
|
+
|
|
58
|
+
return new Communication(pointer)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exports.Factory = Factory
|
package/{src → source}/index.js
RENAMED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { Factory } = require('./factory')
|
|
4
3
|
const { deployment } = require('./deployment')
|
|
5
4
|
const { annotation } = require('./annotation')
|
|
5
|
+
const { Factory } = require('./factory')
|
|
6
|
+
|
|
7
|
+
/** @type {toa.core.bindings.Properties} */
|
|
8
|
+
const properties = { async: true }
|
|
6
9
|
|
|
7
|
-
exports.properties =
|
|
10
|
+
exports.properties = properties
|
|
8
11
|
exports.annotation = annotation
|
|
9
12
|
exports.deployment = deployment
|
|
10
13
|
exports.Factory = Factory
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { Pointer: Base } = require('@toa.io/pointer')
|
|
4
|
-
|
|
5
4
|
const { PREFIX } = require('./constants')
|
|
6
5
|
|
|
7
|
-
// noinspection JSClosureCompilerSyntax
|
|
8
|
-
/**
|
|
9
|
-
* @implements {toa.amqp.Pointer}
|
|
10
|
-
*/
|
|
11
6
|
class Pointer extends Base {
|
|
12
7
|
/**
|
|
13
8
|
* @param {toa.core.Locator} locator
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
const { name } = require('./queues')
|
|
6
|
+
|
|
7
|
+
class Producer extends Connector {
|
|
8
|
+
/** @type {toa.amqp.Communication} */
|
|
9
|
+
#comm
|
|
10
|
+
|
|
11
|
+
/** @type {toa.core.Locator} */
|
|
12
|
+
#locator
|
|
13
|
+
|
|
14
|
+
/** @type {string[]} */
|
|
15
|
+
#endpoints
|
|
16
|
+
|
|
17
|
+
/** @type {toa.core.Component} */
|
|
18
|
+
#component
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {toa.amqp.Communication} comm
|
|
22
|
+
* @param {toa.core.Locator} locator
|
|
23
|
+
* @param {string[]} endpoints
|
|
24
|
+
* @param {toa.core.Component} component
|
|
25
|
+
*/
|
|
26
|
+
constructor (comm, locator, endpoints, component) {
|
|
27
|
+
super()
|
|
28
|
+
|
|
29
|
+
this.#comm = comm
|
|
30
|
+
this.#locator = locator
|
|
31
|
+
this.#endpoints = endpoints
|
|
32
|
+
this.#component = component
|
|
33
|
+
|
|
34
|
+
this.depends(comm)
|
|
35
|
+
this.depends(component)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async open () {
|
|
39
|
+
await Promise.all(this.#endpoints.map((endpoint) => this.#endpoint(endpoint)))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async #endpoint (endpoint) {
|
|
43
|
+
const queue = name(this.#locator, endpoint)
|
|
44
|
+
|
|
45
|
+
await this.#comm.reply(queue, (request) => this.#component.invoke(endpoint, request))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.Producer = Producer
|
package/source/queues.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { concat } = require('@toa.io/generic')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.core.Locator} locator
|
|
7
|
+
* @param {string} endpoint
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
const name = (locator, endpoint) =>
|
|
11
|
+
locator.namespace + '.' + concat(locator.name, '.') + endpoint
|
|
12
|
+
|
|
13
|
+
exports.name = name
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
const { name } = require('./queues')
|
|
5
|
+
|
|
6
|
+
class Receiver extends Connector {
|
|
7
|
+
/** @type {string} */
|
|
8
|
+
#exchange
|
|
9
|
+
|
|
10
|
+
/** @type {string} */
|
|
11
|
+
#group
|
|
12
|
+
|
|
13
|
+
/** @type {toa.amqp.Communication} */
|
|
14
|
+
#comm
|
|
15
|
+
|
|
16
|
+
/** @type {toa.core.Receiver} */
|
|
17
|
+
#receiver
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {toa.amqp.Communication} comm
|
|
21
|
+
* @param {toa.core.Locator} locator
|
|
22
|
+
* @param {string} label
|
|
23
|
+
* @param {string} group
|
|
24
|
+
* @param {toa.core.Receiver} receiver
|
|
25
|
+
*/
|
|
26
|
+
constructor (comm, locator, label, group, receiver) {
|
|
27
|
+
super()
|
|
28
|
+
|
|
29
|
+
this.#exchange = name(locator, label)
|
|
30
|
+
this.#group = group
|
|
31
|
+
this.#comm = comm
|
|
32
|
+
this.#receiver = receiver
|
|
33
|
+
|
|
34
|
+
this.depends(comm)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async open () {
|
|
38
|
+
await this.#comm.consume(this.#exchange, this.#group, (message) => this.#receiver.receive(message))
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.Receiver = Receiver
|
package/test/annotations.test.js
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// region setup
|
|
4
|
+
|
|
5
|
+
const { generate } = require('randomstring')
|
|
6
|
+
const { Connector } = require('@toa.io/core')
|
|
7
|
+
|
|
8
|
+
const mock = {
|
|
9
|
+
communication: require('./communication.mock').communication,
|
|
10
|
+
queues: require('./queues.mock')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
jest.mock('../source/queues', () => mock.queues)
|
|
14
|
+
|
|
15
|
+
const { Broadcast } = require('../source/broadcast')
|
|
16
|
+
|
|
17
|
+
it('should be', async () => {
|
|
18
|
+
expect(Broadcast).toBeDefined()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const comm = mock.communication()
|
|
22
|
+
const locator = /** @type {toa.core.Locator} */ { namespace: generate(), name: generate() }
|
|
23
|
+
const group = generate()
|
|
24
|
+
|
|
25
|
+
/** @type {toa.core.bindings.Broadcast} */
|
|
26
|
+
let broadcast
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
jest.clearAllMocks()
|
|
30
|
+
|
|
31
|
+
broadcast = new Broadcast(comm, locator, group)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// endregion
|
|
35
|
+
|
|
36
|
+
it('should be instance of Connector', async () => {
|
|
37
|
+
expect(broadcast).toBeInstanceOf(Connector)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should depend on communication', async () => {
|
|
41
|
+
expect(comm.link).toHaveBeenCalledWith(broadcast)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should transmit', async () => {
|
|
45
|
+
const label = generate()
|
|
46
|
+
const message = generate()
|
|
47
|
+
|
|
48
|
+
await broadcast.transmit(label, message)
|
|
49
|
+
|
|
50
|
+
expect(mock.queues.name).toHaveBeenCalledWith(locator, label)
|
|
51
|
+
|
|
52
|
+
const exchange = mock.queues.name.mock.results[0].value
|
|
53
|
+
|
|
54
|
+
expect(comm.emit).toHaveBeenCalledWith(exchange, message)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('should receive', async () => {
|
|
58
|
+
const label = generate()
|
|
59
|
+
const process = jest.fn(async () => undefined)
|
|
60
|
+
|
|
61
|
+
await broadcast.receive(label, process)
|
|
62
|
+
|
|
63
|
+
expect(mock.queues.name).toHaveBeenCalledWith(locator, label)
|
|
64
|
+
|
|
65
|
+
const exchange = mock.queues.name.mock.results[0].value
|
|
66
|
+
|
|
67
|
+
expect(comm.consume).toHaveBeenCalledWith(exchange, group, expect.any(Function))
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should create unique group if not provided', async () => {
|
|
71
|
+
jest.clearAllMocks()
|
|
72
|
+
|
|
73
|
+
broadcast = new Broadcast(comm, locator)
|
|
74
|
+
|
|
75
|
+
const label = generate()
|
|
76
|
+
const process = jest.fn(async () => undefined)
|
|
77
|
+
|
|
78
|
+
await broadcast.receive(label, process)
|
|
79
|
+
|
|
80
|
+
const group = comm.consume.mock.calls[0][1]
|
|
81
|
+
|
|
82
|
+
expect(group).toBeDefined()
|
|
83
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @return {jest.MockedObject<toa.amqp.Communication>}
|
|
7
|
+
*/
|
|
8
|
+
const communication = () => (
|
|
9
|
+
/** @type {jest.MockedObject<toa.amqp.Communication>} */ {
|
|
10
|
+
connect: jest.fn(async () => undefined),
|
|
11
|
+
request: jest.fn(async () => generate()),
|
|
12
|
+
reply: jest.fn(async () => undefined),
|
|
13
|
+
emit: jest.fn(async () => undefined),
|
|
14
|
+
consume: jest.fn(async () => undefined),
|
|
15
|
+
|
|
16
|
+
link: jest.fn()
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
exports.communication = communication
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Connector } = require('@toa.io/core')
|
|
5
|
+
const mock = require('./comq.mock')
|
|
6
|
+
|
|
7
|
+
jest.mock('comq', () => mock.comq)
|
|
8
|
+
|
|
9
|
+
const { Communication } = require('../source/communication')
|
|
10
|
+
|
|
11
|
+
it('should be', async () => {
|
|
12
|
+
expect(Communication).toBeDefined()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/** @type {toa.pointer.Pointer} */
|
|
16
|
+
let pointer
|
|
17
|
+
|
|
18
|
+
/** @type {toa.amqp.Communication} */
|
|
19
|
+
let comm
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks()
|
|
23
|
+
|
|
24
|
+
pointer = /** @type {toa.pointer.Pointer} */ { reference: generate() }
|
|
25
|
+
comm = new Communication(pointer)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should be instance of Connector', async () => {
|
|
29
|
+
expect(comm).toBeInstanceOf(Connector)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should connect to a given pointer reference', async () => {
|
|
33
|
+
await comm.open()
|
|
34
|
+
|
|
35
|
+
expect(mock.comq.connect).toHaveBeenCalledWith(pointer.reference)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('connected', () => {
|
|
39
|
+
/** @type {jest.MockedObject<comq.IO>} */
|
|
40
|
+
let io
|
|
41
|
+
|
|
42
|
+
beforeEach(async () => {
|
|
43
|
+
await comm.open()
|
|
44
|
+
|
|
45
|
+
io = await mock.comq.connect.mock.results[0].value
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should close', async () => {
|
|
49
|
+
await comm.close()
|
|
50
|
+
|
|
51
|
+
expect(io.seal).toHaveBeenCalled()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should dispose', async () => {
|
|
55
|
+
await comm.dispose()
|
|
56
|
+
|
|
57
|
+
expect(io.close).toHaveBeenCalled()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should bind reply', async () => {
|
|
61
|
+
const queue = generate()
|
|
62
|
+
const producer = jest.fn(async () => undefined)
|
|
63
|
+
|
|
64
|
+
await comm.reply(queue, producer)
|
|
65
|
+
|
|
66
|
+
expect(io.reply).toHaveBeenCalledWith(queue, producer)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should send request', async () => {
|
|
70
|
+
const queue = generate()
|
|
71
|
+
const request = generate()
|
|
72
|
+
|
|
73
|
+
const reply = await comm.request(queue, request)
|
|
74
|
+
|
|
75
|
+
expect(io.request).toHaveBeenCalledWith(queue, request)
|
|
76
|
+
expect(reply).toStrictEqual(await io.request.mock.results[0].value)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should emit', async () => {
|
|
80
|
+
const exchange = generate()
|
|
81
|
+
const message = generate()
|
|
82
|
+
|
|
83
|
+
await comm.emit(exchange, message)
|
|
84
|
+
|
|
85
|
+
expect(io.emit).toHaveBeenCalledWith(exchange, message)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should consume', async () => {
|
|
89
|
+
const exchange = generate()
|
|
90
|
+
const group = generate()
|
|
91
|
+
const consumer = jest.fn(async () => undefined)
|
|
92
|
+
|
|
93
|
+
await comm.consume(exchange, group, consumer)
|
|
94
|
+
|
|
95
|
+
expect(io.consume).toHaveBeenCalledWith(exchange, group, consumer)
|
|
96
|
+
})
|
|
97
|
+
})
|