Skip to content

Commit

Permalink
[BREAK] Require OPLOG/REPLICASET to run Rocket.Chat
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigok committed Apr 24, 2019
1 parent 4419590 commit f03e616
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 155 deletions.
57 changes: 2 additions & 55 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,11 @@ test-save-npm-cache: &test-save-npm-cache
test-docker-image: &test-docker-image
circleci/node:8.11-stretch-browsers

test: &test
test-with-oplog: &test-with-oplog
<<: *defaults
environment: &test-environment
environment:
TEST_MODE: "true"
MONGO_URL: mongodb://localhost:27017/rocketchat


test-with-oplog: &test-with-oplog
<<: *test
environment:
<<: *test-environment
MONGO_OPLOG_URL: mongodb://localhost:27017/local

steps:
Expand All @@ -69,19 +63,6 @@ test-with-oplog: &test-with-oplog
- save_cache: *test-save-npm-cache
- store_artifacts: *test-store_artifacts

test-without-oplog: &test-without-oplog
<<: *test
steps:
- attach_workspace: *attach_workspace
- checkout
- run: *test-install-dependencies
- restore_cache: *test-restore-npm-cache
- run: *test-npm-install
- run: *test-run
- save_cache: *test-save-npm-cache
- store_artifacts: *test-store_artifacts


version: 2
jobs:
build:
Expand Down Expand Up @@ -248,32 +229,6 @@ jobs:
- image: mongo:4.0
command: [mongod, --noprealloc, --smallfiles, --replSet=rs0]


test-without-oplog-mongo-3-2:
<<: *test-without-oplog
docker:
- image: *test-docker-image
- image: mongo:3.2

test-without-oplog-mongo-3-4:
<<: *test-without-oplog
docker:
- image: *test-docker-image
- image: mongo:3.4

test-without-oplog-mongo-3-6:
<<: *test-without-oplog
docker:
- image: *test-docker-image
- image: mongo:3.6

test-without-oplog-mongo-4-0:
<<: *test-without-oplog
docker:
- image: *test-docker-image
- image: mongo:4.0


deploy:
<<: *defaults
docker:
Expand Down Expand Up @@ -449,20 +404,12 @@ workflows:
only: /^[0-9]+\.[0-9]+\.[0-9]+(?:-(?:rc|beta)\.[0-9]+)?$/
- test-with-oplog-mongo-3-6: *test-mongo-no-pr
- test-with-oplog-mongo-4-0: *test-mongo
- test-without-oplog-mongo-3-2: *test-mongo-no-pr
- test-without-oplog-mongo-3-4: *test-mongo-no-pr
- test-without-oplog-mongo-3-6: *test-mongo-no-pr
- test-without-oplog-mongo-4-0: *test-mongo-no-pr
- deploy:
requires:
- test-with-oplog-mongo-3-2
- test-with-oplog-mongo-3-4
- test-with-oplog-mongo-3-6
- test-with-oplog-mongo-4-0
- test-without-oplog-mongo-3-2
- test-without-oplog-mongo-3-4
- test-without-oplog-mongo-3-6
- test-without-oplog-mongo-4-0
filters:
branches:
only: develop
Expand Down
4 changes: 0 additions & 4 deletions app/lib/server/startup/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -811,10 +811,6 @@ settings.addGroup('General', function() {
type: 'string',
public: false,
});
this.add('Force_Disable_OpLog_For_Cache', false, {
type: 'boolean',
public: false,
});
this.add('Restart', 'restart_server', {
type: 'action',
actionText: 'Restart_the_server',
Expand Down
86 changes: 3 additions & 83 deletions app/models/server/models/_BaseDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Match } from 'meteor/check';
import { Mongo, MongoInternals } from 'meteor/mongo';
import _ from 'underscore';
import { EventEmitter } from 'events';
import { settings } from '../../../settings/server/functions/settings';

const baseName = 'rocketchat_';

Expand All @@ -14,8 +13,7 @@ try {
console.log(e);
}

const isOplogAvailable = MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle && !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry;
let isOplogEnabled = isOplogAvailable;
const isOplogEnabled = MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle && !!MongoInternals.defaultRemoteCollectionDriver().mongo._oplogHandle.onOplogEntry;

export class BaseDb extends EventEmitter {
constructor(model, baseModel) {
Expand All @@ -36,7 +34,6 @@ export class BaseDb extends EventEmitter {
this.wrapModel();

let alreadyListeningToOplog = false;
this.listenSettings();
// When someone start listening for changes we start oplog if available
this.on('newListener', (event/* , listener*/) => {
if (event === 'change' && alreadyListeningToOplog === false) {
Expand All @@ -58,12 +55,6 @@ export class BaseDb extends EventEmitter {
this.tryEnsureIndex({ _updatedAt: 1 });
}

listenSettings() {
settings.get('Force_Disable_OpLog_For_Cache', (key, value) => {
isOplogEnabled = isOplogAvailable && value === false;
});
}

get baseName() {
return baseName;
}
Expand Down Expand Up @@ -142,10 +133,6 @@ export class BaseDb extends EventEmitter {
}

processOplogRecord(action) {
if (isOplogEnabled === false) {
return;
}

if (action.op.op === 'i') {
this.emit('change', {
action: 'insert',
Expand Down Expand Up @@ -214,66 +201,13 @@ export class BaseDb extends EventEmitter {

record._id = result;

if (!isOplogEnabled && this.listenerCount('change') > 0) {
this.emit('change', {
action: 'insert',
clientAction: 'inserted',
id: result,
data: _.extend({}, record),
oplog: false,
});
}

return result;
}

update(query, update, options = {}) {
this.setUpdatedAt(update, true, query);

let ids = [];
if (!isOplogEnabled && this.listenerCount('change') > 0) {
const findOptions = { fields: { _id: 1 } };
let records = options.multi ? this.find(query, findOptions).fetch() : this.findOne(query, findOptions) || [];
if (!Array.isArray(records)) {
records = [records];
}

ids = records.map((item) => item._id);
if (options.upsert !== true && this.updateHasPositionalOperator(update) === false) {
query = {
_id: {
$in: ids,
},
};
}
}

// TODO: CACHE: Can we use findAndModify here when oplog is disabled?
const result = this.originals.update(query, update, options);

if (!isOplogEnabled && this.listenerCount('change') > 0) {
if (options.upsert === true && result.insertedId) {
this.emit('change', {
action: 'insert',
clientAction: 'inserted',
id: result.insertedId,
oplog: false,
});

return result;
}

for (const id of ids) {
this.emit('change', {
action: 'update',
clientAction: 'updated',
id,
oplog: false,
});
}
}

return result;
return this.originals.update(query, update, options);
}

upsert(query, update, options = {}) {
Expand All @@ -297,21 +231,7 @@ export class BaseDb extends EventEmitter {

query = { _id: { $in: ids } };

const result = this.originals.remove(query);

if (!isOplogEnabled && this.listenerCount('change') > 0) {
for (const record of records) {
this.emit('change', {
action: 'remove',
clientAction: 'removed',
id: record._id,
data: _.extend({}, record),
oplog: false,
});
}
}

return result;
return this.originals.remove(query);
}

insertOrUpsert(...args) {
Expand Down
2 changes: 1 addition & 1 deletion app/statistics/server/functions/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ statistics.get = function _getStatistics() {

const { mongo } = MongoInternals.defaultRemoteCollectionDriver();

if (mongo._oplogHandle && mongo._oplogHandle.onOplogEntry && settings.get('Force_Disable_OpLog_For_Cache') !== true) {
if (mongo._oplogHandle && mongo._oplogHandle.onOplogEntry) {
statistics.oplogEnabled = true;
}

Expand Down
3 changes: 1 addition & 2 deletions app/version-check/server/functions/getNewUpdates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import os from 'os';
import { HTTP } from 'meteor/http';
import { check, Match } from 'meteor/check';
import { Settings } from '../../../models';
import { settings } from '../../../settings';
import { Info } from '../../../utils';
import { getWorkspaceAccessToken } from '../../../cloud/server';
import { MongoInternals } from 'meteor/mongo';
Expand All @@ -11,7 +10,7 @@ export default () => {
try {
const uniqueID = Settings.findOne('uniqueID');
const { _oplogHandle } = MongoInternals.defaultRemoteCollectionDriver().mongo;
const oplogEnabled = _oplogHandle && _oplogHandle.onOplogEntry && settings.get('Force_Disable_OpLog_For_Cache') !== true;
const oplogEnabled = _oplogHandle && _oplogHandle.onOplogEntry;

const params = {
uniqueId: uniqueID.value,
Expand Down
2 changes: 0 additions & 2 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1390,8 +1390,6 @@
"For_your_security_you_must_enter_your_current_password_to_continue": "For your security, you must enter your current password to continue",
"force-delete-message": "Force Delete Message",
"force-delete-message_description": "Permission to delete a message bypassing all restrictions",
"Force_Disable_OpLog_For_Cache": "Force Disable OpLog for Cache",
"Force_Disable_OpLog_For_Cache_Description": "Will not use OpLog to sync cache even when it's available",
"Force_SSL": "Force SSL",
"Force_SSL_Description": "*Caution!* _Force SSL_ should never be used with reverse proxy. If you have a reverse proxy, you should do the redirect THERE. This option exists for deployments like Heroku, that does not allow the redirect configuration at the reverse proxy.",
"Force_visitor_to_accept_data_processing_consent": "Force visitor to accept data processing consent",
Expand Down
1 change: 1 addition & 0 deletions server/startup/migrations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,5 @@ import './v138';
import './v139';
import './v140';
import './v141';
import './v142';
import './xrun';
9 changes: 9 additions & 0 deletions server/startup/migrations/v142.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Migrations } from '../../../app/migrations';
import { Settings } from '../../../app/models';

Migrations.add({
version: 142,
up() {
Settings.remove({ _id: 'Force_Disable_OpLog_For_Cache' });
},
});
20 changes: 12 additions & 8 deletions server/startup/serverRunning.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import path from 'path';
import semver from 'semver';

Meteor.startup(function() {
let oplogState = 'Disabled';
let isOplogEnabled = false;

const { mongo } = MongoInternals.defaultRemoteCollectionDriver();

if (mongo._oplogHandle && mongo._oplogHandle.onOplogEntry) {
oplogState = 'Enabled';
if (settings.get('Force_Disable_OpLog_For_Cache') === true) {
oplogState += ' (Disabled for Cache Sync)';
}
isOplogEnabled = true;
}

let mongoDbVersion;
Expand All @@ -42,7 +39,7 @@ Meteor.startup(function() {
` Platform: ${ process.platform }`,
` Process Port: ${ process.env.PORT }`,
` Site URL: ${ settings.get('Site_Url') }`,
` ReplicaSet OpLog: ${ oplogState }`,
` ReplicaSet OpLog: ${ isOplogEnabled ? 'Enabled' : 'Disabled' }`,
];

if (Info.commit && Info.commit.hash) {
Expand All @@ -55,18 +52,25 @@ Meteor.startup(function() {

msg = msg.join('\n');

if (!isOplogEnabled) {
msg += ['', '', 'OPLOG / REPLICASET IS REQUIRED TO RUN ROCKET.CHAT, MORE INFORMATION AT:', 'https://rocket.chat/docs/installation/docker-containers/high-availability-install'].join('\n');
SystemLogger.error_box(msg, 'SERVER ERROR');

return process.exit(1);
}

if (!semver.satisfies(process.versions.node, desiredNodeVersionMajor)) {
msg += ['', '', 'YOUR CURRENT NODEJS VERSION IS NOT SUPPORTED,', `PLEASE UPGRADE / DOWNGRADE TO VERSION ${ desiredNodeVersionMajor }.X.X`].join('\n');
SystemLogger.error_box(msg, 'SERVER ERROR');

return process.exit();
return process.exit(1);
}

if (!semver.satisfies(mongoDbVersion, '>=3.2.0')) {
msg += ['', '', 'YOUR CURRENT MONGODB VERSION IS NOT SUPPORTED,', 'PLEASE UPGRADE TO VERSION 3.2 OR LATER'].join('\n');
SystemLogger.error_box(msg, 'SERVER ERROR');

return process.exit();
return process.exit(1);
}

return SystemLogger.startup_box(msg, 'SERVER RUNNING');
Expand Down

0 comments on commit f03e616

Please sign in to comment.