Skip to content

Commit

Permalink
feat: allow to pass custom timer for keepalive manager (#1896)
Browse files Browse the repository at this point in the history
* feat: allow to pass custom timer for keepalive manager

* docs(readme): update `timerVariant` description

* feat: export `Timer` type

* feat(test): add test for KeepaliveManager to use provided Timer object

* fix(type): add Timer type to timerVariant on client options

---------

Co-authored-by: Sandu Luca <[email protected]>
  • Loading branch information
sanduluca and sanduluca authored Jul 1, 2024
1 parent 37b08c9 commit ee81184
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,14 @@ The arguments are:
- `messageIdProvider`: custom messageId provider. when `new UniqueMessageIdProvider()` is set, then non conflict messageId is provided.
- `log`: custom log function. Default uses [debug](https://www.npmjs.com/package/debug) package.
- `manualConnect`: prevents the constructor to call `connect`. In this case after the `mqtt.connect` is called you should call `client.connect` manually.
- `timerVariant`: defaults to `auto`, which tries to determine which timer is most appropriate for you environment, if you're having detection issues, you can set it to `worker` or `native`
- `timerVariant`: defaults to `auto`, which tries to determine which timer is most appropriate for you environment, if you're having detection issues, you can set it to `worker` or `native`. If none suits you, you can pass a timer object with set and clear properties:
```js
timerVariant: {
set: (func, timer) => setInterval(func, timer),
clear: (id) => clearInterval(id)
}
```

- `unixSocket`: if you want to connect to a unix socket, set this to true

In case mqtts (mqtt over tls) is required, the `options` object is passed through to [`tls.connect()`](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback). If using a **self-signed certificate**, set `rejectUnauthorized: false`. However, be cautious as this exposes you to potential man in the middle attacks and isn't recommended for production.
Expand Down
9 changes: 7 additions & 2 deletions src/lib/KeepaliveManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ export default class KeepaliveManager {
return this._keepalive
}

constructor(client: MqttClient, variant: TimerVariant) {
constructor(client: MqttClient, variant: TimerVariant | Timer) {
this.client = client
this.timer = getTimer(variant)
this.timer =
typeof variant === 'object' &&
'set' in variant &&
'clear' in variant
? variant
: getTimer(variant)
this.setKeepalive(client.options.keepalive)
}

Expand Down
4 changes: 3 additions & 1 deletion src/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import TopicAliasSend from './topic-alias-send'
import { TypedEventEmitter } from './TypedEmitter'
import KeepaliveManager from './KeepaliveManager'
import isBrowser, { isWebWorker } from './is-browser'
import { Timer } from './get-timer'

const setImmediate =
globalThis.setImmediate ||
Expand Down Expand Up @@ -278,8 +279,9 @@ export interface IClientOptions extends ISecureClientOptions {
properties?: IConnectPacket['properties']
/**
* @description 'auto', set to 'native' or 'worker' if you're having issues with 'auto' detection
* or pass a custom timer object
*/
timerVariant?: TimerVariant
timerVariant?: TimerVariant | Timer
}

export interface IClientPublishOptions {
Expand Down
1 change: 1 addition & 0 deletions src/mqtt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export {
export * from './lib/client'
export * from './lib/shared'
export { ReasonCodes } from './lib/handlers/ack'
export type { Timer } from './lib/get-timer'
20 changes: 19 additions & 1 deletion test/keepaliveManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, it } from 'node:test'
import KeepaliveManager from '../src/lib/KeepaliveManager'
import { assert } from 'chai'
import { useFakeTimers, spy, mock } from 'sinon'
import { useFakeTimers, spy, stub } from 'sinon'
import { MqttClient } from 'src'

function mockedClient(keepalive: number) {
Expand Down Expand Up @@ -105,4 +105,22 @@ describe('KeepaliveManager', () => {
assert.equal(manager.keepalive, 10000)
assert.equal(manager.intervalEvery, 5000)
})

it('should use provided Timer object', () => {
const keepalive = 10 // seconds
const customTimer = {
set: stub().returns(123),
clear: stub(),
}
const manager = new KeepaliveManager(
mockedClient(keepalive),
customTimer,
)
assert.equal(manager['timer'], customTimer)
assert.equal(customTimer.set.callCount, 1)
assert.equal(manager['timerId'], 123)

manager.destroy()
assert.equal(customTimer.clear.called, true)
})
})

0 comments on commit ee81184

Please sign in to comment.