diff --git a/.codeclimate.yml b/.codeclimate.yml
index 30106f6..d657c7a 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -1,9 +1,9 @@
engines:
eslint:
enabled: true
- channel: "eslint-8"
+ channel: 'eslint-8'
config:
- config: ".eslintrc.yaml"
+ config: '.eslintrc.yaml'
checks:
method-complexity:
@@ -11,5 +11,5 @@ checks:
threshold: 10
ratings:
- paths:
- - "**.js"
+ paths:
+ - '**.js'
diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index b10c53f..035a400 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -2,19 +2,6 @@ env:
node: true
es6: true
mocha: true
- es2020: true
+ es2022: true
-plugins: [ haraka ]
-
-extends: [ eslint:recommended, plugin:haraka/recommended ]
-
-root: true
-
-globals:
- OK: true
- CONT: true
- DENY: true
- DENYSOFT: true
- DENYDISCONNECT: true
- DENYSOFTDISCONNECT: true
- connection: true
+extends: ['@haraka']
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index afafec5..bd8fb43 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,10 +1,12 @@
Fixes #
Changes proposed in this pull request:
--
--
+
+-
+-
Checklist:
+
- [ ] docs updated
- [ ] tests updated
- [ ] Changes.md updated
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 94be697..a067f44 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,41 +1,22 @@
name: CI
-on: [ push, pull_request ]
+on: [push, pull_request]
env:
CI: true
- node-version: 16
jobs:
-
lint:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
- name: Node ${{ env.node-version }}
- with:
- node-version: ${{ env.node-version }}
- - run: npm install
- - run: npm run lint
+ uses: haraka/.github/.github/workflows/lint.yml@master
+
+ # coverage:
+ # uses: haraka/.github/.github/workflows/coverage.yml@master
+ # secrets: inherit
test:
- runs-on: ${{ matrix.os }}
- services:
- redis:
- image: redis
- ports:
- - 6379:6379
- strategy:
- matrix:
- os: [ ubuntu-latest ]
- node-version: [ 14, 16, 18 ]
- fail-fast: false
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-node@v3
- name: Node ${{ matrix.node-version }} on ${{ matrix.os }}
- with:
- node-version: ${{ matrix.node-version }}
- - run: npm install
- - run: npm run test
+ needs: [lint]
+ uses: haraka/.github/.github/workflows/ubuntu.yml@master
+
+ # windows:
+ # needs: [lint]
+ # uses: haraka/.github/.github/workflows/windows.yml@master
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 3627451..8314a66 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -2,10 +2,10 @@ name: CodeQL
on:
push:
- branches: [ master ]
+ branches: [master]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ master ]
+ branches: [master]
schedule:
- cron: '18 7 * * 4'
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index d489fbd..e81c15f 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -13,4 +13,4 @@ env:
jobs:
publish:
uses: haraka/.github/.github/workflows/publish.yml@master
- secrets: inherit
\ No newline at end of file
+ secrets: inherit
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index 3e8e260..0000000
--- a/.npmignore
+++ /dev/null
@@ -1,58 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules
-jspm_packages
-
-# Optional npm cache directory
-.npm
-
-# Optional REPL history
-.node_repl_history
-
-package-lock.json
-bower_components
-# Optional npm cache directory
-.npmrc
-.idea
-.DS_Store
-haraka-update.sh
-
-.github
-.release
-.codeclimate.yml
-.editorconfig
-.gitignore
-.gitmodules
-.lgtm.yml
-appveyor.yml
-codecov.yml
-.travis.yml
-.eslintrc.yaml
-.eslintrc.json
diff --git a/.prettierrc.yml b/.prettierrc.yml
new file mode 100644
index 0000000..8ded5e0
--- /dev/null
+++ b/.prettierrc.yml
@@ -0,0 +1,2 @@
+singleQuote: true
+semi: false
diff --git a/.release b/.release
index 0890e94..36bb27a 160000
--- a/.release
+++ b/.release
@@ -1 +1 @@
-Subproject commit 0890e945e4e061c96c7b2ab45017525904c17728
+Subproject commit 36bb27a93862517943e04f24fd67b0df2da6cbbe
diff --git a/Changes.md b/CHANGELOG.md
similarity index 64%
rename from Changes.md
rename to CHANGELOG.md
index c8eb9c3..4ed4ab6 100644
--- a/Changes.md
+++ b/CHANGELOG.md
@@ -1,17 +1,27 @@
+# Changelog
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/).
### Unreleased
+### [2.0.7] - 2024-04-21
+
+- populate [files] in package.json. Delete .npmignore.
+- lint: remove duplicate / stale rules from .eslintrc
+- ci: update to shared GHA workflows
+- doc(CONTRIBUTORS): added
+- doc: Changes -> CHANGELOG
+- prettier
### [2.0.6] - 2023-12-12
- doc(README): '[socket]' is now '[server]' (#39)
- chore(ci): add .release, updated dot files
-
### 2.0.5 - 2022-05-26
- fix: backwards compatibility with legacy plugin config files
-- fix: rename p\* methods -> * (required in redis v4)
+- fix: rename p\* methods -> \* (required in redis v4)
- fix: add `await client.connect()` as is now required, fixes #32
- fix: make redis_ping async
- dep(redis): bump 4.0 -> 4.1
@@ -19,33 +29,28 @@
- chore(ci): added codeql config
- test: added tests for init_redis_plugin
-
### 2.0.0 - 2022-03-29
- dep(redis): bump major version 3 -> 4
- breaking API change: replaced callbacks with promises
- config.ini
- - opts.db -> opts.database (to match upstream)
-
+ - opts.db -> opts.database (to match upstream)
### 1.0.13 - 2021-10-14
- chore(ci): switch CI from Travis to GitHub Actions
- doc(README): update formatting with GFM
-
### 1.0.12 - 2020-03-16
- chore(ci): replace nodeunit with mocha
- dep(redis): update lib to v3
- appveyor: test on node 10
-
### 1.0.11 - 2019-04-11
- create custom connection only after: all 3 conditions match
-
### 1.0.10 - 2019-04-09
- merge ALL of [opts] into [server] config (fixes #18)
@@ -53,7 +58,6 @@
- include an empty config/redis.ini
- add defaultOpts once, vs defaults in two places
-
### 1.0.9 - 2019-02-19
- bump redis version to 2.8.0
@@ -61,34 +65,36 @@
- add 3s timeout for subscribe connects: minimize connections stalls
- add es6 template literals
-
### 1.0.8 - 2018-01-03
- upon punsubscribe, `quit()` (disconnect) redis client
-
### 1.0.7 - 2017-07-31
- apply config [opts] to pubsub settings #7
-
### 1.0.6 - 2017-06-16
- eslint 4 compat
-
### 1.0.5 - 2017-06-09
- disconnect per-connection redis client upon punsubscribe
-
### 1.0.4 - 2017-02-06
- remove retry_strategy, redis client now does The Right Thing w/o it
-
### 1.0.3 - 2017-02-06
- don't break when no [redis] config exists
-[2.0.6]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.6
+[1.0.13]: https://github.com/haraka/haraka-plugin-redis/releases/tag/1.0.13
+[2.0.0]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.0
+[2.0.1]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.1
+[2.0.2]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.2
+[2.0.3]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.3
+[2.0.4]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.4
+[2.0.5]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.5
+[2.0.6]: https://github.com/haraka/haraka-plugin-redis/releases/tag/v2.0.6
+[2.0.7]: https://github.com/haraka/haraka-plugin-redis/releases/tag/2.0.7
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 0000000..6e24629
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,8 @@
+# Contributors
+
+This handcrafted artisinal software is brought to you by:
+
+|
msimerson (57) |
zazapeta (1) |
+| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+
+this file is maintained by [.release](https://github.com/msimerson/.release)
diff --git a/README.md b/README.md
index 59b82ac..bfec36f 100644
--- a/README.md
+++ b/README.md
@@ -72,32 +72,31 @@ optionally with a redis db ID. All redis config options must be listed in your p
```js
exports.register = function () {
- this.inherits('redis');
+ this.inherits('redis')
- this.cfg = this.config.get('my-plugin.ini');
+ this.cfg = this.config.get('my-plugin.ini')
- // populate plugin.cfg.redis with defaults from redis.ini
- this.merge_redis_ini();
+ // populate plugin.cfg.redis with defaults from redis.ini
+ this.merge_redis_ini()
- // cluster aware redis connection(s)
- this.register_hook('init_master', 'init_redis_plugin');
- this.register_hook('init_child', 'init_redis_plugin');
+ // cluster aware redis connection(s)
+ this.register_hook('init_master', 'init_redis_plugin')
+ this.register_hook('init_child', 'init_redis_plugin')
}
```
When a db ID is specified in the [redis] section of a redis inheriting plugin, log messages like these will be emitted when Haraka starts:
-````
+```
[INFO] [-] [redis] connected to redis://172.16.15.16:6379 v3.2.6
[INFO] [-] [limit] connected to redis://172.16.15.16:6379/1 v3.2.6
[INFO] [-] [karma] connected to redis://172.16.15.16:6379/2 v3.2.6
[INFO] [-] [known-senders] connected to redis://172.16.15.16:6379/3 v3.2.6
-````
+```
Notice the database ID numbers appended to each plugins redis connection
message.
-
[ci-img]: https://github.com/haraka/haraka-plugin-redis/actions/workflows/ci.yml/badge.svg
[ci-url]: https://github.com/haraka/haraka-plugin-redis/actions/workflows/ci.yml
[clim-img]: https://codeclimate.com/github/haraka/haraka-plugin-redis/badges/gpa.svg
diff --git a/index.js b/index.js
index 25efa01..8021aa8 100644
--- a/index.js
+++ b/index.js
@@ -1,251 +1,256 @@
-'use strict';
+'use strict'
/* global server */
-const redis = require('redis');
+const redis = require('redis')
exports.register = function () {
- this.load_redis_ini();
+ this.load_redis_ini()
- // another plugin has called us with: inherits('haraka-plugin-redis')
- if (this.name !== 'redis') return;
+ // another plugin has called us with: inherits('haraka-plugin-redis')
+ if (this.name !== 'redis') return
- // register when 'redis' is declared in config/plugins
- this.register_hook('init_master', 'init_redis_shared');
- this.register_hook('init_child', 'init_redis_shared');
+ // register when 'redis' is declared in config/plugins
+ this.register_hook('init_master', 'init_redis_shared')
+ this.register_hook('init_child', 'init_redis_shared')
}
const defaultOpts = { socket: { host: '127.0.0.1', port: '6379' } }
-const socketOpts = [ 'host', 'port', 'path', 'tls', 'connectTimeout', 'noDelay', 'keepAlive', 'reconnectStrategy' ]
+const socketOpts = [
+ 'host',
+ 'port',
+ 'path',
+ 'tls',
+ 'connectTimeout',
+ 'noDelay',
+ 'keepAlive',
+ 'reconnectStrategy',
+]
exports.load_redis_ini = function () {
- const plugin = this;
-
- // store redis cfg at redisCfg, to avoid conflicting with plugins that
- // inherit this plugin and have *their* config at plugin.cfg
- plugin.redisCfg = plugin.config.get('redis.ini', function () {
- plugin.load_redis_ini();
- });
-
- // backwards compat
- if (plugin.redisCfg?.server?.ip && !plugin.redisCfg?.server?.host) {
- plugin.redisCfg.server.host = plugin.redisCfg.server.ip
- delete plugin.redisCfg.server.ip
- }
- if (plugin.redisCfg.db && !plugin.redisCfg.database) {
- plugin.redisCfg.database = plugin.redisCfg.db
- delete plugin.redisCfg.db
- }
-
- plugin.redisCfg.server = Object.assign({}, defaultOpts, plugin.redisCfg.opts, plugin.redisCfg.server);
- plugin.redisCfg.pubsub = Object.assign({}, defaultOpts, plugin.redisCfg.opts, plugin.redisCfg.pubsub);
-
- // socket options. In redis < 4, the options like host and port were
- // top level, now they're in socket.*. Permit legacy configs to still work
- for (const s of [ 'server', 'pubsub' ]) {
- for (const o of socketOpts) {
- if (plugin.redisCfg[s][o]) plugin.redisCfg[s].socket[o] = plugin.redisCfg[s][o]
- delete plugin.redisCfg[s][o]
- }
+ const plugin = this
+
+ // store redis cfg at redisCfg, to avoid conflicting with plugins that
+ // inherit this plugin and have *their* config at plugin.cfg
+ plugin.redisCfg = plugin.config.get('redis.ini', () => {
+ plugin.load_redis_ini()
+ })
+
+ // backwards compat
+ if (plugin.redisCfg?.server?.ip && !plugin.redisCfg?.server?.host) {
+ plugin.redisCfg.server.host = plugin.redisCfg.server.ip
+ delete plugin.redisCfg.server.ip
+ }
+ if (plugin.redisCfg.db && !plugin.redisCfg.database) {
+ plugin.redisCfg.database = plugin.redisCfg.db
+ delete plugin.redisCfg.db
+ }
+
+ plugin.redisCfg.server =
+ { ...defaultOpts, ...plugin.redisCfg.opts, ...plugin.redisCfg.server };
+ plugin.redisCfg.pubsub =
+ { ...defaultOpts, ...plugin.redisCfg.opts, ...plugin.redisCfg.pubsub };
+
+ // socket options. In redis < 4, the options like host and port were
+ // top level, now they're in socket.*. Permit legacy configs to still work
+ for (const s of ['server', 'pubsub']) {
+ for (const o of socketOpts) {
+ if (plugin.redisCfg[s][o])
+ plugin.redisCfg[s].socket[o] = plugin.redisCfg[s][o]
+ delete plugin.redisCfg[s][o]
}
+ }
}
exports.merge_redis_ini = function () {
-
- if (!this.cfg) this.cfg = {}; // no .ini loaded?
- if (!this.cfg.redis) this.cfg.redis = {}; // no [redis] in .ini file
- if (!this.redisCfg) this.load_redis_ini();
-
- this.cfg.redis = Object.assign({}, this.redisCfg.server, this.cfg.redis);
-
- // backwards compatibility
- for (const o of socketOpts) {
- if (this.cfg.redis[o] === undefined) continue
- this.cfg.redis.socket[o] = this.cfg.redis[o]
- delete this.cfg.redis[o]
- }
- if (this.cfg.redis.db && !this.cfg.redis.database) {
- this.cfg.redis.database = this.cfg.redis.db
- delete this.cfg.redis.db
- }
+ if (!this.cfg) this.cfg = {} // no .ini loaded?
+ if (!this.cfg.redis) this.cfg.redis = {} // no [redis] in .ini file
+ if (!this.redisCfg) this.load_redis_ini()
+
+ this.cfg.redis = Object.assign({}, this.redisCfg.server, this.cfg.redis)
+
+ // backwards compatibility
+ for (const o of socketOpts) {
+ if (this.cfg.redis[o] === undefined) continue
+ this.cfg.redis.socket[o] = this.cfg.redis[o]
+ delete this.cfg.redis[o]
+ }
+ if (this.cfg.redis.db && !this.cfg.redis.database) {
+ this.cfg.redis.database = this.cfg.redis.db
+ delete this.cfg.redis.db
+ }
}
exports.init_redis_shared = function (next, server) {
+ let calledNext = false
+ function nextOnce(e) {
+ if (e) this.logerror(`Redis error: ${e.message}`)
+ if (calledNext) return
+ calledNext = true
+ next()
+ }
+
+ // this is the server-wide redis, shared by plugins that don't
+ // specify a db ID.
+ if (!server.notes.redis) {
+ this.get_redis_client(this.redisCfg.server).then((client) => {
+ server.notes.redis = client
+ nextOnce()
+ })
+ return
+ }
- let calledNext = false;
- function nextOnce (e) {
- if (e) this.logerror(`Redis error: ${e.message}`);
- if (calledNext) return;
- calledNext = true;
- next();
- }
-
- // this is the server-wide redis, shared by plugins that don't
- // specificy a db ID.
- if (!server.notes.redis) {
- this.get_redis_client(this.redisCfg.server).then(client => {
- server.notes.redis = client
- nextOnce()
- })
- return
- }
-
- server.notes.redis.ping((err, res) => {
- if (err) return nextOnce(err);
+ server.notes.redis.ping((err) => {
+ if (err) return nextOnce(err)
- this.loginfo('already connected');
- nextOnce(); // connection is good
- });
+ this.loginfo('already connected')
+ nextOnce() // connection is good
+ })
}
exports.init_redis_plugin = function (next, server) {
- const plugin = this;
-
- // this function is called by plugins at init_*, to establish their
- // shared or unique redis db handle.
-
- let calledNext=false;
- function nextOnce () {
- if (calledNext) return;
- calledNext = true;
- next();
+ const plugin = this
+
+ // this function is called by plugins at init_*, to establish their
+ // shared or unique redis db handle.
+
+ let calledNext = false
+ function nextOnce() {
+ if (calledNext) return
+ calledNext = true
+ next()
+ }
+
+ // for tests that do not load a shared config
+ if (!plugin.cfg) {
+ plugin.cfg = { redis: {} }
+ if (plugin.redisCfg)
+ plugin.cfg.redis = JSON.parse(JSON.stringify(plugin.redisCfg))
+ }
+ if (!server) server = { notes: {} }
+
+ const pidb = plugin.cfg.redis.database
+ if (server.notes.redis) {
+ // server-wide redis is available
+ // and the DB not specified or is the same as server-wide
+ if (pidb === undefined || pidb === plugin.redisCfg.db) {
+ server.loginfo(plugin, 'using server.notes.redis')
+ plugin.db = server.notes.redis
+ nextOnce()
+ return
}
+ }
- // for tests that do not load a shared config
- if (!plugin.cfg) {
- plugin.cfg = { redis: {} };
- if (plugin.redisCfg) plugin.cfg.redis = JSON.parse(JSON.stringify(plugin.redisCfg))
- }
- if (!server) server = { notes: {} };
-
- const pidb = plugin.cfg.redis.database;
- if (server.notes.redis) { // server-wide redis is available
- // and the DB not specified or is the same as server-wide
- if (pidb === undefined || pidb === plugin.redisCfg.db) {
- server.loginfo(plugin, 'using server.notes.redis');
- plugin.db = server.notes.redis;
- nextOnce();
- return;
- }
- }
-
- plugin.get_redis_client(plugin.cfg.redis).then(client => {
- plugin.db = client
- nextOnce()
- })
+ plugin.get_redis_client(plugin.cfg.redis).then((client) => {
+ plugin.db = client
+ nextOnce()
+ })
}
exports.shutdown = function () {
- if (this.db) this.db.quit();
+ if (this.db) this.db.quit()
- if (server && server.notes && server.notes.redis) {
- server.notes.redis.quit();
- }
+ if (server && server.notes && server.notes.redis) {
+ server.notes.redis.quit()
+ }
}
exports.redis_ping = async function () {
+ this.redis_pings = false
+ if (!this.db) throw new Error('redis not initialized')
- this.redis_pings=false;
- if (!this.db) throw new Error('redis not initialized');
-
- const r = await this.db.ping()
- if (r !== 'PONG') throw new Error('not PONG');
- this.redis_pings=true
+ const r = await this.db.ping()
+ if (r !== 'PONG') throw new Error('not PONG')
+ this.redis_pings = true
- return true
+ return true
}
-function getUriStr (client, opts) {
- let msg = `redis://${opts?.socket?.host}:${opts?.socket?.port}`;
- if (opts?.database) msg += `/${opts?.database}`;
- if (client?.server_info?.redis_version) {
- msg += `\tv${client?.server_info?.redis_version}`;
- }
- return msg;
+function getUriStr(client, opts) {
+ let msg = `redis://${opts?.socket?.host}:${opts?.socket?.port}`
+ if (opts?.database) msg += `/${opts?.database}`
+ if (client?.server_info?.redis_version) {
+ msg += `\tv${client?.server_info?.redis_version}`
+ }
+ return msg
}
exports.get_redis_client = async function (opts) {
+ const client = redis.createClient(opts)
- const client = redis.createClient(opts)
-
- let urlStr
+ let urlStr
- client
- .on('error', (err) => {
- this.logerror(err.message);
- })
- .on('end', () => {
- this.loginfo(`Disconnected from ${urlStr}`);
- })
+ client
+ .on('error', (err) => {
+ this.logerror(err.message)
+ })
+ .on('end', () => {
+ this.loginfo(`Disconnected from ${urlStr}`)
+ })
- try {
- await client.connect()
+ try {
+ await client.connect()
- if (opts?.database) client.dbid = opts?.database
+ if (opts?.database) client.dbid = opts?.database
- client.server_info = await client.info()
- urlStr = getUriStr(client, opts)
- this.loginfo(`connected to ${urlStr}`);
+ client.server_info = await client.info()
+ urlStr = getUriStr(client, opts)
+ this.loginfo(`connected to ${urlStr}`)
- return client
- }
- catch (e) {
- console.error(e)
- this.logerror(e);
- }
+ return client
+ } catch (e) {
+ console.error(e)
+ this.logerror(e)
+ }
}
-
exports.get_redis_pub_channel = function (conn) {
- return `result-${conn.transaction ? conn.transaction.uuid : conn.uuid}`;
+ return `result-${conn.transaction ? conn.transaction.uuid : conn.uuid}`
}
exports.get_redis_sub_channel = function (conn) {
- return `result-${conn.uuid}*`;
+ return `result-${conn.uuid}*`
}
// formerly used by pi-watch
exports.redis_subscribe_pattern = async function (pattern, onMessage) {
+ if (this.redis) return // already subscribed?
- if (this.redis) return // already subscribed?
+ this.redis = redis.createClient(this.redisCfg.pubsub)
+ await this.redis.connect()
- this.redis = redis.createClient(this.redisCfg.pubsub)
- await this.redis.connect()
-
- await this.redis.pSubscribe(pattern, onMessage);
- this.logdebug(this, `pSubscribed to ${pattern}`);
+ await this.redis.pSubscribe(pattern, onMessage)
+ this.logdebug(this, `pSubscribed to ${pattern}`)
}
// the next two functions are use by pi-karma
exports.redis_subscribe = async function (connection, onMessage) {
+ if (connection.notes.redis) {
+ connection.logdebug(this, `redis already subscribed`)
+ return // another plugin has already called this.
+ }
- if (connection.notes.redis) {
- connection.logdebug(this, `redis already subscribed`);
- return; // another plugin has already called this.
- }
+ const timer = setTimeout(() => {
+ connection.logerror('redis subscribe timed out')
+ }, 3 * 1000)
- const timer = setTimeout(() => {
- connection.logerror('redis subscribe timed out');
- }, 3 * 1000);
+ connection.notes.redis = redis.createClient(this.redisCfg.pubsub)
+ await connection.notes.redis.connect()
- connection.notes.redis = redis.createClient(this.redisCfg.pubsub)
- await connection.notes.redis.connect()
+ clearTimeout(timer)
- clearTimeout(timer);
-
- const pattern = this.get_redis_sub_channel(connection)
- connection.notes.redis.pSubscribe(pattern, onMessage);
- connection.logdebug(this, `pSubscribed to ${pattern}`);
+ const pattern = this.get_redis_sub_channel(connection)
+ connection.notes.redis.pSubscribe(pattern, onMessage)
+ connection.logdebug(this, `pSubscribed to ${pattern}`)
}
exports.redis_unsubscribe = async function (connection) {
-
- if (!connection.notes.redis) {
- connection.logerror(this, `redis_unsubscribe called when no redis`)
- return;
- }
-
- const pattern = this.get_redis_sub_channel(connection)
- await connection.notes.redis.unsubscribe(pattern);
- connection.logdebug(this, `unsubsubscribed from ${pattern}`);
- connection.notes.redis.quit();
+ if (!connection.notes.redis) {
+ connection.logerror(this, `redis_unsubscribe called when no redis`)
+ return
+ }
+
+ const pattern = this.get_redis_sub_channel(connection)
+ await connection.notes.redis.unsubscribe(pattern)
+ connection.logdebug(this, `unsubsubscribed from ${pattern}`)
+ connection.notes.redis.quit()
}
diff --git a/package.json b/package.json
index be2e86f..4eaa9dc 100644
--- a/package.json
+++ b/package.json
@@ -1,26 +1,30 @@
{
"name": "haraka-plugin-redis",
- "version": "2.0.6",
+ "version": "2.0.7",
"description": "Redis plugin for Haraka & other plugins to inherit from",
"main": "index.js",
+ "files": [
+ "config"
+ ],
"directories": {
"test": "test"
},
"dependencies": {
- "redis": "4"
+ "redis": "^4.6.0"
},
"devDependencies": {
- "eslint": "8",
- "eslint-plugin-haraka": "*",
- "haraka-test-fixtures": "*",
- "mocha": "9"
+ "@haraka/eslint-config": "^1.1.3",
+ "haraka-test-fixtures": "1.3.7"
},
"scripts": {
- "lint": "npx eslint *.js test",
- "lintfix": "npx eslint --fix *.js test",
- "cover": "NODE_ENV=cov npx nyc --reporter=lcovonly npm run test",
+ "format": "npm run prettier:fix && npm run lint:fix",
+ "lint": "npx eslint@^8 *.js test",
+ "lint:fix": "npx eslint@^8 *.js test --fix",
+ "prettier": "npx prettier . --check",
+ "prettier:fix": "npx prettier . --write --log-level=warn",
+ "test": "npx mocha@10",
"versions": "npx dependency-version-checker check",
- "test": "npx mocha"
+ "versions:fix": "npx dependency-version-checker update && npm run prettier:fix"
},
"repository": {
"type": "git",
@@ -28,6 +32,7 @@
},
"keywords": [
"haraka",
+ "haraka-plugin",
"mail",
"smtp",
"redis"
diff --git a/test/redis.js b/test/redis.js
index 3d1f97a..e6cbb4a 100644
--- a/test/redis.js
+++ b/test/redis.js
@@ -1,138 +1,141 @@
-'use strict';
+'use strict'
const assert = require('assert')
-const path = require('path')
+const path = require('path')
const fixtures = require('haraka-test-fixtures')
-function retry (options) {
- if (options.error) {
- console.error(options.error);
- }
- return undefined;
+function retry(options) {
+ if (options.error) {
+ console.error(options.error)
+ }
+ return undefined
}
describe('config', function () {
- before(async function () {
- this.plugin = new fixtures.plugin('index')
- this.plugin.config = this.plugin.config.module_config(path.resolve('test'));
+ before(async function () {
+ this.plugin = new fixtures.plugin('index')
+ this.plugin.config = this.plugin.config.module_config(path.resolve('test'))
+ })
+
+ it('loads', async function () {
+ assert.equal(this.plugin.name, 'index')
+ })
+
+ it('config defaults', async function () {
+ this.plugin.load_redis_ini()
+ assert.equal(this.plugin.redisCfg.server.socket.host, '127.0.0.1')
+ assert.equal(this.plugin.redisCfg.server.socket.port, 6379)
+ })
+
+ it('merges [opts] into server config', async function () {
+ this.plugin.load_redis_ini()
+ assert.deepEqual(this.plugin.redisCfg, {
+ main: {},
+ pubsub: {
+ socket: {
+ host: '127.0.0.1',
+ port: '6379',
+ },
+ database: 5,
+ password: 'dontUseThisOne',
+ },
+ opts: { database: 5, password: 'dontUseThisOne' },
+ server: {
+ socket: {
+ host: '127.0.0.1',
+ port: '6379',
+ },
+ database: 5,
+ password: 'dontUseThisOne',
+ },
})
-
- it('loads', async function () {
- assert.equal(this.plugin.name, 'index');
- })
-
- it('config defaults', async function () {
- this.plugin.load_redis_ini();
- assert.equal(this.plugin.redisCfg.server.socket.host, '127.0.0.1')
- assert.equal(this.plugin.redisCfg.server.socket.port, 6379)
- })
-
- it('merges [opts] into server config', async function () {
- this.plugin.load_redis_ini();
- assert.deepEqual(this.plugin.redisCfg, {
- main: {},
- pubsub: {
- socket: {
- host: '127.0.0.1',
- port: '6379',
- },
- database: 5,
- password: 'dontUseThisOne'
- },
- opts: { database: 5, password: 'dontUseThisOne' },
- server: {
- socket: {
- host: '127.0.0.1',
- port: '6379',
- },
- database: 5,
- password: 'dontUseThisOne'
- }
- });
- })
-
- it('merges redis.ini [opts] into plugin config', async function () {
- this.plugin.load_redis_ini();
- this.plugin.cfg = {};
- this.plugin.merge_redis_ini();
- assert.deepEqual(this.plugin.cfg.redis, {
- socket: {
- host: '127.0.0.1',
- port: '6379',
- },
- database: 5,
- password: 'dontUseThisOne'
- })
+ })
+
+ it('merges redis.ini [opts] into plugin config', async function () {
+ this.plugin.load_redis_ini()
+ this.plugin.cfg = {}
+ this.plugin.merge_redis_ini()
+ assert.deepEqual(this.plugin.cfg.redis, {
+ socket: {
+ host: '127.0.0.1',
+ port: '6379',
+ },
+ database: 5,
+ password: 'dontUseThisOne',
})
+ })
})
describe('connects', function () {
- before(async function () {
- this.plugin = new fixtures.plugin('index')
- this.plugin.register()
- })
-
- it('loads', async function () {
- assert.equal(this.plugin.name, 'index');
+ before(async function () {
+ this.plugin = new fixtures.plugin('index')
+ this.plugin.register()
+ })
+
+ it('loads', async function () {
+ assert.equal(this.plugin.name, 'index')
+ })
+
+ it('connects', async function () {
+ const redis = await this.plugin.get_redis_client({
+ socket: {
+ host: this.plugin.redisCfg.server.host,
+ port: this.plugin.redisCfg.server.port,
+ },
+ retry_strategy: retry,
})
-
- it('connects', async function () {
- const redis = await this.plugin.get_redis_client({
- socket: {
- host: this.plugin.redisCfg.server.host,
- port: this.plugin.redisCfg.server.port,
- },
- retry_strategy: retry,
- })
- assert.ok(redis);
- await redis.quit()
- })
-
- it('populates plugin.cfg.redis when asked', async function () {
- assert.equal(this.plugin.cfg, undefined);
- this.plugin.merge_redis_ini();
- assert.deepEqual(this.plugin.cfg.redis, { socket: { host: '127.0.0.1', port: '6379' } });
- })
-
- it('connects to a different redis db', async function () {
- this.plugin.merge_redis_ini();
- this.plugin.cfg.redis.database = 2;
- this.plugin.cfg.redis.retry_strategy = retry;
- const client = await this.plugin.get_redis_client(this.plugin.cfg.redis)
- const res = await client.ping()
- assert.equal(res, 'PONG')
- assert.ok(client)
- await client.quit()
+ assert.ok(redis)
+ await redis.quit()
+ })
+
+ it('populates plugin.cfg.redis when asked', async function () {
+ assert.equal(this.plugin.cfg, undefined)
+ this.plugin.merge_redis_ini()
+ assert.deepEqual(this.plugin.cfg.redis, {
+ socket: { host: '127.0.0.1', port: '6379' },
})
+ })
+
+ it('connects to a different redis db', async function () {
+ this.plugin.merge_redis_ini()
+ this.plugin.cfg.redis.database = 2
+ this.plugin.cfg.redis.retry_strategy = retry
+ const client = await this.plugin.get_redis_client(this.plugin.cfg.redis)
+ const res = await client.ping()
+ assert.equal(res, 'PONG')
+ assert.ok(client)
+ await client.quit()
+ })
})
describe('init_redis_plugin', function () {
- before(function () {
- this.server = { notes: { } }
-
- this.plugin = new fixtures.plugin('index')
- this.plugin.register()
- this.plugin.merge_redis_ini()
- })
-
- after(function () {
- this.plugin.db.quit()
- })
-
- it('connects to redis', function (done) {
- this.plugin.init_redis_plugin(() => {
- assert.ok(this.plugin.db?.server_info)
- done()
- }, this.server)
- })
-
- it('pings and gets PONG answer', function (done) {
- this.plugin.redis_ping()
- .then(r => {
- assert.equal(r, true)
- done()
- })
- .catch(done)
- })
-})
\ No newline at end of file
+ before(function () {
+ this.server = { notes: {} }
+
+ this.plugin = new fixtures.plugin('index')
+ this.plugin.register()
+ this.plugin.merge_redis_ini()
+ })
+
+ after(function () {
+ this.plugin.db.quit()
+ })
+
+ it('connects to redis', function (done) {
+ this.plugin.init_redis_plugin(() => {
+ assert.ok(this.plugin.db?.server_info)
+ done()
+ }, this.server)
+ })
+
+ it('pings and gets PONG answer', function (done) {
+ this.plugin
+ .redis_ping()
+ .then((r) => {
+ assert.equal(r, true)
+ done()
+ })
+ .catch(done)
+ })
+})