forked from oknosoft/windowbuilder-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackup.js
More file actions
139 lines (124 loc) · 3.72 KB
/
backup.js
File metadata and controls
139 lines (124 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* ### Модуль записи данных из couchdb в файл *.json
*
* @module restore
*
* Created by Evgeniy Malyarov on 16.06.2018.
*/
/**
* ### Переменные окружения
* DEBUG "wb:*,-not_this"
* ZONE 21
* DBPWD admin
* DBUSER admin
* COUCHPATH http://cou221:5984/wb_
*/
'use strict';
const debug = require('debug')('wb:backup');
const PouchDB = require('./pouchdb');
const fs = require('fs');
const JSZip = require('jszip');
const yargs = require('yargs')
.demand(1)
.strict()
.version('v', 'Show version', '0.0.1').alias('v', 'version')
.help('h').alias('h', 'help')
.example('node backup database wb_21_doc', 'backup database `wb_21_doc` to `wb_21_doc.json` file')
.command(
'database [name]',
'backup database',
(yargs) => yargs.positional('name', {type: 'string', describe: 'empty database name'}),
({name}) => {
if(name) {
// получаем параметры сеанса
const {DBUSER, DBPWD, COUCHPATH} = process.env;
const prefix = 'wb_';
// подключаемся к базе данных
const src = new PouchDB(`${COUCHPATH.replace(prefix, '')}${name}`, {
auth: {
username: DBUSER,
password: DBPWD
},
skip_setup: true,
ajax: {timeout: 100000}
});
let ind = 0;
function add (rows) {
return new Promise((resolve, reject) => {
let chank = '';
for(const row of rows) {
chank += JSON.stringify(row.doc) + '\n';
}
const zip = new JSZip();
ind++;
let suffix = ind.toString();
while (suffix.length < 5) {
suffix = '0' + suffix;
}
const file = fs.createWriteStream(`${name}_${suffix}.zip`);
zip.file(`${name}_${ind}.json`, chank, {
compression: 'DEFLATE',
compressionOptions: {level: 9}
});
zip.generateNodeStream({streamFiles:true})
.pipe(file)
.on('finish', function () {
// JSZip generates a readable stream with a "end" event,
// but is piped here in a writable stream which emits a "finish" event.
resolve();
});
});
}
const opt = {
include_docs: true,
attachments: true,
startkey: '',
endkey: '\u0fff',
limit: 3000,
}
src.info()
.then((info) => {
debug(`connected to ${info.host}, doc count: ${info.doc_count}`);
return step(src, add, opt);
})
.then(() => {
debug('all done');
//process.exit(0);
})
.catch((err) => {
debug(err);
process.exit(1);
});
}
else {
yargs.showHelp();
process.exit(1);
}
})
.epilog('\nMore information about the library: https://github.com/oknosoft/windowbuilder');
debug('required');
const {argv} = yargs;
if(!argv._.length){
yargs.showHelp();
process.exit(1);
}
let docs = 0;
const mb = 1024 * 1024;
function step(src, add, opt) {
return src.allDocs(opt)
.then(({rows}) => {
// повторяем, пока есть данные
if(rows.length) {
// обновляем ключ для следующей выборки
opt.startkey = rows[rows.length - 1].key;
opt.skip = 1;
docs += rows.length;
process.stdout.write(`\u001b[2K\u001b[0E\t${docs} docs written`);
// записываем в stream
return add(rows)
.then(() => {
return step(src, add, opt);
});
}
});
}