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

🔥 remove MongoDB #1344

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions docker/compose/subfolderWithSSL/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,3 @@ To stop it execute:
```
docker-compose stop
```

## Configuration

The default name of the database, user and password for MongoDB can be changed in the `.env` file in the current directory.
31 changes: 2 additions & 29 deletions docker/images/n8n/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,42 +107,16 @@ docker run -it --rm \
### Start with other Database

By default n8n uses SQLite to save credentials, past executions and workflows.
n8n however also supports MongoDB, PostgresDB and MySQL. To use them simply a few
n8n however also supports PostgresDB, MySQL and MariaDB. To use them simply a few
environment variables have to be set.

It is important to still persist the data in the `/root/.n8` folder. The reason
It is important to still persist the data in the `/root/.n8n` folder. The reason
is that it contains n8n user data. That is the name of the webhook
(in case) the n8n tunnel gets used and even more important the encryption key
for the credentials. If none gets found n8n creates automatically one on
startup. In case credentials are already saved with a different encryption key
it can not be used anymore as encrypting it is not possible anymore.

#### Use with MongoDB

> **WARNING**: Use Postgres if possible! Mongo has problems with saving large
> amounts of data in a document and causes also other problems. So support will
> may be dropped in the future.

Replace the following placeholders with the actual data:
- MONGO_DATABASE
- MONGO_HOST
- MONGO_PORT
- MONGO_USER
- MONGO_PASSWORD

```
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e DB_TYPE=mongodb \
-e DB_MONGODB_CONNECTION_URL="mongodb://<MONGO_USER>:<MONGO_PASSWORD>@<MONGO_SERVER>:<MONGO_PORT>/<MONGO_DATABASE>" \
-v ~/.n8n:/home/node/.n8n \
n8nio/n8n \
n8n start
```

A full working setup with docker-compose can be found [here](https://github.com/n8n-io/n8n/blob/master/docker/compose/withMongo/README.md)

#### Use with PostgresDB

Replace the following placeholders with the actual data:
Expand Down Expand Up @@ -203,7 +177,6 @@ with the given name. That makes it possible to load data easily from
Docker- and Kubernetes-Secrets.

The following environment variables support file input:
- DB_MONGODB_CONNECTION_URL_FILE
- DB_POSTGRESDB_DATABASE_FILE
- DB_POSTGRESDB_HOST_FILE
- DB_POSTGRESDB_PASSWORD_FILE
Expand Down
10 changes: 1 addition & 9 deletions packages/cli/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,10 @@ const config = convict({
database: {
type: {
doc: 'Type of database to use',
format: ['sqlite', 'mariadb', 'mongodb', 'mysqldb', 'postgresdb'],
format: ['sqlite', 'mariadb', 'mysqldb', 'postgresdb'],
default: 'sqlite',
env: 'DB_TYPE',
},
mongodb: {
connectionUrl: {
doc: 'MongoDB Connection URL',
format: '*',
default: 'mongodb://user:password@localhost:27017/database',
env: 'DB_MONGODB_CONNECTION_URL',
},
},
tablePrefix: {
doc: 'Prefix for table names',
format: '*',
Expand Down
21 changes: 1 addition & 20 deletions packages/cli/migrations/ormconfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {MongoDb, SQLite, MySQLDb, PostgresDb} from '../src/databases/index';
import { SQLite, MySQLDb, PostgresDb} from '../src/databases/index';

module.exports = [
{
Expand All @@ -19,25 +19,6 @@ module.exports = [
"subscribersDir": "./src/databases/sqlite/subscribers"
}
},
{
"name": "mongodb",
"type": "mongodb",
"logging": false,
"entities": Object.values(MongoDb),
"url": "mongodb://root:example@localhost:27017/n8n",
"authSource": 'admin',
"migrations": [
"./src/databases/mongodb/migrations/*.ts"
],
"subscribers": [
"src/subscriber/**/*.ts"
],
"cli": {
"entitiesDir": "./src/databases/mongodb",
"migrationsDir": "./src/databases/mongodb/Migrations",
"subscribersDir": "./src/databases/mongodb/Subscribers"
}
},
{
"name": "postgres",
"type": "postgres",
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@
"jwks-rsa": "~1.9.0",
"localtunnel": "^2.0.0",
"lodash.get": "^4.4.2",
"mongodb": "^3.5.5",
"mysql2": "~2.1.0",
"n8n-core": "~0.59.0",
"n8n-editor-ui": "~0.72.0",
Expand All @@ -114,7 +113,7 @@
"sqlite3": "^4.2.0",
"sse-channel": "^3.1.1",
"tslib": "1.11.2",
"typeorm": "^0.2.24"
"typeorm": "^0.2.30"
},
"jest": {
"transform": {
Expand Down
48 changes: 35 additions & 13 deletions packages/cli/src/ActiveWorkflowRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from 'n8n-core';

import {
IDataObject,
IExecuteData,
IGetExecutePollFunctions,
IGetExecuteTriggerFunctions,
Expand Down Expand Up @@ -116,12 +117,29 @@ export class ActiveWorkflowRunner {
throw new ResponseHelper.ResponseError('The "activeWorkflows" instance did not get initialized yet.', 404, 404);
}

const webhook = await Db.collections.Webhook?.findOne({ webhookPath: path, method: httpMethod }) as IWebhookDb;
let webhook = await Db.collections.Webhook?.findOne({ webhookPath: path, method: httpMethod }) as IWebhookDb;
let webhookId: string | undefined;

// check if something exist
// check if path is dynamic
if (webhook === undefined) {
// The requested webhook is not registered
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404);
// check if a dynamic webhook path exists
const pathElements = path.split('/');
webhookId = pathElements.shift();
webhook = await Db.collections.Webhook?.findOne({ webhookId, method: httpMethod }) as IWebhookDb;
if (webhook === undefined) {
// The requested webhook is not registered
throw new ResponseHelper.ResponseError(`The requested webhook "${httpMethod} ${path}" is not registered.`, 404, 404);
}
path = webhook.webhookPath;
// extracting params from path
const webhookPathParams: IDataObject = {};
webhook.webhookPath.split('/').forEach((ele, index) => {
if (ele.startsWith(':')) {
webhookPathParams[ele.slice(1)] = pathElements[index];
}
});
// write params to req.params
Object.assign(req.params, webhookPathParams);
}

const workflowData = await Db.collections.Workflow!.findOne(webhook.workflowId);
Expand Down Expand Up @@ -253,6 +271,14 @@ export class ActiveWorkflowRunner {
method: webhookData.httpMethod,
} as IWebhookDb;

if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
webhook.webhookId = node.webhookId;
}

if (webhook.webhookPath.startsWith('/')) {
webhook.webhookPath = webhook.webhookPath.slice(1);
}

try {

await Db.collections.Webhook?.insert(webhook);
Expand All @@ -273,11 +299,12 @@ export class ActiveWorkflowRunner {
let errorMessage = '';

// if it's a workflow from the the insert
// TODO check if there is standard error code for deplicate key violation that works
// TODO check if there is standard error code for duplicate key violation that works
// with all databases
if (error.name === 'MongoError' || error.name === 'QueryFailedError') {

errorMessage = `The webhook path [${webhook.webhookPath}] and method [${webhook.method}] already exist.`;
if (error.name === 'QueryFailedError') {
errorMessage = error.parameters.length === 5
? `Node [${webhook.node}] can't be saved, please duplicate [${webhook.node}] and delete the currently existing one.`
: `The webhook path [${webhook.webhookPath}] and method [${webhook.method}] already exist.`;

} else if (error.detail) {
// it's a error runnig the webhook methods (checkExists, create)
Expand Down Expand Up @@ -323,11 +350,6 @@ export class ActiveWorkflowRunner {

await WorkflowHelpers.saveStaticData(workflow);

// if it's a mongo objectId convert it to string
if (typeof workflowData.id === 'object') {
workflowData.id = workflowData.id.toString();
}

const webhook = {
workflowId: workflowData.id,
} as IWebhookDb;
Expand Down
62 changes: 6 additions & 56 deletions packages/cli/src/Db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { TlsOptions } from 'tls';
import * as config from '../config';

import {
MongoDb,
MySQLDb,
PostgresDb,
SQLite,
Expand All @@ -32,29 +31,9 @@ export let collections: IDatabaseCollections = {
Webhook: null,
};

import {
CreateIndexStoppedAt1594828256133,
InitialMigration1587669153312,
WebhookModel1589476000887,
} from './databases/postgresdb/migrations';

import {
CreateIndexStoppedAt1594910478695,
InitialMigration1587563438936,
WebhookModel1592679094242,
} from './databases/mongodb/migrations';

import {
CreateIndexStoppedAt1594902918301,
InitialMigration1588157391238,
WebhookModel1592447867632,
} from './databases/mysqldb/migrations';

import {
CreateIndexStoppedAt1594825041918,
InitialMigration1588102412422,
WebhookModel1592445003908,
} from './databases/sqlite/migrations';
import { postgresMigrations } from './databases/postgresdb/migrations';
import { mysqlMigrations } from './databases/mysqldb/migrations';
import { sqliteMigrations } from './databases/sqlite/migrations';

import * as path from 'path';

Expand All @@ -68,23 +47,6 @@ export async function init(): Promise<IDatabaseCollections> {
const entityPrefix = config.get('database.tablePrefix');

switch (dbType) {
case 'mongodb':
entities = MongoDb;
connectionOptions = {
type: 'mongodb',
entityPrefix,
url: await GenericHelpers.getConfigValue('database.mongodb.connectionUrl') as string,
useNewUrlParser: true,
migrations: [
InitialMigration1587563438936,
WebhookModel1592679094242,
CreateIndexStoppedAt1594910478695,
],
migrationsRun: true,
migrationsTableName: `${entityPrefix}migrations`,
};
break;

case 'postgresdb':
entities = PostgresDb;

Expand Down Expand Up @@ -112,11 +74,7 @@ export async function init(): Promise<IDatabaseCollections> {
port: await GenericHelpers.getConfigValue('database.postgresdb.port') as number,
username: await GenericHelpers.getConfigValue('database.postgresdb.user') as string,
schema: config.get('database.postgresdb.schema'),
migrations: [
InitialMigration1587669153312,
WebhookModel1589476000887,
CreateIndexStoppedAt1594828256133,
],
migrations: postgresMigrations,
migrationsRun: true,
migrationsTableName: `${entityPrefix}migrations`,
ssl,
Expand All @@ -135,11 +93,7 @@ export async function init(): Promise<IDatabaseCollections> {
password: await GenericHelpers.getConfigValue('database.mysqldb.password') as string,
port: await GenericHelpers.getConfigValue('database.mysqldb.port') as number,
username: await GenericHelpers.getConfigValue('database.mysqldb.user') as string,
migrations: [
InitialMigration1588157391238,
WebhookModel1592447867632,
CreateIndexStoppedAt1594902918301,
],
migrations: mysqlMigrations,
migrationsRun: true,
migrationsTableName: `${entityPrefix}migrations`,
};
Expand All @@ -151,11 +105,7 @@ export async function init(): Promise<IDatabaseCollections> {
type: 'sqlite',
database: path.join(n8nFolder, 'database.sqlite'),
entityPrefix,
migrations: [
InitialMigration1588102412422,
WebhookModel1592445003908,
CreateIndexStoppedAt1594825041918,
],
migrations: sqliteMigrations,
migrationsRun: true,
migrationsTableName: `${entityPrefix}migrations`,
};
Expand Down
6 changes: 2 additions & 4 deletions packages/cli/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface IWebhookDb {
webhookPath: string;
method: string;
node: string;
webhookId?: string;
}

export interface IWorkflowBase extends IWorkflowBaseWorkflow {
Expand Down Expand Up @@ -103,7 +104,7 @@ export interface ICredentialsDecryptedResponse extends ICredentialsDecryptedDb {
id: string;
}

export type DatabaseType = 'mariadb' | 'mongodb' | 'postgresdb' | 'mysqldb' | 'sqlite';
export type DatabaseType = 'mariadb' | 'postgresdb' | 'mysqldb' | 'sqlite';
export type SaveExecutionDataType = 'all' | 'none';

export interface IExecutionBase {
Expand Down Expand Up @@ -247,9 +248,6 @@ export interface IN8nConfig {

export interface IN8nConfigDatabase {
type: DatabaseType;
mongodb: {
connectionUrl: string;
};
postgresdb: {
host: string;
password: string;
Expand Down
Loading