mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Implement Neo4J store for migrate
This commit is contained in:
parent
30268dec09
commit
daf2c40cae
@ -13,8 +13,10 @@
|
|||||||
"db:reset": "babel-node src/seed/reset-db.js",
|
"db:reset": "babel-node src/seed/reset-db.js",
|
||||||
"db:seed": "babel-node src/seed/seed-db.js",
|
"db:seed": "babel-node src/seed/seed-db.js",
|
||||||
"db:setup": "babel-node src/db/setup.js",
|
"db:setup": "babel-node src/db/setup.js",
|
||||||
"db:migrate:create": "migrate create --template-file./src/db/migrationTemplate.js",
|
"__migrate": "migrate --compiler 'js:@babel/register' --migrations-dir ./src/db/migrations",
|
||||||
"db:migrate": "migrate --compiler 'js:@babel/register'"
|
"db:migrate": "yarn run __migrate --store ./src/db/migrate/store.js",
|
||||||
|
"db:migrate:create": "yarn run __migrate --template-file ./src/db/migrate/template.js create",
|
||||||
|
"production:db:migrate": "migrate --migrations-dir ./dist/db/migrations --store ./dist/db/migrate/store.js"
|
||||||
},
|
},
|
||||||
"author": "Human Connection gGmbH",
|
"author": "Human Connection gGmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -106,7 +108,7 @@
|
|||||||
"@babel/node": "~7.8.3",
|
"@babel/node": "~7.8.3",
|
||||||
"@babel/plugin-proposal-throw-expressions": "^7.8.3",
|
"@babel/plugin-proposal-throw-expressions": "^7.8.3",
|
||||||
"@babel/preset-env": "~7.8.3",
|
"@babel/preset-env": "~7.8.3",
|
||||||
"@babel/register": "~7.8.3",
|
"@babel/register": "^7.8.3",
|
||||||
"apollo-server-testing": "~2.9.16",
|
"apollo-server-testing": "~2.9.16",
|
||||||
"babel-core": "~7.0.0-0",
|
"babel-core": "~7.0.0-0",
|
||||||
"babel-eslint": "~10.0.3",
|
"babel-eslint": "~10.0.3",
|
||||||
|
|||||||
57
backend/src/db/migrate/store.js
Normal file
57
backend/src/db/migrate/store.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { getDriver } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
|
class Store {
|
||||||
|
async load(fn) {
|
||||||
|
const driver = getDriver()
|
||||||
|
const session = driver.session()
|
||||||
|
const readTxResultPromise = session.readTransaction(async txc => {
|
||||||
|
const result = await txc.run(
|
||||||
|
'MATCH (migration:Migration) RETURN migration {.*} ORDER BY migration.timestamp DESC',
|
||||||
|
)
|
||||||
|
return result.records.map(r => r.get('migration'))
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
const migrations = await readTxResultPromise
|
||||||
|
if (migrations.length <= 0) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(
|
||||||
|
"No migrations found in database. If it's the first time you run migrations, then this is normal.",
|
||||||
|
)
|
||||||
|
return fn(null, {})
|
||||||
|
}
|
||||||
|
const [{ title: lastRun }] = migrations
|
||||||
|
fn(null, { lastRun, migrations })
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error) // eslint-disable-line no-console
|
||||||
|
} finally {
|
||||||
|
session.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(set, fn) {
|
||||||
|
const driver = getDriver()
|
||||||
|
const session = driver.session()
|
||||||
|
const { migrations } = set
|
||||||
|
const writeTxResultPromise = session.writeTransaction(txc => {
|
||||||
|
return Promise.all(
|
||||||
|
migrations.map(migration => {
|
||||||
|
const { title, description, timestamp } = migration
|
||||||
|
const properties = { title, description, timestamp }
|
||||||
|
return txc.run('CREATE (migration:Migration) SET migration += $properties', {
|
||||||
|
properties,
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
await writeTxResultPromise
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error) // eslint-disable-line no-console
|
||||||
|
} finally {
|
||||||
|
session.close()
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Store
|
||||||
7
backend/src/db/migrate/template.js
Normal file
7
backend/src/db/migrate/template.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export function up(next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function down(next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
@ -1,7 +0,0 @@
|
|||||||
export function up (next) {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
|
|
||||||
export function down (next) {
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
@ -1,10 +1,18 @@
|
|||||||
import { throwError, of, concat } from 'rxjs'
|
import { throwError, of, concat } from 'rxjs'
|
||||||
import { tap, flatMap, mergeMap, map, catchError, filter } from 'rxjs/operators'
|
import { tap, flatMap, mergeMap, map, catchError, filter } from 'rxjs/operators'
|
||||||
import CONFIG from '../src/config'
|
import CONFIG from '../../src/config'
|
||||||
import { getNeode, getDriver } from '../src/bootstrap/neo4j'
|
import { getNeode, getDriver } from '../../src/bootstrap/neo4j'
|
||||||
import normalizeEmail from '../src/schema/resolvers//helpers/normalizeEmail'
|
import normalizeEmail from '../../src/schema/resolvers//helpers/normalizeEmail'
|
||||||
|
|
||||||
|
export const description = `
|
||||||
|
This migration merges duplicate :User and :EmailAddress nodes. It became
|
||||||
|
necessary after we implemented the email normalization but forgot to migrate
|
||||||
|
the existing data. Some (40) users decided to just register with a new account
|
||||||
|
but the same email address. On signup our backend would normalize the email,
|
||||||
|
which is good, but would also keep the existing unnormalized email address.
|
||||||
|
|
||||||
|
This led to about 40 duplicate user and email address nodes in our database.
|
||||||
|
`
|
||||||
export function up (next) {
|
export function up (next) {
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const rxSession = driver.rxSession()
|
const rxSession = driver.rxSession()
|
||||||
@ -11,7 +11,7 @@ export default {
|
|||||||
direction: 'in',
|
direction: 'in',
|
||||||
},
|
},
|
||||||
title: { type: 'string', disallow: [null], min: 3 },
|
title: { type: 'string', disallow: [null], min: 3 },
|
||||||
slug: { type: 'string', allow: [null], unique: 'true', },
|
slug: { type: 'string', allow: [null], unique: 'true' },
|
||||||
content: { type: 'string', disallow: [null], min: 3 },
|
content: { type: 'string', disallow: [null], min: 3 },
|
||||||
contentExcerpt: { type: 'string', allow: [null] },
|
contentExcerpt: { type: 'string', allow: [null] },
|
||||||
image: { type: 'string', allow: [null] },
|
image: { type: 'string', allow: [null] },
|
||||||
|
|||||||
@ -751,7 +751,7 @@
|
|||||||
levenary "^1.1.0"
|
levenary "^1.1.0"
|
||||||
semver "^5.5.0"
|
semver "^5.5.0"
|
||||||
|
|
||||||
"@babel/register@^7.8.3", "@babel/register@~7.8.3":
|
"@babel/register@^7.8.3":
|
||||||
version "7.8.3"
|
version "7.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.8.3.tgz#5d5d30cfcc918437535d724b8ac1e4a60c5db1f8"
|
resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.8.3.tgz#5d5d30cfcc918437535d724b8ac1e4a60c5db1f8"
|
||||||
integrity sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==
|
integrity sha512-t7UqebaWwo9nXWClIPLPloa5pN33A2leVs8Hf0e9g9YwUP8/H9NeR7DJU+4CXo23QtjChQv5a3DjEtT83ih1rg==
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user