MongoDB Transactions (#12335)

* add run-rs to dependencies

* wip: add replica set to api unit github action

* wip: add replica set to api unit github action

* wip: fix gh actions mongodb replica set setting

* usa replica set for integration tests

* add correct mongodb version matrix for integration tests

* use different db connection on gh actions

* Revert "use different db connection on gh actions"

This reverts commit aa8db759d3.

* add example transaction

* add mongo script to package.json

* abstract mongodb utils, connect using hostname on windows

* npm scripts: mongo -> mongo:dev

* add setup script for run-rs on windows

* gh actions: run in test environment

* remove test files

* better error handling, use cross-spawn to avoid issues on windows

* fix lint
This commit is contained in:
Matteo Pagliazzi
2020-07-14 18:55:47 +02:00
committed by GitHub
parent e89ff95a21
commit c93bf3e498
11 changed files with 1432 additions and 864 deletions

View File

@@ -1,5 +1,10 @@
import gulp from 'gulp';
import path from 'path';
import babel from 'gulp-babel';
import os from 'os';
import fs from 'fs';
import spawn from 'cross-spawn'; // eslint-disable-line import/no-extraneous-dependencies
import clean from 'rimraf';
gulp.task('build:babel:server', () => gulp.src('website/server/**/*.js')
.pipe(babel())
@@ -24,10 +29,67 @@ gulp.task('build:prod', gulp.series(
done => done(),
));
// Due to this issue https://github.com/vkarpov15/run-rs/issues/45
// When used on windows `run-rs` must first be run without the `--keep` option
// in order to be setup correctly, afterwards it can be used.
const MONGO_PATH = path.join(__dirname, '/../mongodb-data/');
gulp.task('build:prepare-mongo', async () => {
if (fs.existsSync(MONGO_PATH)) {
// console.log('MongoDB data folder exists, skipping setup.');
return;
}
if (os.platform() !== 'win32') {
// console.log('Not on Windows, skipping MongoDB setup.');
return;
}
console.log('MongoDB data folder is missing, setting up.');
// use run-rs without --keep, kill it as soon as the replica set starts
const runRsProcess = spawn('run-rs', ['-v', '4.2.8', '-l', 'ubuntu1804', '--dbpath', 'mongodb-data', '--number', '1', '--quiet']);
for await (const chunk of runRsProcess.stdout) {
const stringChunk = chunk.toString();
console.log(stringChunk);
// kills the process after the replica set is setup
if (stringChunk.includes('Started replica set')) {
console.log('MongoDB setup correctly.');
runRsProcess.kill();
}
}
let error = '';
for await (const chunk of runRsProcess.stderr) {
const stringChunk = chunk.toString();
error += stringChunk;
}
const exitCode = await new Promise(resolve => {
runRsProcess.on('close', resolve);
});
if (exitCode || error.length > 0) {
// remove any leftover files
clean.sync(MONGO_PATH);
throw new Error(`Error running run-rs: ${error}`);
}
});
gulp.task('build:dev', gulp.series(
'build:prepare-mongo',
done => done(),
));
const buildArgs = [];
if (process.env.NODE_ENV === 'production') { // eslint-disable-line no-process-env
buildArgs.push('build:prod');
} else if (process.env.NODE_ENV !== 'test') { // eslint-disable-line no-process-env
buildArgs.push('build:dev');
}
gulp.task('build', gulp.series(buildArgs, done => {

View File

@@ -3,6 +3,10 @@ import nconf from 'nconf';
import repl from 'repl';
import gulp from 'gulp';
import logger from '../website/server/libs/logger';
import {
getDevelopmentConnectionUrl,
getDefaultConnectionOptions,
} from '../website/server/libs/mongodb';
// Add additional properties to the repl's context
const improveRepl = context => {
@@ -26,13 +30,14 @@ const improveRepl = context => {
context.Group = require('../website/server/models/group').model; // eslint-disable-line global-require
context.User = require('../website/server/models/user').model; // eslint-disable-line global-require
const isProd = nconf.get('NODE_ENV') === 'production';
const mongooseOptions = !isProd ? {} : {
keepAlive: 1,
connectTimeoutMS: 30000,
};
const IS_PROD = nconf.get('NODE_ENV') === 'production';
const NODE_DB_URI = nconf.get('NODE_DB_URI');
const mongooseOptions = getDefaultConnectionOptions();
const connectionUrl = IS_PROD ? NODE_DB_URI : getDevelopmentConnectionUrl(NODE_DB_URI);
mongoose.connect(
nconf.get('NODE_DB_URI'),
connectionUrl,
mongooseOptions,
err => {
if (err) throw err;

View File

@@ -6,6 +6,10 @@ import nconf from 'nconf';
import {
pipe,
} from './taskHelper';
import {
getDevelopmentConnectionUrl,
getDefaultConnectionOptions,
} from '../website/server/libs/mongodb';
// TODO rewrite
@@ -44,7 +48,10 @@ gulp.task('test:nodemon', gulp.series(done => {
}, 'nodemon'));
gulp.task('test:prepare:mongo', cb => {
mongoose.connect(TEST_DB_URI, err => {
const mongooseOptions = getDefaultConnectionOptions();
const connectionUrl = getDevelopmentConnectionUrl(TEST_DB_URI);
mongoose.connect(connectionUrl, mongooseOptions, err => {
if (err) return cb(`Unable to connect to mongo database. Are you sure it's running? \n\n${err}`);
return mongoose.connection.dropDatabase(err2 => {
if (err2) return cb(err2);