@toa.io/bindings.amqp 0.2.1-dev.3 → 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/src/channel.js DELETED
@@ -1,140 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
- const { newid, timeout } = require('@toa.io/generic')
5
- const { console } = require('@toa.io/console')
6
-
7
- const { pack, unpack } = require('./message')
8
-
9
- class Channel extends Connector {
10
- #id
11
- #connection
12
- #channel
13
-
14
- #bound = {}
15
- #expected = {}
16
-
17
- constructor (connection) {
18
- super()
19
-
20
- this.#id = newid()
21
- this.#connection = connection
22
-
23
- this.depends(connection)
24
- }
25
-
26
- async connection () {
27
- this.#channel = await this.#connection.channel()
28
- this.#channel.prefetch(100)
29
- }
30
-
31
- async disconnection () {
32
- // solves 'Channel ended, no reply will be forthcoming'
33
- await timeout(50)
34
- }
35
-
36
- async request (label, request) {
37
- const queue = 'request.' + label
38
- const correlation = newid()
39
-
40
- await this.#channel.assertQueue(queue, QUEUE)
41
- await this.#bind(label)
42
-
43
- const message = pack(request)
44
- const properties = { replyTo: this.#id, correlationId: correlation }
45
-
46
- await this.#channel.sendToQueue(queue, message, properties)
47
-
48
- const reply = await this.#reply(label, correlation)
49
-
50
- return unpack(reply.content)
51
- }
52
-
53
- async reply (label, invocation) {
54
- const queue = 'request.' + label
55
- const exchange = 'reply.' + label
56
-
57
- await this.#channel.assertQueue(queue, QUEUE)
58
- await this.#channel.assertExchange(exchange, 'direct', EXCHANGE)
59
-
60
- await this.#channel.consume(queue, async (received) => {
61
- const content = unpack(received.content)
62
- const reply = await invocation(content)
63
-
64
- const buffer = pack(reply)
65
- const properties = { correlationId: received.properties.correlationId }
66
-
67
- await this.#channel.publish(exchange, received.properties.replyTo, buffer, properties)
68
- await this.#channel.ack(received)
69
- })
70
- }
71
-
72
- async publish (label, content, options) {
73
- const exchange = 'event.' + label
74
-
75
- // TODO: assert once per exchange
76
- await this.#channel.assertExchange(exchange, 'fanout', EXCHANGE)
77
-
78
- const buffer = pack(content)
79
-
80
- await this.#channel.publish(exchange, '', buffer, options)
81
- }
82
-
83
- async subscribe (label, id, callback) {
84
- const exchange = 'event.' + label
85
- const queue = exchange + '..' + id
86
- const options = { consumerTag: id }
87
-
88
- await this.#channel.assertExchange(exchange, 'fanout', EXCHANGE)
89
- await this.#channel.assertQueue(queue, QUEUE)
90
- await this.#channel.bindQueue(queue, exchange, '')
91
-
92
- await this.#channel.consume(queue, async (message) => {
93
- const content = unpack(message.content)
94
- await callback(content)
95
- await this.#channel.ack(message)
96
- }, options)
97
- }
98
-
99
- async unsubscribe (id) {
100
- await this.#channel.cancel(id)
101
- }
102
-
103
- async #bind (label) {
104
- const queue = `reply.${label}.${this.#id}`
105
- const exchange = 'reply.' + label
106
-
107
- if (this.#bound[queue]) return
108
-
109
- await this.#channel.assertQueue(queue, { exclusive: true, ...QUEUE })
110
- await this.#channel.assertExchange(exchange, 'direct', EXCHANGE)
111
- await this.#channel.bindQueue(queue, exchange, this.#id)
112
- await this.#channel.consume(queue, (message) => this.#replies(message))
113
-
114
- this.#bound[queue] = true
115
- }
116
-
117
- #reply (label, correlation) {
118
- return new Promise((resolve) => (this.#expected[correlation] = resolve))
119
- }
120
-
121
- async #replies (message) {
122
- const correlation = message.properties.correlationId
123
- const resolve = this.#expected[correlation]
124
-
125
- if (!resolve) {
126
- console.warn(`Unexpected reply '${correlation}'. Possible message redelivery.`)
127
- return
128
- }
129
-
130
- resolve(message)
131
-
132
- delete this.#expected[correlation]
133
- await this.#channel.ack(message)
134
- }
135
- }
136
-
137
- const QUEUE = { durable: true }
138
- const EXCHANGE = { durable: true }
139
-
140
- exports.Channel = Channel
package/src/connection.js DELETED
@@ -1,49 +0,0 @@
1
- 'use strict'
2
-
3
- const amqp = require('amqplib')
4
-
5
- const { Connector } = require('@toa.io/core')
6
- const { console } = require('@toa.io/console')
7
-
8
- class Connection extends Connector {
9
- /** @type {toa.amqp.Pointer} */
10
- #pointer
11
-
12
- /** @type {import('amqplib').Connection} */
13
- #connection
14
-
15
- /**
16
- * @param {toa.amqp.Pointer} pointer
17
- */
18
- constructor (pointer) {
19
- super()
20
-
21
- this.#pointer = pointer
22
- }
23
-
24
- async connection () {
25
- try {
26
- this.#connection = await amqp.connect(this.#pointer.reference)
27
- } catch (e) {
28
- console.error(`Connection to ${this.#pointer.label} has failed`)
29
-
30
- throw e
31
- }
32
-
33
- console.info(`AMQP Binding connected to ${this.#pointer.label}`)
34
- }
35
-
36
- async disconnection () {
37
- // TODO: handle current operations
38
- // http://www.squaremobius.net/amqp.node/channel_api.html#model_close
39
- await this.#connection.close()
40
-
41
- console.info(`AMQP Binding disconnected from ${this.#pointer.label}`)
42
- }
43
-
44
- async channel () {
45
- return await this.#connection.createChannel()
46
- }
47
- }
48
-
49
- exports.Connection = Connection
package/src/consumer.js DELETED
@@ -1,28 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
-
5
- const { name } = require('./queue')
6
-
7
- /**
8
- * @implements {toa.core.bindings.Consumer}
9
- */
10
- class Consumer extends Connector {
11
- #channel
12
- #queue
13
-
14
- constructor (channel, locator, endpoint) {
15
- super()
16
-
17
- this.#channel = channel
18
- this.#queue = name(locator, endpoint)
19
-
20
- this.depends(channel)
21
- }
22
-
23
- async request (request) {
24
- return this.#channel.request(this.#queue, request)
25
- }
26
- }
27
-
28
- exports.Consumer = Consumer
package/src/emitter.js DELETED
@@ -1,31 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
- const { name } = require('./queue')
5
-
6
- /**
7
- * @implements {toa.core.bindings.Emitter}
8
- */
9
- class Emitter extends Connector {
10
- #channel
11
- #locator
12
- #label
13
-
14
- constructor (channel, locator, label) {
15
- super()
16
-
17
- this.#channel = channel
18
- this.#locator = locator
19
- this.#label = label
20
-
21
- this.depends(channel)
22
- }
23
-
24
- async emit (payload) {
25
- const label = name(this.#locator, this.#label)
26
-
27
- await this.#channel.publish(label, payload)
28
- }
29
- }
30
-
31
- exports.Emitter = Emitter
package/src/factory.js DELETED
@@ -1,69 +0,0 @@
1
- 'use strict'
2
-
3
- const { Locator } = require('@toa.io/core')
4
-
5
- const { Channel } = require('./channel')
6
- const { Consumer } = require('./consumer')
7
- const { Producer } = require('./producer')
8
- const { Emitter } = require('./emitter')
9
- const { Receiver } = require('./receiver')
10
- const { Broadcaster } = require('./broadcaster')
11
- const { Connection } = require('./connection')
12
- const { Pointer } = require('./pointer')
13
- const { SYSTEM } = require('./constants')
14
-
15
- /**
16
- * @implements {toa.core.bindings.Factory}
17
- */
18
- class Factory {
19
- #connections = {}
20
-
21
- producer (locator, endpoints, producer) {
22
- const channel = this.#channel(locator)
23
-
24
- return new Producer(channel, locator, endpoints, producer)
25
- }
26
-
27
- consumer (locator, endpoint) {
28
- const channel = this.#channel(locator)
29
-
30
- return new Consumer(channel, locator, endpoint)
31
- }
32
-
33
- emitter (locator, label) {
34
- const channel = this.#channel(locator)
35
-
36
- return new Emitter(channel, locator, label)
37
- }
38
-
39
- receiver (locator, label, id, receiver) {
40
- const channel = this.#channel(locator)
41
-
42
- return new Receiver(channel, locator, label, id, receiver)
43
- }
44
-
45
- broadcaster (name, group) {
46
- const channel = this.#channel()
47
-
48
- return new Broadcaster(channel, name, group)
49
- }
50
-
51
- /**
52
- * @param {toa.core.Locator} [locator]
53
- * @returns {Channel}
54
- */
55
- #channel (locator) {
56
- if (locator === undefined) locator = new Locator(SYSTEM)
57
-
58
- const pointer = new Pointer(locator)
59
- const key = pointer.reference
60
-
61
- if (this.#connections[key] === undefined) {
62
- this.#connections[key] = new Connection(pointer)
63
- }
64
-
65
- return new Channel(this.#connections[key])
66
- }
67
- }
68
-
69
- exports.Factory = Factory
package/src/message.js DELETED
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- const pack = (content) => Buffer.from(JSON.stringify(content))
4
- const unpack = (content) => JSON.parse(content)
5
-
6
- exports.pack = pack
7
- exports.unpack = unpack
package/src/producer.js DELETED
@@ -1,38 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
-
5
- const { name } = require('./queue')
6
-
7
- class Producer extends Connector {
8
- #channel
9
- /** @type {toa.core.Locator} */
10
- #locator
11
- /** @type {toa.core.Component} */
12
- #producer
13
- /** @type {Array<string>} */
14
- #endpoints
15
-
16
- constructor (channel, locator, endpoints, producer) {
17
- super()
18
-
19
- this.#channel = channel
20
- this.#locator = locator
21
- this.#endpoints = endpoints
22
- this.#producer = producer
23
-
24
- this.depends(channel)
25
- this.depends(producer)
26
- }
27
-
28
- async connection () {
29
- await Promise.all(this.#endpoints.map((endpoint) => this.#endpoint(endpoint)))
30
- }
31
-
32
- async #endpoint (endpoint) {
33
- const queue = name(this.#locator, endpoint)
34
- await this.#channel.reply(queue, async (request) => this.#producer.invoke(endpoint, request))
35
- }
36
- }
37
-
38
- exports.Producer = Producer
package/src/queue.js DELETED
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- const { concat } = require('@toa.io/generic')
4
-
5
- const name = (locator, endpoint) => locator.namespace + '.' + concat(locator.name, '.') + endpoint
6
-
7
- exports.name = name
package/src/receiver.js DELETED
@@ -1,39 +0,0 @@
1
- 'use strict'
2
-
3
- const { Connector } = require('@toa.io/core')
4
-
5
- const { name } = require('./queue')
6
-
7
- class Receiver extends Connector {
8
- #channel
9
- /** @type {toa.core.Receiver} */
10
- #receiver
11
-
12
- /** @type {string} */
13
- #label
14
-
15
- /** @type {string} */
16
- #id
17
-
18
- constructor (channel, locator, label, id, receiver) {
19
- super()
20
-
21
- this.#channel = channel
22
- this.#receiver = receiver
23
- this.#label = name(locator, label)
24
- this.#id = id
25
-
26
- this.depends(channel)
27
- this.depends(receiver)
28
- }
29
-
30
- async connection () {
31
- await this.#channel.subscribe(this.#label, this.#id, (message) => this.#receiver.receive(message))
32
- }
33
-
34
- async disconnection () {
35
- await this.#channel.unsubscribe(this.#id)
36
- }
37
- }
38
-
39
- exports.Receiver = Receiver
@@ -1,8 +0,0 @@
1
- import type { Pointer as Base } from '@toa.io/pointer/types'
2
-
3
- declare namespace toa.amqp {
4
-
5
- interface Pointer extends Base {
6
- }
7
-
8
- }
File without changes
File without changes
File without changes