refs #4823 Added function handler and more
This commit is contained in:
parent
02cd8124ba
commit
14b29400a4
31
floriday.js
31
floriday.js
|
@ -6,22 +6,22 @@ import fs from 'fs';
|
|||
|
||||
const env = process.env;
|
||||
const flModels = yml.load(fs.readFileSync('./models/models.yml', 'utf8'));
|
||||
let cycle = 1;
|
||||
let cycle = 1, stopSchedule = false;
|
||||
class Floriday {
|
||||
async start() {
|
||||
try {
|
||||
await utils.checkConfig();
|
||||
await utils.checkToken();
|
||||
utils.separator('Init');
|
||||
await utils.separator('Init');
|
||||
} catch (err) {
|
||||
utils.criticalError(err);
|
||||
utils.handler('critical', err);
|
||||
}
|
||||
};
|
||||
|
||||
async tryConn() {
|
||||
while (true)
|
||||
try {
|
||||
utils.warning(new Error('Awaiting a response from the database...'));
|
||||
await utils.handler('warning', new Error('Awaiting a response from the database...'));
|
||||
await utils.sleep(env.DB_RECON_TIMEOUT);
|
||||
await checkCon();
|
||||
await this.schedule();
|
||||
|
@ -34,7 +34,7 @@ class Floriday {
|
|||
const intervalTime = JSON.parse(env.IS_PRODUCTION)
|
||||
? env.MS_PRODUCTION_SCHEDULE
|
||||
: env.MS_TEST_SCHEDULE;
|
||||
while (!this.stopSchedule) {
|
||||
while (!stopSchedule) {
|
||||
try {
|
||||
await this.trunk();
|
||||
await new Promise(resolve => setTimeout(resolve, intervalTime));
|
||||
|
@ -50,26 +50,27 @@ class Floriday {
|
|||
|
||||
async trunk() {
|
||||
try{
|
||||
for (let model of flModels)
|
||||
await utils.syncModel(model);
|
||||
|
||||
await utils.checkConnections();
|
||||
utils.separator(`${cycle++} ${(cycle == 2 ? 'Cycle' : 'Cycles')}`);
|
||||
} catch (err) {
|
||||
if (['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name))
|
||||
throw err;
|
||||
|
||||
utils.criticalError(err);
|
||||
for (let model of flModels) {
|
||||
if (stopSchedule) return;
|
||||
await utils.syncModel(model);
|
||||
}
|
||||
|
||||
await utils.separator(`${cycle++} ${(cycle == 2 ? 'Cycle' : 'Cycles')}`);
|
||||
} catch (err) {
|
||||
if (err?.original?.code === 'ER_SOCKET_UNEXPECTED_CLOSE') throw err;
|
||||
utils.handler('critical', err);
|
||||
}
|
||||
};
|
||||
|
||||
async stop() {
|
||||
try {
|
||||
this.stopSchedule = false;
|
||||
stopSchedule = true;
|
||||
await closeCon();
|
||||
console.warn(chalk.dim('\nBye, come back soon 👋'))
|
||||
} catch (err) {
|
||||
utils.criticalError(err);
|
||||
utils.handler('critical', err);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -19,12 +19,12 @@ console.log(chalk.hex('#06c581')(
|
|||
))
|
||||
|
||||
try {
|
||||
utils.startSpin('Creating database connection...');
|
||||
await utils.startSpin('Creating database connection...');
|
||||
sequelize = await createConn();
|
||||
await checkCon();
|
||||
utils.okSpin();
|
||||
await utils.okSpin();
|
||||
} catch (err) {
|
||||
utils.criticalSpin(err);
|
||||
await utils.criticalSpin(err);
|
||||
}
|
||||
|
||||
// Conf Models
|
||||
|
@ -161,13 +161,13 @@ try {
|
|||
});
|
||||
*/
|
||||
} catch (err) {
|
||||
utils.criticalError(err);
|
||||
utils.handler('critical', err);
|
||||
}
|
||||
|
||||
try {
|
||||
const action = JSON.parse(env.FORCE_SYNC) ? { force: true } : { alter: true };
|
||||
const actionMsg = JSON.parse(env.FORCE_SYNC) ? 'Forcing' : 'Altering';
|
||||
utils.startSpin(`${actionMsg} models...`);
|
||||
await utils.startSpin(`${actionMsg} models...`);
|
||||
await sequelize.sync(action);
|
||||
|
||||
/*
|
||||
|
@ -177,11 +177,10 @@ try {
|
|||
// Create procedures
|
||||
sequelize.query(fs.readFileSync('routines/procedures/offerRefresh.sql', 'utf-8'));
|
||||
*/
|
||||
|
||||
utils.okSpin();
|
||||
await utils.okSpin();
|
||||
}
|
||||
catch (err) {
|
||||
utils.criticalSpin(err)
|
||||
await utils.criticalSpin(err)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,13 +218,13 @@ async function checkCon() {
|
|||
* Close the connection to the database
|
||||
*/
|
||||
async function closeCon() {
|
||||
utils.failSpin(null, true);
|
||||
utils.startSpin('Closing database connection...');
|
||||
await utils.failSpin(null, true);
|
||||
await utils.startSpin('Closing database connection...');
|
||||
try {
|
||||
await sequelize.close()
|
||||
utils.okSpin();
|
||||
await utils.okSpin();
|
||||
} catch (err) {
|
||||
utils.criticalSpin(err);
|
||||
await utils.criticalSpin(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
145
utils.js
145
utils.js
|
@ -10,7 +10,7 @@ import fs from 'fs';
|
|||
const env = process.env;
|
||||
const methods = yml.load(fs.readFileSync('./methods.yml', 'utf8'));
|
||||
const flModels = yml.load(fs.readFileSync('./models/models.yml', 'utf8'));
|
||||
const arrow = '└─────';
|
||||
const arrow = '└───────';
|
||||
let spinner;
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ let spinner;
|
|||
*/
|
||||
export async function checkToken(isForce) {
|
||||
try {
|
||||
startSpin(`Checking token...`);
|
||||
await startSpin(`Checking token...`);
|
||||
|
||||
const clientConfigData = await models.config.findOne();
|
||||
|
||||
|
@ -57,9 +57,9 @@ export async function checkToken(isForce) {
|
|||
});
|
||||
} else
|
||||
optionalMsg = 'Using stored token...';
|
||||
okSpin(optionalMsg);
|
||||
await okSpin(optionalMsg);
|
||||
} catch (err) {
|
||||
failSpin(err);
|
||||
await await failSpin(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,7 @@ export async function getCurrentToken() {
|
|||
* Check the floriday data config.
|
||||
*/
|
||||
export async function checkConfig() {
|
||||
startSpin(`Checking config...`);
|
||||
await startSpin(`Checking config...`);
|
||||
|
||||
const excludedEnvVars = ['VSCODE_GIT_ASKPASS_EXTRA_ARGS'];
|
||||
const requiredEnvVars = Object.keys(env);
|
||||
|
@ -84,13 +84,13 @@ export async function checkConfig() {
|
|||
|
||||
for (const reqEnvVar of filteredEnvVars)
|
||||
if (!process.env[reqEnvVar])
|
||||
failSpin(new Error(`You haven't provided the ${reqEnvVar} environment variable`));
|
||||
await failSpin(new Error(`You haven't provided the ${reqEnvVar} environment variable`));
|
||||
|
||||
const clientConfigData = await models.config.findOne();
|
||||
if (!clientConfigData)
|
||||
await updateClientConfig(env.CLIENT_ID, env.CLIENT_SECRET);
|
||||
|
||||
okSpin();
|
||||
await okSpin();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -125,8 +125,8 @@ export async function updateClientConfig(clientConfig) {
|
|||
*
|
||||
* @param {Integer} ms
|
||||
*/
|
||||
export function sleep(ms) {
|
||||
new Promise(resolve => setTimeout(resolve, ms));
|
||||
export async function sleep(ms) {
|
||||
await new Promise(resolve => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -135,7 +135,7 @@ export function sleep(ms) {
|
|||
* @param {String} model Supported models (./models/methods.yml)
|
||||
*/
|
||||
export async function syncModel(model) {
|
||||
startSpin(`Syncing ${model}...`);
|
||||
await startSpin(`Syncing ${model}...`);
|
||||
try {
|
||||
const dbSeqNum = await models.sequenceNumber.findOne({ where: { model } })
|
||||
let curSeqNum = dbSeqNum?.maxSequenceNumber ?? 0, i = 0;
|
||||
|
@ -155,21 +155,26 @@ export async function syncModel(model) {
|
|||
params = params.toString();
|
||||
}
|
||||
|
||||
const res = (await vnRequest('GET', `${env.API_URL}${methods[model].sync.url}${curSeqNum}${params ? `?${params}` : ''}`)).data;
|
||||
const data = res.results;
|
||||
curSeqNum = res.maximumSequenceNumber;
|
||||
const res = (await vnRequest('GET', `${env.API_URL}${methods[model].sync.url}${curSeqNum}${params ? `?${params}` : ''}`));
|
||||
if (res?.response?.status == 403 && res?.response?.data?.title === 'There are no connected suppliers.') { // Forbidden
|
||||
await await warnSpin(`Syncing ${model}...`, new Error(res.response.data.title), true);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = res.data.results;
|
||||
curSeqNum = res.data.maximumSequenceNumber;
|
||||
misSeqNum = maxSeqNum - curSeqNum;
|
||||
await insertModel(model, data);
|
||||
txtSpin(`Syncing ${i = i + data.length} ${model}, ${misSeqNum} missing...`);
|
||||
await txtSpin(`Syncing ${i = i + data.length} ${model}, ${misSeqNum} missing...`);
|
||||
await insertSequenceNumber(model, curSeqNum);
|
||||
}
|
||||
await insertSequenceNumber(model, maxSeqNum);
|
||||
txtSpin((i)
|
||||
await txtSpin((i)
|
||||
? `Syncing ${i} ${model}...`
|
||||
: `Syncing ${model}...`);
|
||||
okSpin();
|
||||
await okSpin();
|
||||
} catch (err) {
|
||||
failSpin(err);
|
||||
await await failSpin(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -210,12 +215,12 @@ export async function insertModel(model, data) {
|
|||
*/
|
||||
export async function checkConnections(){
|
||||
try {
|
||||
startSpin('Checking connections...');
|
||||
await startSpin('Checking connections...');
|
||||
await createConnections();
|
||||
await deleteConnections();
|
||||
if (spinner) okSpin();
|
||||
if (spinner) await okSpin();
|
||||
} catch (err) {
|
||||
failSpin(err);
|
||||
await failSpin(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -669,13 +674,13 @@ export async function createConnections() {
|
|||
connectionsToPut.push(value.organizationId);
|
||||
});
|
||||
|
||||
if (connectionsToPut.length && !spinner) startSpin('Creating connections...');
|
||||
if (connectionsToPut.length && !spinner) await startSpin('Creating connections...');
|
||||
|
||||
for (let connection of connectionsToPut) {
|
||||
await vnRequest('PUT', `${env.API_URL}${methods.connections.base.url}${connection}`);
|
||||
txtSpin(`Creating ${i++} connections, ${connectionsToPut.length - i} missing...`);
|
||||
await txtSpin(`Creating ${i++} connections, ${connectionsToPut.length - i} missing...`);
|
||||
}
|
||||
if (spinner && i) okSpin(`Creating ${i++} connections...`);
|
||||
if (spinner && i) await okSpin(`Creating ${i++} connections...`);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
|
@ -697,16 +702,16 @@ export async function deleteConnections() {
|
|||
ghostConnections.push(value.organizationId);
|
||||
});
|
||||
|
||||
if (ghostConnections.length && !spinner) startSpin('Deleting connections...');
|
||||
if (ghostConnections.length && !spinner) await startSpin('Deleting connections...');
|
||||
|
||||
for (let connection of ghostConnections) {
|
||||
await vnRequest('DELETE', `${env.API_URL}/connections/${connection}`);
|
||||
txtSpin(`Deleting ${i++} connections, ${ghostConnections.length - i} missing...`)
|
||||
await txtSpin(`Deleting ${i++} connections, ${ghostConnections.length - i} missing...`)
|
||||
}
|
||||
|
||||
if (spinner && i) okSpin(`Deleting ${i++} connections...`);
|
||||
if (spinner && i) await okSpin(`Deleting ${i++} connections...`);
|
||||
} catch (err) {
|
||||
criticalSpin(err);
|
||||
await criticalSpin(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -737,43 +742,43 @@ export async function vnRequest(method, url, data, headers) {
|
|||
switch (err.code) {
|
||||
case 'ECONNRESET': // Client network socket TLS
|
||||
case 'EAI_AGAIN': // getaddrinfo
|
||||
warnSpin(null, err, false);
|
||||
sleep(1000);
|
||||
await await warnSpin(null, err, false);
|
||||
await sleep(1000);
|
||||
break;
|
||||
case 'ECONNABORTED':
|
||||
case 'ECONNREFUSED':
|
||||
case 'ERR_BAD_REQUEST':
|
||||
switch (err.response.status) {
|
||||
case 404: // Not found
|
||||
case 404, 403: // Not found and Forbidden
|
||||
return err;
|
||||
case 504:
|
||||
case 502:
|
||||
warnSpin(null, err, false);
|
||||
sleep(1000);
|
||||
await warnSpin(null, err, false);
|
||||
await sleep(1000);
|
||||
break;
|
||||
case 429: // Too Many Requests
|
||||
warnSpin(null, err, false);
|
||||
sleep(60000);
|
||||
await warnSpin(null, err, false);
|
||||
await sleep(60000);
|
||||
break;
|
||||
case 401: // Unauthorized
|
||||
warnSpin(null, err, false);
|
||||
await warnSpin(null, err, false);
|
||||
await checkToken(true);
|
||||
headers.Authorization
|
||||
? headers.Authorization = `Bearer ${await getCurrentToken()}`
|
||||
: criticalError(err);
|
||||
: handler('critical', err);;
|
||||
break;
|
||||
default:
|
||||
warnSpin(null, err, false);
|
||||
sleep(env.MS_RETRY_UNHANDLED_ERROR);
|
||||
await warnSpin(null, err, false);
|
||||
await sleep(env.MS_RETRY_UNHANDLED_ERROR);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warnSpin(null, err, false);
|
||||
sleep(env.MS_RETRY_UNHANDLED_ERROR);
|
||||
await warnSpin(null, err, false);
|
||||
await sleep(env.MS_RETRY_UNHANDLED_ERROR);
|
||||
break;
|
||||
}
|
||||
startSpin();
|
||||
await startSpin();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -784,7 +789,7 @@ export async function vnRequest(method, url, data, headers) {
|
|||
* @param {String} msg Text of spinner
|
||||
* @param {Boolean} isNew Reinstantiate the object
|
||||
**/
|
||||
export function startSpin(msg, isKeep) {
|
||||
export async function startSpin(msg, isKeep) {
|
||||
if (JSON.parse(env.TIME_STAMPS) && msg)
|
||||
msg = `${chalk.gray(`[${new moment().format('YYYY-MM-DD hh:mm:ss A')}]`)} ${msg}`;
|
||||
|
||||
|
@ -803,7 +808,7 @@ export function startSpin(msg, isKeep) {
|
|||
*
|
||||
* @param {String} msg Text of spinner
|
||||
**/
|
||||
export function txtSpin(msg) {
|
||||
export async function txtSpin(msg) {
|
||||
if (JSON.parse(env.TIME_STAMPS) && msg)
|
||||
msg = `${chalk.gray(`[${new moment().format('YYYY-MM-DD hh:mm:ss A')}]`)} ${msg}`;
|
||||
|
||||
|
@ -815,7 +820,7 @@ export function txtSpin(msg) {
|
|||
*
|
||||
* @param {String} msg Text of spinner
|
||||
**/
|
||||
export function okSpin(msg) {
|
||||
export async function okSpin(msg) {
|
||||
if (JSON.parse(env.TIME_STAMPS) && msg)
|
||||
msg = `${chalk.gray(`[${new moment().format('YYYY-MM-DD hh:mm:ss A')}]`)} ${msg ?? ''}`;
|
||||
|
||||
|
@ -832,7 +837,7 @@ export function okSpin(msg) {
|
|||
* @param {Error} err Error object
|
||||
* @param {Boolean} clear Clean the instance
|
||||
**/
|
||||
export function warnSpin(msg, err, clear) {
|
||||
export async function warnSpin(msg, err, clear) {
|
||||
if (JSON.parse(env.TIME_STAMPS) && msg)
|
||||
msg = `${chalk.gray(`[${new moment().format('YYYY-MM-DD hh:mm:ss A')}]`)} ${msg}`;
|
||||
|
||||
|
@ -840,7 +845,7 @@ export function warnSpin(msg, err, clear) {
|
|||
spinner.warn(msg);
|
||||
if (clear) spinner = null;
|
||||
}
|
||||
if (err) warning(err);
|
||||
if (err) await handler('warning', err);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -848,7 +853,7 @@ export function warnSpin(msg, err, clear) {
|
|||
*
|
||||
* @param {Error} err Error object
|
||||
**/
|
||||
export function failSpin(err) {
|
||||
export async function failSpin(err) {
|
||||
if (spinner) {
|
||||
spinner.fail();
|
||||
spinner = null;
|
||||
|
@ -861,12 +866,12 @@ export function failSpin(err) {
|
|||
*
|
||||
* @param {Error} err Error object
|
||||
**/
|
||||
export function criticalSpin(err) {
|
||||
export async function criticalSpin(err) {
|
||||
if (spinner) {
|
||||
spinner.fail();
|
||||
spinner = null;
|
||||
}
|
||||
criticalError(err);
|
||||
handler('critical', err);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -874,28 +879,36 @@ export function criticalSpin(err) {
|
|||
*
|
||||
* @param {String} msg String to show
|
||||
**/
|
||||
export function separator(msg) {
|
||||
console.log(chalk.gray(` ──────────────────────── ${msg}`));
|
||||
export async function separator(msg) {
|
||||
console.log(chalk.gray(`↺ ──────────────────────── ${msg}`));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Critical error.
|
||||
* Function to handle error messages.
|
||||
*
|
||||
* @param {String} type Type name
|
||||
* @param {Error} err Error object
|
||||
**/
|
||||
export function criticalError(err) {
|
||||
const msg = `${chalk.red.bold(arrow)} ${chalk.red.bold('[CRITICAL]')}`;
|
||||
console.log(`${msg} ${chalk.red(err.message)}`);
|
||||
process.exit();
|
||||
};
|
||||
export async function handler(type, err) {
|
||||
let header = (`${arrow} [${type.toUpperCase()}]`);
|
||||
let msg = (err.response?.status && err.response?.data?.message)
|
||||
? `${err.response.status} - ${err.response?.data?.message}`
|
||||
: err.message;
|
||||
|
||||
/**
|
||||
* Warning.
|
||||
*
|
||||
* @param {Error} err
|
||||
**/
|
||||
export function warning(err) {
|
||||
const msg = `${chalk.yellow.bold(arrow)} ${chalk.yellow.bold('[WARNING]')}`;
|
||||
console.log(`${msg} ${chalk.yellow((err.response?.status && err.response?.data?.message) ?? err.message)}`);
|
||||
switch (type) {
|
||||
case 'critical':
|
||||
header = chalk.red.bold(header);
|
||||
msg = chalk.red(msg);
|
||||
break;
|
||||
case 'warning':
|
||||
header = chalk.yellow.bold(header);
|
||||
msg = chalk.yellow(msg);
|
||||
break;
|
||||
default:
|
||||
console.error('Unhandled handler type');
|
||||
process.exit();
|
||||
};
|
||||
|
||||
console.log(header, msg);
|
||||
if (type === 'critical') process.exit();
|
||||
};
|
Loading…
Reference in New Issue