iambus
Version:
minimalist pattern-matching pub-sub message-bus
172 lines (123 loc) • 4.54 kB
Markdown
# iambus
> minimalist pattern-matching pub-sub message-bus
## Installation
Install using npm:
```bash
npm install iambus
```
## Creating a bus
```js
const Iambus = require('iambus')
const bus = new Iambus()
```
## Publishing Messages
Messages should be objects. To publish a message to the bus, use the `pub` method:
```js
const message = {
topic: 'news',
content: 'Hello, world!'
}
bus.pub(message)
```
## Subscribing & Unsubscribing
Subscribers are Readable [streamx](https://npmjs.com/package/streamx) streams.
Subscribe to a pattern (an object which partially matches against target messages).
To subscribe to messages pass a pattern object to the `sub` method:
```js
const pattern= { topic: 'news' }
const subscriber = bus.sub(pattern)
```
The pattern object must deeply-equal properties in a published message to match (but does not need to match all properties).
When in async contexts (such as async functions or top-level ESM), a `for await...of` loop can be used to listen for messages:
```js
for await (const message of subscriber) {
console.log('Received one message:', message)
break
}
```
To unsubscribe, destroy the stream. The usage of `break` in the `for await` loop causes the `subscriber` stream to be destroyed. Exiting the loop via `return` also causes the `subscriber` stream to be destroyed.
Here's an equivalent example with the `data` event and `destroy` method:
```js
// Listen for messages using 'data' event
subscriber.on('data', (message) => {
console.log('Received one message:', message)
subscriber.destroy()
})
```
A graceful stream close is also possible with the `end` method:
```js
// Listen for messages using 'data' event
subscriber.on('data', (message) => {
console.log('Received one message:', message)
subscriber.end()
})
```
### Subscribing to all messages
An empty pattern object can be used to subscribe to all messages on the bus:
```js
async function msglogger () {
for await (const message of bus.sub({})) console.log('BUS MSG', Date.now(), ' - ', message)
}
msglogger().catch(console.error)
```
## Resubscribing
To resubscribe create a new subscriber using `bus.sub(pattern)`.
```js
import Iambus from './index.js'
const bus = new Iambus()
let count = 0
setImmediate(() => {
bus.pub({ match: 'this', and: { also: 'this' }, content: 'Hello, world!' })
setImmediate(() => {
bus.pub({ match: 'this', and: { also: 'this' }, content: 'more content' })
setImmediate(() => {
bus.pub({ match: 'this', and: { also: 'this' }, content: 'even more content' })
})
})
})
for await (const message of bus.sub({ match: 'this', and: { also: 'this' } })) {
console.log('1st subscriber got', message)
if (++count === 2) break // destroy
}
for await (const message of bus.sub({ match: 'this', and: { also: 'this' } })) {
console.log('2nd subscriber got', message)
if (++count === 3) break // destroy
}
console.log('done')
```
This should output:
```sh
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'Hello, world!' }
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'more content' }
2nd subscriber got { match: 'this', and: { also: 'this' }, content: 'even more content' }
done
```
## Example
The [example.mjs](./example.mjs) file contains both the resubscribing code and the message logger
that uses an empty pattern to subscribe to all messages.
```
node example.mjs
```
Should output:
```sh
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'Hello, world!' }
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'more content' }
2nd subscriber got { match: 'this', and: { also: 'this' }, content: 'even more content' }
done
```
```
node example.mjs --log
```
Should output similar to:
```sh
BUS MSG 2023-06-21T15:25:32.897Z - { match: 'this', and: { also: 'this' }, content: 'Hello, world!' }
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'Hello, world!' }
BUS MSG 2023-06-21T15:25:32.901Z - { something: 'else', whatever: 'that might be' }
1st subscriber got { match: 'this', and: { also: 'this' }, content: 'more content' }
BUS MSG 2023-06-21T15:25:32.901Z - { match: 'this', and: { also: 'this' }, content: 'more content' }
BUS MSG 2023-06-21T15:25:32.902Z - { match: 'this', and: { also: 'this' }, content: 'even more content' }
2nd subscriber got { match: 'this', and: { also: 'this' }, content: 'even more content' }
done
```
## License
Apache License 2.0. See the [LICENSE](./LICENSE) file for more details.