First commit
gitea/mylogger/pipeline/head There was a failure building this commit
Details
gitea/mylogger/pipeline/head There was a failure building this commit
Details
This commit is contained in:
commit
e57ccf6e41
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules
|
||||||
|
zongji
|
||||||
|
config/*.local.yml
|
|
@ -0,0 +1,35 @@
|
||||||
|
FROM debian:bullseye-slim
|
||||||
|
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# NodeJs
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
gnupg2 \
|
||||||
|
&& url -fsSL https://deb.nodesource.com/setup_14.x | bash - \
|
||||||
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Consumer
|
||||||
|
|
||||||
|
WORKDIR /mycdc
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm install --only=prod
|
||||||
|
|
||||||
|
ARG BUILD_ID=unknown
|
||||||
|
ARG VERSION
|
||||||
|
ENV VERSION $VERSION
|
||||||
|
RUN echo $VERSION
|
||||||
|
|
||||||
|
COPY \
|
||||||
|
LICENSE \
|
||||||
|
README.md \
|
||||||
|
mylogger.js \
|
||||||
|
index.js \
|
||||||
|
config.yml \
|
||||||
|
./
|
||||||
|
|
||||||
|
CMD ["node", "mylogger.js"]
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env groovy
|
||||||
|
|
||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
options {
|
||||||
|
disableConcurrentBuilds()
|
||||||
|
}
|
||||||
|
environment {
|
||||||
|
PROJECT_NAME = 'mycdc'
|
||||||
|
STACK_NAME = "${env.PROJECT_NAME}-${env.BRANCH_NAME}"
|
||||||
|
}
|
||||||
|
stages {
|
||||||
|
stage('Checkout') {
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
def packageJson = readJSON file: 'package.json'
|
||||||
|
env.VERSION = packageJson.version
|
||||||
|
}
|
||||||
|
configFileProvider([
|
||||||
|
configFile(fileId: "mycdc.groovy",
|
||||||
|
variable: 'GROOVY_FILE')
|
||||||
|
]) {
|
||||||
|
load env.GROOVY_FILE
|
||||||
|
}
|
||||||
|
setEnv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
when {branch 'master'}
|
||||||
|
environment {
|
||||||
|
CREDENTIALS = credentials('docker-registry')
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh 'docker login --username $CREDS_USR --password $CREDS_PSW $REGISTRY'
|
||||||
|
sh 'docker-compose build --build-arg BUILD_ID=$BUILD_ID --parallel'
|
||||||
|
sh 'docker-compose push'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Deploy') {
|
||||||
|
when {branch 'master'}
|
||||||
|
environment {
|
||||||
|
DOCKER_HOST = "${env.SWARM_HOST}"
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
sh "docker stack deploy --with-registry-auth --compose-file docker-compose.yml ${env.STACK_NAME}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
unsuccessful {
|
||||||
|
sendEmail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
Copyright (C) 2018 - Verdnatura Levante S.L.
|
||||||
|
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
On Debian systems, the complete text of the GNU General Public
|
||||||
|
License can be found in "/usr/share/common-licenses/GPL-3".
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Asynchronous DB calculations reading the binary log
|
||||||
|
|
||||||
|
## Enviroment setup
|
||||||
|
|
||||||
|
Because a bug with MariaDB wich it's fix is pending to be merged into main
|
||||||
|
project branch, a *zongji* fork must be cloned into project root directory.
|
||||||
|
More info at https://github.com/nevill/zongji/issues/143
|
||||||
|
```text
|
||||||
|
git clone https://github.com/juan-ferrer-toribio/zongji.git
|
||||||
|
cd zongji
|
||||||
|
git checkout fix-143
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply *zongji.sql* script into DB.
|
||||||
|
|
||||||
|
Copy *config.json* to *config.local.json* and place your local configuration
|
||||||
|
there.
|
||||||
|
|
||||||
|
Install dependencies.
|
||||||
|
```text
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run application
|
||||||
|
|
||||||
|
Launch app.
|
||||||
|
```text
|
||||||
|
node index.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Built With
|
||||||
|
|
||||||
|
* [Zongji](https://github.com/nevill/zongji)
|
||||||
|
* [MySQL2](https://github.com/sidorares/node-mysql2#readme)
|
|
@ -0,0 +1,36 @@
|
||||||
|
debug: true
|
||||||
|
testMode: false
|
||||||
|
db:
|
||||||
|
host: localhost
|
||||||
|
port: 3306
|
||||||
|
user: root
|
||||||
|
password: root
|
||||||
|
database: vn
|
||||||
|
showField:
|
||||||
|
- name
|
||||||
|
description
|
||||||
|
logs:
|
||||||
|
ticket:
|
||||||
|
logTable: clientLog
|
||||||
|
mainTable: ticket
|
||||||
|
tables:
|
||||||
|
- sale
|
||||||
|
- ticketTracking
|
||||||
|
client:
|
||||||
|
logTable: clientLog
|
||||||
|
mainTable: client
|
||||||
|
tables:
|
||||||
|
- client
|
||||||
|
- address
|
||||||
|
item:
|
||||||
|
logTable: itemLog
|
||||||
|
mainTable: item
|
||||||
|
tables:
|
||||||
|
- name: item
|
||||||
|
exclude:
|
||||||
|
- image
|
||||||
|
- supplyResponseFk
|
||||||
|
- itemTag
|
||||||
|
route:
|
||||||
|
logTable: routeLog
|
||||||
|
mainTable: route
|
|
@ -0,0 +1,30 @@
|
||||||
|
code: mylogger
|
||||||
|
debug: false
|
||||||
|
testMode: false
|
||||||
|
pingInterval: 60
|
||||||
|
flushInterval: 10
|
||||||
|
db:
|
||||||
|
host: localhost
|
||||||
|
port: 3306
|
||||||
|
user: zongji
|
||||||
|
password: password
|
||||||
|
database: util
|
||||||
|
showFields:
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
castTypes:
|
||||||
|
tinyint: boolean
|
||||||
|
logs:
|
||||||
|
item:
|
||||||
|
logTable: vn.itemLog
|
||||||
|
mainTable: item
|
||||||
|
tables:
|
||||||
|
- name: item
|
||||||
|
exclude:
|
||||||
|
- image
|
||||||
|
- supplyResponseFk
|
||||||
|
types:
|
||||||
|
id: number
|
||||||
|
isPrinted: boolean
|
||||||
|
- name: itemTag
|
||||||
|
relation: itemFk
|
|
@ -0,0 +1,23 @@
|
||||||
|
version: '3.7'
|
||||||
|
services:
|
||||||
|
main:
|
||||||
|
image: registry.verdnatura.es/mylogger
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
- VERSION=${VERSION:?}
|
||||||
|
configs:
|
||||||
|
- source: config
|
||||||
|
target: /mylogger/config.local.yml
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 1G
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.role == worker
|
||||||
|
configs:
|
||||||
|
config:
|
||||||
|
external: true
|
||||||
|
name: mylogger_config
|
|
@ -0,0 +1,17 @@
|
||||||
|
const MyLogger = require('./mylogger');
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const mylogger = new MyLogger()
|
||||||
|
await mylogger.start();
|
||||||
|
|
||||||
|
process.on('SIGINT', async function() {
|
||||||
|
console.log('Got SIGINT.');
|
||||||
|
try {
|
||||||
|
await mylogger.stop();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
main();
|
|
@ -0,0 +1,611 @@
|
||||||
|
require('require-yaml');
|
||||||
|
require('colors');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const ZongJi = require('./zongji');
|
||||||
|
const mysql = require('mysql2/promise');
|
||||||
|
|
||||||
|
const allEvents = [
|
||||||
|
'writerows',
|
||||||
|
'updaterows',
|
||||||
|
'deleterows'
|
||||||
|
];
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
writerows: 'insert',
|
||||||
|
updaterows: 'update',
|
||||||
|
deleterows: 'delete'
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = class MyLogger {
|
||||||
|
constructor() {
|
||||||
|
this.running = false;
|
||||||
|
this.filename = null;
|
||||||
|
this.position = null;
|
||||||
|
this.schemaMap = new Map();
|
||||||
|
this.logMap = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
const defaultConfig = require('./config.yml');
|
||||||
|
const conf = this.conf = Object.assign({}, defaultConfig);
|
||||||
|
const localPath = path.join(__dirname, 'config.local.yml');
|
||||||
|
if (fs.existsSync(localPath)) {
|
||||||
|
const localConfig = require(localPath);
|
||||||
|
Object.assign(conf, localConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultSchema = conf.db.database;
|
||||||
|
function parseTable(tableString) {
|
||||||
|
let name, schema;
|
||||||
|
const split = tableString.split('.');
|
||||||
|
if (split.length == 1) {
|
||||||
|
name = split[0];
|
||||||
|
schema = defaultSchema;
|
||||||
|
} else {
|
||||||
|
[name, schema] = split;
|
||||||
|
}
|
||||||
|
return {name, schema};
|
||||||
|
}
|
||||||
|
|
||||||
|
const schemaMap = this.schemaMap;
|
||||||
|
function addTable(tableConf, logInfo) {
|
||||||
|
if (typeof tableConf == 'string')
|
||||||
|
tableConf = {name: tableConf};
|
||||||
|
const table = parseTable(tableConf.name);
|
||||||
|
|
||||||
|
let tableMap = schemaMap.get(table.schema);
|
||||||
|
if (!tableMap) {
|
||||||
|
tableMap = new Map();
|
||||||
|
schemaMap.set(table.schema, tableMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tableInfo = tableMap.get(table.name);
|
||||||
|
if (!tableInfo) {
|
||||||
|
tableInfo = {
|
||||||
|
conf: tableConf,
|
||||||
|
log: logInfo
|
||||||
|
};
|
||||||
|
tableMap.set(table.name, tableInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(tableInfo, {
|
||||||
|
conf: tableConf,
|
||||||
|
exclude: new Set(tableConf.exclude),
|
||||||
|
castTypes: new Map(),
|
||||||
|
columns: new Map(),
|
||||||
|
showField: tableConf.showField,
|
||||||
|
relation: tableConf.relation
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tableConf.types)
|
||||||
|
for (const col in tableConf.types)
|
||||||
|
tableInfo.castTypes.set(col, tableConf.types[col]);
|
||||||
|
|
||||||
|
return tableInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const logName in conf.logs) {
|
||||||
|
const logConf = conf.logs[logName];
|
||||||
|
const logInfo = {
|
||||||
|
conf: logConf,
|
||||||
|
table: parseTable(logConf.logTable),
|
||||||
|
mainTable: parseTable(logConf.mainTable)
|
||||||
|
};
|
||||||
|
this.logMap.set(logName, logInfo);
|
||||||
|
|
||||||
|
const mainTable = addTable(logInfo.mainTable, logInfo);
|
||||||
|
mainTable.isMain = true;
|
||||||
|
|
||||||
|
if (logConf.tables)
|
||||||
|
for (const tableConf of logConf.tables){
|
||||||
|
const table = addTable(tableConf, logInfo);
|
||||||
|
if (table !== mainTable) {
|
||||||
|
Object.assign(table, {
|
||||||
|
main: mainTable,
|
||||||
|
isMain: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const includeSchema = {};
|
||||||
|
for (const [schemaName, tableMap] of this.schemaMap)
|
||||||
|
includeSchema[schemaName] = Array.from(tableMap.keys());
|
||||||
|
|
||||||
|
this.opts = {
|
||||||
|
includeEvents: [
|
||||||
|
'rotate',
|
||||||
|
'tablemap',
|
||||||
|
'writerows',
|
||||||
|
'updaterows',
|
||||||
|
'deleterows'
|
||||||
|
],
|
||||||
|
includeSchema
|
||||||
|
};
|
||||||
|
|
||||||
|
if (conf.testMode)
|
||||||
|
console.log('Test mode enabled, just logging queries to console.');
|
||||||
|
|
||||||
|
console.log('Starting process.');
|
||||||
|
await this.init();
|
||||||
|
console.log('Process started.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async stop() {
|
||||||
|
console.log('Stopping process.');
|
||||||
|
await this.end();
|
||||||
|
console.log('Process stopped.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
const {conf} = this;
|
||||||
|
this.debug('MyLogger', 'Initializing.');
|
||||||
|
this.onErrorListener = err => this.onError(err);
|
||||||
|
|
||||||
|
// DB connection
|
||||||
|
|
||||||
|
const db = this.db = await mysql.createConnection(conf.db);
|
||||||
|
db.on('error', this.onErrorListener);
|
||||||
|
|
||||||
|
for (const logInfo of this.logMap.values()) {
|
||||||
|
const table = logInfo.table;
|
||||||
|
const sqlTable = `${db.escapeId(table.schema)}.${db.escapeId(table.name)}`
|
||||||
|
logInfo.addStmt = await db.prepare(
|
||||||
|
`INSERT INTO ${sqlTable}
|
||||||
|
SET originFk = ?,
|
||||||
|
userFk = ?,
|
||||||
|
action = ?,
|
||||||
|
creationDate = ?,
|
||||||
|
changedModel = ?,
|
||||||
|
oldInstance = ?,
|
||||||
|
newInstance = ?,
|
||||||
|
changedModelId = ?,
|
||||||
|
changedModelValue = ?`
|
||||||
|
);
|
||||||
|
logInfo.fetchStmt = await db.prepare(
|
||||||
|
`SELECT id FROM ${sqlTable}
|
||||||
|
WHERE changedModel = ?
|
||||||
|
AND changedModelId = ?
|
||||||
|
AND action = 'delete'`
|
||||||
|
);
|
||||||
|
logInfo.updateStmt = await db.prepare(
|
||||||
|
`UPDATE ${sqlTable}
|
||||||
|
SET originFk = ?,
|
||||||
|
creationDate = ?,
|
||||||
|
oldInstance = ?,
|
||||||
|
changedModelValue = ?
|
||||||
|
WHERE id = ?`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [schema, tableMap] of this.schemaMap)
|
||||||
|
for (const [table, tableInfo] of tableMap) {
|
||||||
|
|
||||||
|
// Fetch columns & types
|
||||||
|
|
||||||
|
const [dbCols] = await db.query(
|
||||||
|
`SELECT COLUMN_NAME \`col\`, DATA_TYPE \`type\`, COLUMN_DEFAULT \`def\`
|
||||||
|
FROM information_schema.\`COLUMNS\`
|
||||||
|
WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?`,
|
||||||
|
[table, schema]
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const {col, type, def} of dbCols) {
|
||||||
|
if (!tableInfo.exclude.has(col))
|
||||||
|
tableInfo.columns.set(col, {type, def});
|
||||||
|
|
||||||
|
const castType = conf.castTypes[type];
|
||||||
|
if (castType && !tableInfo.castTypes.has(col))
|
||||||
|
tableInfo.castTypes.set(col, castType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch primary key
|
||||||
|
|
||||||
|
const [dbPks] = await db.query(
|
||||||
|
`SELECT COLUMN_NAME idName
|
||||||
|
FROM information_schema.KEY_COLUMN_USAGE
|
||||||
|
WHERE CONSTRAINT_NAME = 'PRIMARY'
|
||||||
|
AND TABLE_NAME = ?
|
||||||
|
AND TABLE_SCHEMA = ?`,
|
||||||
|
[table, schema]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!dbPks.length)
|
||||||
|
throw new Error(`Primary not found for table: ${schema}.${table}`);
|
||||||
|
if (dbPks.length > 1)
|
||||||
|
throw new Error(`Only one column primary is supported: ${schema}.${table}`);
|
||||||
|
|
||||||
|
for (const {idName} of dbPks)
|
||||||
|
tableInfo.idName = idName;
|
||||||
|
|
||||||
|
// Get show field
|
||||||
|
|
||||||
|
if (!tableInfo.showField) {
|
||||||
|
for (const showField of conf.showFields) {
|
||||||
|
if (tableInfo.columns.has(showField)) {
|
||||||
|
tableInfo.showField = showField;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [schema, tableMap] of this.schemaMap)
|
||||||
|
for (const [table, tableInfo] of tableMap) {
|
||||||
|
|
||||||
|
// Fetch relation
|
||||||
|
|
||||||
|
if (!tableInfo.relation && !tableInfo.isMain) {
|
||||||
|
const mainTable = tableInfo.log.mainTable;
|
||||||
|
const mainTableInfo = this.schemaMap
|
||||||
|
.get(mainTable.schema)
|
||||||
|
.get(mainTable.name);
|
||||||
|
|
||||||
|
const [relations] = await db.query(
|
||||||
|
`SELECT COLUMN_NAME relation
|
||||||
|
FROM information_schema.KEY_COLUMN_USAGE
|
||||||
|
WHERE TABLE_NAME = ?
|
||||||
|
AND TABLE_SCHEMA = ?
|
||||||
|
AND REFERENCED_TABLE_NAME = ?
|
||||||
|
AND REFERENCED_TABLE_SCHEMA = ?
|
||||||
|
AND REFERENCED_COLUMN_NAME = ?`,
|
||||||
|
[
|
||||||
|
table,
|
||||||
|
schema,
|
||||||
|
mainTable.name,
|
||||||
|
mainTable.schema,
|
||||||
|
mainTableInfo.idName
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.debug(
|
||||||
|
table,
|
||||||
|
schema,
|
||||||
|
mainTable.name,
|
||||||
|
mainTable.schema,
|
||||||
|
mainTableInfo.idName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!relations.length)
|
||||||
|
throw new Error(`No relation to main table found for table: ${schema}.${table}`);
|
||||||
|
if (relations.length > 1)
|
||||||
|
throw new Error(`Found more multiple relations to main table: ${schema}.${table}`);
|
||||||
|
|
||||||
|
for (const {relation} of relations)
|
||||||
|
tableInfo.relation = relation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zongji
|
||||||
|
|
||||||
|
const zongji = new ZongJi(conf.db);
|
||||||
|
this.zongji = zongji;
|
||||||
|
|
||||||
|
this.onBinlogListener = evt => this.onBinlog(evt);
|
||||||
|
zongji.on('binlog', this.onBinlogListener);
|
||||||
|
|
||||||
|
const [res] = await db.query(
|
||||||
|
'SELECT `logName`, `position` FROM `util`.`binlogQueue` WHERE code = ?',
|
||||||
|
[conf.code]
|
||||||
|
);
|
||||||
|
if (res.length) {
|
||||||
|
const [row] = res;
|
||||||
|
this.filename = row.logName;
|
||||||
|
this.position = row.position;
|
||||||
|
Object.assign(this.opts, {
|
||||||
|
filename: this.filename,
|
||||||
|
position: this.position
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
this.opts.startAtEnd = true;
|
||||||
|
|
||||||
|
this.debug('Zongji', 'Starting.');
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const onReady = () => {
|
||||||
|
zongji.off('error', onError);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
const onError = err => {
|
||||||
|
this.zongji = null;
|
||||||
|
zongji.off('ready', onReady);
|
||||||
|
zongji.off('binlog', this.onBinlogListener);
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
zongji.once('ready', onReady);
|
||||||
|
zongji.once('error', onError);
|
||||||
|
zongji.start(this.opts);
|
||||||
|
});
|
||||||
|
this.debug('Zongji', 'Started.');
|
||||||
|
|
||||||
|
this.zongji.on('error', this.onErrorListener);
|
||||||
|
|
||||||
|
this.flushInterval = setInterval(
|
||||||
|
() => this.flushQueue(), conf.flushInterval * 1000);
|
||||||
|
this.pingInterval = setInterval(
|
||||||
|
() => this.connectionPing(), conf.pingInterval * 1000);
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
|
||||||
|
this.running = true;
|
||||||
|
this.debug('MyLogger', 'Initialized.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async end(silent) {
|
||||||
|
const zongji = this.zongji;
|
||||||
|
if (!zongji) return;
|
||||||
|
|
||||||
|
this.debug('MyLogger', 'Ending.');
|
||||||
|
|
||||||
|
// Zongji
|
||||||
|
|
||||||
|
clearInterval(this.flushInterval);
|
||||||
|
clearInterval(this.pingInterval);
|
||||||
|
zongji.off('binlog', this.onBinlogListener);
|
||||||
|
zongji.off('error', this.onErrorListener);
|
||||||
|
this.zongji = null;
|
||||||
|
this.running = false;
|
||||||
|
|
||||||
|
this.debug('Zongji', 'Stopping.');
|
||||||
|
// FIXME: Cannot call Zongji.stop(), it doesn't wait to end connection
|
||||||
|
zongji.connection.destroy(() => {
|
||||||
|
console.log('zongji.connection.destroy');
|
||||||
|
});
|
||||||
|
await new Promise(resolve => {
|
||||||
|
zongji.ctrlConnection.query('KILL ?', [zongji.connection.threadId],
|
||||||
|
err => {
|
||||||
|
if (err && err.code !== 'ER_NO_SUCH_THREAD' && !silent)
|
||||||
|
console.error(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
zongji.ctrlConnection.destroy(() => {
|
||||||
|
console.log('zongji.ctrlConnection.destroy');
|
||||||
|
});
|
||||||
|
zongji.emit('stopped');
|
||||||
|
this.debug('Zongji', 'Stopped.');
|
||||||
|
|
||||||
|
// DB connection
|
||||||
|
|
||||||
|
this.db.off('error', this.onErrorListener);
|
||||||
|
// FIXME: mysql2/promise bug, db.end() ends process
|
||||||
|
this.db.on('error', () => {});
|
||||||
|
try {
|
||||||
|
await this.db.end();
|
||||||
|
} catch (err) {
|
||||||
|
if (!silent)
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
|
||||||
|
this.debug('MyLogger', 'Ended.');
|
||||||
|
}
|
||||||
|
|
||||||
|
async tryRestart() {
|
||||||
|
try {
|
||||||
|
await this.init();
|
||||||
|
console.log('Process restarted.');
|
||||||
|
} catch(err) {
|
||||||
|
setTimeout(() => this.tryRestart(), 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onError(err) {
|
||||||
|
console.log(`Error: ${err.code}: ${err.message}`);
|
||||||
|
try {
|
||||||
|
await this.end(true);
|
||||||
|
} catch(e) {}
|
||||||
|
|
||||||
|
switch (err.code) {
|
||||||
|
case 'PROTOCOL_CONNECTION_LOST':
|
||||||
|
case 'ECONNRESET':
|
||||||
|
console.log('Trying to restart process.');
|
||||||
|
await this.tryRestart();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBinlog(evt) {
|
||||||
|
//evt.dump();
|
||||||
|
const eventName = evt.getEventName();
|
||||||
|
let position = evt.nextPosition;
|
||||||
|
|
||||||
|
switch (eventName) {
|
||||||
|
case 'rotate':
|
||||||
|
this.filename = evt.binlogName;
|
||||||
|
position = evt.position;
|
||||||
|
console.log(`[${eventName}] filename: ${this.filename}`, `position: ${this.position}, nextPosition: ${evt.nextPosition}`);
|
||||||
|
break;
|
||||||
|
case 'writerows':
|
||||||
|
case 'deleterows':
|
||||||
|
case 'updaterows':
|
||||||
|
this.onRowEvent(evt, eventName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.position = position;
|
||||||
|
this.flushed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onRowEvent(evt, eventName) {
|
||||||
|
const table = evt.tableMap[evt.tableId];
|
||||||
|
const tableName = table.tableName;
|
||||||
|
const tableMap = this.schemaMap.get(table.parentSchema);
|
||||||
|
if (!tableMap) return;
|
||||||
|
|
||||||
|
const tableInfo = tableMap.get(tableName);
|
||||||
|
if (!tableInfo) return;
|
||||||
|
|
||||||
|
const action = actions[eventName];
|
||||||
|
const columns = tableInfo.columns;
|
||||||
|
let changes = [];
|
||||||
|
|
||||||
|
function castValue(col, value) {
|
||||||
|
switch(tableInfo.castTypes.get(col)) {
|
||||||
|
case 'boolean':
|
||||||
|
return !!value;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action == 'update') {
|
||||||
|
for (const row of evt.rows) {
|
||||||
|
let nColsChanged = 0;
|
||||||
|
const before = row.before;
|
||||||
|
const after = row.after;
|
||||||
|
const oldI = {};
|
||||||
|
const newI = {};
|
||||||
|
|
||||||
|
for (const col in before) {
|
||||||
|
if (columns.has(col)
|
||||||
|
&& after[col] !== undefined
|
||||||
|
&& !equals(after[col], before[col])) {
|
||||||
|
if (before[col] !== null)
|
||||||
|
oldI[col] = castValue(col, before[col]);
|
||||||
|
newI[col] = castValue(col, after[col]);
|
||||||
|
nColsChanged++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nColsChanged)
|
||||||
|
changes.push({row: after, oldI, newI});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const cols = columns.keys();
|
||||||
|
|
||||||
|
for (const row of evt.rows) {
|
||||||
|
const instance = {};
|
||||||
|
|
||||||
|
for (const col of cols) {
|
||||||
|
if (row[col] !== null)
|
||||||
|
instance[col] = castValue(col, row[col]);
|
||||||
|
}
|
||||||
|
|
||||||
|
changes.push({row, instance});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changes.length) return;
|
||||||
|
|
||||||
|
if (this.debug) {
|
||||||
|
console.debug('Log:'.blue,
|
||||||
|
`${tableName}(${changes}) [${eventName}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const logInfo = tableInfo.log;
|
||||||
|
const isDelete = action == 'delete';
|
||||||
|
|
||||||
|
for (const change of changes) {
|
||||||
|
let newI, oldI;
|
||||||
|
const row = change.row;
|
||||||
|
|
||||||
|
switch(action) {
|
||||||
|
case 'update':
|
||||||
|
newI = change.newI;
|
||||||
|
oldI = change.oldI;
|
||||||
|
break;
|
||||||
|
case 'insert':
|
||||||
|
newI = change.instance;
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
oldI = change.instance;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelId = row[tableInfo.idName];
|
||||||
|
const modelValue = tableInfo.showField
|
||||||
|
? row[tableInfo.showField] || null
|
||||||
|
: null;
|
||||||
|
const created = new Date(evt.timestamp);
|
||||||
|
const oldInstance = oldI ? JSON.stringify(oldI) : null;
|
||||||
|
const originFk = !tableInfo.isMain
|
||||||
|
? row[tableInfo.relation]
|
||||||
|
: modelId;
|
||||||
|
|
||||||
|
let deleteRow;
|
||||||
|
|
||||||
|
if (isDelete) {
|
||||||
|
[[deleteRow]] = await logInfo.fetchStmt.execute([
|
||||||
|
tableName, modelId
|
||||||
|
]);
|
||||||
|
if (deleteRow)
|
||||||
|
await logInfo.updateStmt.execute([
|
||||||
|
originFk,
|
||||||
|
created,
|
||||||
|
oldInstance,
|
||||||
|
modelValue,
|
||||||
|
deleteRow.id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (!isDelete || !deleteRow) {
|
||||||
|
await logInfo.addStmt.execute([
|
||||||
|
originFk,
|
||||||
|
row.editorFk || null,
|
||||||
|
action,
|
||||||
|
created,
|
||||||
|
tableName,
|
||||||
|
oldInstance,
|
||||||
|
newI ? JSON.stringify(newI) : null,
|
||||||
|
modelId,
|
||||||
|
modelValue
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async flushQueue() {
|
||||||
|
if (this.flushed) return;
|
||||||
|
const position = this.nextPosition;
|
||||||
|
|
||||||
|
if (position) {
|
||||||
|
const filename = this.nextFilename;
|
||||||
|
this.debug('Flush', `filename: ${filename}, position: ${position}`);
|
||||||
|
|
||||||
|
const replaceQuery =
|
||||||
|
'REPLACE INTO `util`.`binlogQueue` SET `code` = ?, `logName` = ?, `position` = ?';
|
||||||
|
if (!this.conf.testMode)
|
||||||
|
await this.db.query(replaceQuery, [this.conf.code, filename, position]);
|
||||||
|
|
||||||
|
this.flushed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nextFilename = this.filename;
|
||||||
|
this.nextPosition = this.position;
|
||||||
|
}
|
||||||
|
|
||||||
|
async connectionPing() {
|
||||||
|
this.debug('Ping', 'Sending ping to database.');
|
||||||
|
|
||||||
|
// FIXME: Should Zongji.connection be pinged?
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
this.zongji.ctrlConnection.ping(err => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
await this.db.ping();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(namespace, message) {
|
||||||
|
if (this.conf.debug)
|
||||||
|
console.debug(`${namespace}:`.blue, message.yellow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function equals(a, b) {
|
||||||
|
if (a === b)
|
||||||
|
return true;
|
||||||
|
const type = typeof a;
|
||||||
|
if (a == null || b == null || type !== typeof b)
|
||||||
|
return false;
|
||||||
|
if (type === 'object' && a.constructor === b.constructor) {
|
||||||
|
if (a instanceof Date)
|
||||||
|
return a.getTime() === b.getTime();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,508 @@
|
||||||
|
{
|
||||||
|
"name": "mycdc",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"amqplib": "^0.10.3",
|
||||||
|
"colors": "^1.4.0",
|
||||||
|
"mysql2": "^2.3.3",
|
||||||
|
"require-yaml": "^0.0.1",
|
||||||
|
"zongji": "file:../zongji"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"../zongji": {},
|
||||||
|
"node_modules/@acuminous/bitsyntax": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-more-ints": "~1.0.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"safe-buffer": "~5.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/amqplib": {
|
||||||
|
"version": "0.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz",
|
||||||
|
"integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@acuminous/bitsyntax": "^0.1.2",
|
||||||
|
"buffer-more-ints": "~1.0.0",
|
||||||
|
"readable-stream": "1.x >=1.1.9",
|
||||||
|
"url-parse": "~1.5.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
|
},
|
||||||
|
"node_modules/buffer-more-ints": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
||||||
|
},
|
||||||
|
"node_modules/colors": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.1.90"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
|
"node_modules/is-property": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
|
||||||
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/long": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
|
},
|
||||||
|
"node_modules/lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"node_modules/mysql2": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==",
|
||||||
|
"dependencies": {
|
||||||
|
"denque": "^2.0.1",
|
||||||
|
"generate-function": "^2.3.1",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"long": "^4.0.0",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"named-placeholders": "^1.1.2",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^4.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||||
|
"dependencies": {
|
||||||
|
"pseudomap": "^1.0.2",
|
||||||
|
"yallist": "^2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/yallist": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
|
||||||
|
},
|
||||||
|
"node_modules/pseudomap": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
|
||||||
|
},
|
||||||
|
"node_modules/querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "1.1.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||||
|
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.1",
|
||||||
|
"isarray": "0.0.1",
|
||||||
|
"string_decoder": "~0.10.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/require-yaml": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"js-yaml": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"node_modules/seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
|
"node_modules/sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
|
||||||
|
},
|
||||||
|
"node_modules/url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
|
},
|
||||||
|
"node_modules/zongji": {
|
||||||
|
"resolved": "../zongji",
|
||||||
|
"link": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@acuminous/bitsyntax": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-more-ints": "~1.0.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"safe-buffer": "~5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"amqplib": {
|
||||||
|
"version": "0.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz",
|
||||||
|
"integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==",
|
||||||
|
"requires": {
|
||||||
|
"@acuminous/bitsyntax": "^0.1.2",
|
||||||
|
"buffer-more-ints": "~1.0.0",
|
||||||
|
"readable-stream": "1.x >=1.1.9",
|
||||||
|
"url-parse": "~1.5.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
|
},
|
||||||
|
"buffer-more-ints": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
||||||
|
},
|
||||||
|
"colors": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
|
||||||
|
},
|
||||||
|
"core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
|
||||||
|
},
|
||||||
|
"generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"requires": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
|
"is-property": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
|
},
|
||||||
|
"isarray": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
|
||||||
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"long": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
|
},
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
|
"requires": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
},
|
||||||
|
"mysql2": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==",
|
||||||
|
"requires": {
|
||||||
|
"denque": "^2.0.1",
|
||||||
|
"generate-function": "^2.3.1",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"long": "^4.0.0",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"named-placeholders": "^1.1.2",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"named-placeholders": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||||
|
"requires": {
|
||||||
|
"lru-cache": "^4.1.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "4.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||||
|
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||||
|
"requires": {
|
||||||
|
"pseudomap": "^1.0.2",
|
||||||
|
"yallist": "^2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pseudomap": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
|
||||||
|
},
|
||||||
|
"querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "1.1.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||||
|
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
|
||||||
|
"requires": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.1",
|
||||||
|
"isarray": "0.0.1",
|
||||||
|
"string_decoder": "~0.10.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-yaml": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
||||||
|
"requires": {
|
||||||
|
"js-yaml": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
|
"sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "0.10.31",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||||
|
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
|
||||||
|
},
|
||||||
|
"url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"requires": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
|
},
|
||||||
|
"zongji": {
|
||||||
|
"version": "file:../zongji"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"amqplib": "^0.10.3",
|
||||||
|
"colors": "^1.4.0",
|
||||||
|
"mysql2": "^2.3.3",
|
||||||
|
"require-yaml": "^0.0.1",
|
||||||
|
"zongji": "file:../zongji"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
CREATE TABLE `util`.`binlogQueue`(
|
||||||
|
`code` VARCHAR(255) NOT NULL,
|
||||||
|
`logName` VARCHAR(255) NOT NULL,
|
||||||
|
`position` BIGINT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (`code`)
|
||||||
|
) ENGINE = InnoDB;
|
||||||
|
|
||||||
|
CREATE USER 'zongji'@'%' IDENTIFIED BY 'password';
|
||||||
|
GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON *.* TO 'zongji'@'%';
|
||||||
|
|
||||||
|
GRANT INSERT, DELETE ON `util`.* TO 'zongji'@'%';
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `util`.`binlogQueue`;
|
||||||
|
DROP USER 'zongji'@'%';
|
Loading…
Reference in New Issue