From 6e356217ae977e5614dba4d5f11d25b9c84753fd Mon Sep 17 00:00:00 2001 From: Liordino Neto Date: Mon, 20 Jul 2020 22:41:45 -0300 Subject: [PATCH] feat: created migration to add a schema_version column on the user_config table feat: adapted the new settings loader to work with the db instead of the json file fix: fixed the schema migration file fix: updated accounts to work with the db fix: fetch only data with the new schema version fix: change the account saving process so there's no more than one account record chore: removed unnecessary TODO comments fix: replaced an error throwing with a Promise reject fix: when looking for the latest config, don't limit it to the new ones fix: fix function names on gql server fix: remove duplicate import fix: return an empty object when there's no schema_version 2 config yet --- lib/new-admin/graphql/schema.js | 4 +- lib/new-settings-loader.js | 144 +++++++++++------- ...295132361-schema-version-on-user-config.js | 13 ++ 3 files changed, 107 insertions(+), 54 deletions(-) create mode 100644 migrations/1595295132361-schema-version-on-user-config.js diff --git a/lib/new-admin/graphql/schema.js b/lib/new-admin/graphql/schema.js index 6bf2c18b..8c8813d9 100644 --- a/lib/new-admin/graphql/schema.js +++ b/lib/new-admin/graphql/schema.js @@ -258,8 +258,8 @@ const resolvers = { serverLogs.getServerLogs(from, until, limit, offset), transactions: (...[, { from, until, limit, offset }]) => transactions.batch(from, until, limit, offset), - config: () => settingsLoader.getConfig(), - accounts: () => settingsLoader.getAccounts() + config: () => settingsLoader.loadLatestConfig(), + accounts: () => settingsLoader.loadAccounts() }, Mutation: { machineAction: (...[, { deviceId, action, cassette1, cassette2 }]) => machineAction({ deviceId, action, cassette1, cassette2 }), diff --git a/lib/new-settings-loader.js b/lib/new-settings-loader.js index 661fa37e..73322eee 100644 --- a/lib/new-settings-loader.js +++ b/lib/new-settings-loader.js @@ -1,71 +1,111 @@ const _ = require('lodash/fp') -const low = require('lowdb') -const FileAsync = require('lowdb/adapters/FileAsync') +const db = require('./db') -const adapter = new FileAsync('db.json') -let db = null - -// TODO new-admin save to actual db, like the old settings -low(adapter).then(it => { - db = it -}) +const NEW_SETTINGS_LOADER_SCHEMA_VERSION = 2 function saveAccounts (accountsToSave) { - const currentState = db.getState() || {} - const accounts = currentState.accounts || {} + const sql = `update user_config set data = $2, valid = $3, schema_version = $4 where type = $1; + insert into user_config (type, data, valid, schema_version) + select $1, $2, $3, $4 where $1 not in (select type from user_config)` - const newAccounts = _.assign(accounts)(accountsToSave) - - const newState = _.set('accounts', newAccounts, currentState) - db.setState(newState) - return db.write() - .then(() => newState.accounts) + return loadAccounts() + .then(currentAccounts => { + const newAccounts = _.assign(currentAccounts, accountsToSave) + return db.none(sql, ['accounts', { accounts: newAccounts }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION]) + }) } -function getAccounts () { - const state = db.getState() - return state ? state.accounts : null +function loadAccounts () { + const toFields = fieldArr => _.fromPairs(_.map(r => [r.code, r.value], fieldArr)) + const toPairs = r => [r.code, toFields(r.fields)] + + const sql = `select data + from user_config + where type=$1 + and schema_version=$2 + and valid + order by id desc + limit 1` + + return db.oneOrNone(sql, ['accounts', NEW_SETTINGS_LOADER_SCHEMA_VERSION]) + .then(row => { + if (!row) return {} + return _.fromPairs(_.map(toPairs, row.data.accounts)) + }) } function saveConfig (config) { - const currentState = db.getState() || {} - const currentConfig = currentState.config || {} - const newConfig = _.assign(currentConfig, config) + const sql = 'insert into user_config (type, data, valid, schema_version) values ($1, $2, $3, $4)' - const newState = _.set('config', newConfig, currentState) - db.setState(newState) - return db.write() - .then(() => newState.config) -} - -function getConfig () { - const state = db.getState() - return (state && state.config) || {} + return loadLatestConfig() + .then(currentConfig => { + const newConfig = _.assign(currentConfig, config) + return db.none(sql, ['config', { config: newConfig }, true, NEW_SETTINGS_LOADER_SCHEMA_VERSION]) + }) } function loadLatest () { - return new Promise((resolve) => { - if (!db) { - setTimeout(() => { - return resolve(db.getState()) - }, 1000) - } else { - return resolve(db.getState()) - } - }) + return Promise.all([loadLatestConfig(), loadAccounts()]) + .then(([config, accounts]) => ({ + config, + accounts + })) +} + +function loadLatestConfig () { + const sql = `select data + from user_config + where type=$1 + and schema_version=$2 + and valid + order by id desc + limit 1` + + return db.oneOrNone(sql, ['config', NEW_SETTINGS_LOADER_SCHEMA_VERSION]) + .then(row => !row ? {} : row.data.config) + .catch(err => { + if (err.name === 'QueryResultError') { + throw new Error('lamassu-server is not configured') + } + + throw err + }) +} + +function loadConfig (versionId) { + const sql = `select data + from user_config + where id=$1 + and type=$2 + and schema_version=$3 + and valid` + + return db.one(sql, [versionId, 'config', NEW_SETTINGS_LOADER_SCHEMA_VERSION]) + .then(row => row.data.config) + .catch(err => { + if (err.name === 'QueryResultError') { + throw new Error('No such config version: ' + versionId) + } + + throw err + }) } -// TODO new-admin: grab correct version function load (versionId) { - return new Promise((resolve) => { - if (!db) { - setTimeout(() => { - return resolve(db.getState()) - }, 1000) - } else { - return resolve(db.getState()) - } - }) + if (!versionId) Promise.reject('versionId is required') + + return Promise.all([loadConfig(versionId), loadAccounts()]) + .then(([config, accounts]) => ({ + config, + accounts + })) } -module.exports = { getConfig, saveConfig, saveAccounts, getAccounts, loadLatest, load } +module.exports = { + saveConfig, + saveAccounts, + loadAccounts, + loadLatest, + loadLatestConfig, + load +} diff --git a/migrations/1595295132361-schema-version-on-user-config.js b/migrations/1595295132361-schema-version-on-user-config.js new file mode 100644 index 00000000..e8784b5a --- /dev/null +++ b/migrations/1595295132361-schema-version-on-user-config.js @@ -0,0 +1,13 @@ +const db = require('./db') + +module.exports.up = function (next) { + var sql = [ + 'alter table user_config add column schema_version smallint DEFAULT 1' + ] + + db.multi(sql, next) +} + +module.exports.down = function (next) { + next() +}