Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readding socket.io mongodb adapter #9955

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 52 additions & 2 deletions .github/workflows/test.yaml
Expand Up @@ -22,7 +22,7 @@ jobs:
matrix:
os: [ubuntu-latest]
node: [12, 14, 16]
database: [mongo-dev, mongo, redis, postgres]
database: [mongo-dev, mongo, rs-mongo, redis, postgres]
include:
# only run coverage once
- os: ubuntu-latest
Expand Down Expand Up @@ -70,10 +70,32 @@ jobs:

mongo:
image: 'mongo:3.2'
options: >-
--health-cmd "mongo --quiet 'localhost/test' --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
# Maps port 27017 on service container to the host
- 27017:27017

mongo-rs:
image: 'bitnami/mongodb:5.0'
ports:
# Maps port 27017 on service container to port 27018 of the host
- 27018:27017
options: >-
--health-cmd "mongo -u healthcheck -p healthcheck --quiet 'localhost/test' --eval 'quit(db.runCommand({ ping: 1 }).ok ? 0 : 2)'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
MONGODB_REPLICA_SET_MODE: primary
MONGODB_REPLICA_SET_KEY: nodebb
MONGODB_ROOT_PASSWORD: nodebb
MONGODB_EXTRA_USERNAMES: nodebb,ci_test,healthcheck
MONGODB_EXTRA_PASSWORDS: nodebb,nodebb,healthcheck
MONGODB_EXTRA_DATABASES: nodebb,ci_test,test

steps:
- uses: actions/checkout@v2

Expand Down Expand Up @@ -116,7 +138,35 @@ jobs:
}
run: |
node app --setup="${SETUP}" --ci="${CI}"
- name: Setup on MongoDB Replica Set
if: startsWith(matrix.database, 'rs-mongo')
env:
SETUP: >-
{
"url": "http://127.0.0.1:4567",
"secret": "abcdef",
"admin:username": "admin",
"admin:email": "test@example.org",
"admin:password": "hAN3Eg8W",
"admin:password:confirm": "hAN3Eg8W",

"database": "mongo",
"mongo:host": "127.0.0.1",
"mongo:port": 27018,
"mongo:username": "nodebb",
"mongo:password": "nodebb",
"mongo:database": "nodebb"
}
CI: >-
{
"host": "127.0.0.1",
"port": 27018,
"database": "ci_test",
"username": "ci_test",
"password": "nodebb"
}
run: |
node app --setup="${SETUP}" --ci="${CI}"
- name: Setup on PostgreSQL
if: startsWith(matrix.database, 'postgres')
env:
Expand Down
2 changes: 2 additions & 0 deletions install/package.json
Expand Up @@ -81,6 +81,7 @@
"mongodb": "4.1.4",
"morgan": "^1.10.0",
"mousetrap": "^1.6.5",
"@nodebb/mubsub": "^1.8.0",
"multiparty": "4.2.2",
"@nodebb/bootswatch": "3.4.2",
"nconf": "^0.11.2",
Expand Down Expand Up @@ -123,6 +124,7 @@
"socket.io-adapter-cluster": "^1.0.1",
"socket.io-client": "4.3.2",
"@socket.io/redis-adapter": "7.0.0",
"@socket.io/mongo-adapter": "0.1.0",
"sortablejs": "1.14.0",
"spdx-license-list": "^6.4.0",
"spider-detector": "2.0.0",
Expand Down
34 changes: 34 additions & 0 deletions src/database/mongo.js
Expand Up @@ -178,6 +178,40 @@ mongoModule.close = function (callback) {
client.close(err => callback(err));
};

mongoModule.socketAdapter = async function () {
const { createAdapter } = require('@socket.io/mongo-adapter');
if (client.topology.description.type === 'Single' || !client.topology.hasSessionSupport()) {
winston.warn('clustering with MongoDB is only supported on replica sets (in MongoDB versions >=3.6)');
return;
}
try {
await mongoModule.client.createCollection('socket.io-events', {
capped: true,
size: 1e6,
});
} catch (err) {
// catch only NamespaceExists error that is thrown if the collection already exists
if (err.codeName === 'NamespaceExists') {
// ensure the collection is capped
if (!await mongoModule.client.collection('socket.io-events').isCapped()) {
/* in mongo shell you'd run the `convertToCapped` command, but `runCommand` is not implemented in node driver.
Luckily since it's just a temporary store for pub/sub, there is no need to implement the most complex part,
that is saving the data and moving it to the new capped collection.
As such just recreating the collection is good enough here */
await mongoModule.client.collection('socket.io-events').drop();
await mongoModule.client.createCollection('socket.io-events', {
capped: true,
size: 1e6,
});
}
} else {
winston.error(err.stack);
}
}
const socketCollection = mongoModule.client.collection('socket.io-events');
return createAdapter(socketCollection);
};

require('./mongo/main')(mongoModule);
require('./mongo/hash')(mongoModule);
require('./mongo/sets')(mongoModule);
Expand Down
11 changes: 11 additions & 0 deletions src/database/mongo/pubsub.js
@@ -0,0 +1,11 @@
'use strict';


const mubsub = require('@nodebb/mubsub');
const connection = require('./connection');

const client = mubsub(connection.getConnectionString(), connection.getConnectionOptions());
client.on('error', err => console.error(err));
const channel = client.channel('pubsub');
channel.on('error', err => console.error(err));
module.exports = channel;
2 changes: 2 additions & 0 deletions src/pubsub.js
Expand Up @@ -47,6 +47,8 @@ function get() {
pubsub = singleHost;
} else if (nconf.get('redis')) {
pubsub = require('./database/redis/pubsub');
} else if (nconf.get('mongo')) {
pubsub = require('./database/mongo/pubsub');
} else {
throw new Error('[[error:redis-required-for-pubsub]]');
}
Expand Down
7 changes: 6 additions & 1 deletion src/socket.io/index.js
Expand Up @@ -29,8 +29,13 @@ Sockets.init = async function (server) {
if (nconf.get('redis')) {
const adapter = await require('../database/redis').socketAdapter();
io.adapter(adapter);
} else if (nconf.get('mongo')) {
const adapter = await require('../database/mongo').socketAdapter();
if (adapter) {
io.adapter(adapter);
}
} else {
winston.warn('clustering detected, you should setup redis!');
winston.warn('clustering detected, you should setup redis or a MongoDB replica set!');
}
}

Expand Down