UNPKG

5.02 kBJavaScriptView Raw
1#! /usr/bin/env node
2// vim:set sw=2 ts=2 sts=2 ft=javascript expandtab:
3'use strict';
4
5var program = require('commander'),
6 fs = require('fs'),
7 path = require('path');
8
9var ueberDB = require('ueberdb2'),
10 jsonminify = require('jsonminify'),
11 forever = require('async/forever'),
12 eachSeries = require('async/eachSeries'),
13 eachOfSeries = require('async/eachOfSeries');
14
15var JOBQ_PREFIX = require('../storage').DBPREFIX.JOBQ;
16
17// Arguments handling
18program
19 .version('0.1.0')
20 .option('-s, --settings <file>', '[MANDATORY] the path to your Etherpad\'s settings.json file')
21 .option('-q, --quiet', '[OPTIONAL] low verbosity')
22 .option('-o, --oneshot', '[OPTIONAL] don\'t start a loop, process the jobs and exit')
23 .parse(process.argv);
24
25// Check that we have the mandatory arguments
26if (!program.settings) {
27 console.log('');
28 console.log('=====================================================================');
29 console.log(' You must provide the path to your Etherpad\'s settings.json file!');
30 console.log('=====================================================================');
31 program.help();
32}
33
34// Try to parse the settings
35var settingsFilename = path.resolve(program.settings);
36var settingsStr = fs.readFileSync(settingsFilename).toString();
37var settings;
38try {
39 if(settingsStr) {
40 settingsStr = jsonminify(settingsStr).replace(',]',']').replace(',}','}');
41 settings = JSON.parse(settingsStr);
42 }
43} catch(e) {
44 console.error('There was an error processing your settings.json file: '+e.message);
45 process.exit(1);
46}
47
48// Open the database
49var db = new ueberDB.database(settings.dbType, { cache: 0, writeInterval: 0 });
50
51/*
52 * Functions
53 */
54function exitIfErr(err) {
55 console.log('=====================');
56 console.error(err);
57 return db.doShutdown(function() { process.exit(1); });
58}
59
60// Remove record from DB
61function removeRecord(key, callback) {
62 db.remove(key, function(err) {
63 if (err) { return exitIfErr(err); }
64 callback();
65 });
66}
67
68function deletePads(nextLoop) {
69 if (!program.quiet) { console.log('Entering loop'); }
70
71 db.findKeys(JOBQ_PREFIX+'deletePad:*', null, function(err, pads) {
72 if (err) { return exitIfErr(err); }
73
74 if (pads !== null && pads.length > 0) {
75 if (!program.quiet) { console.log('Pads to delete: '+pads); }
76
77 eachOfSeries(pads, function(padId, index, next) {
78 padId = padId.substring(26); // remove "mypads:jobqueue:deletePad:"
79
80 if (!program.quiet) { console.log('Starting deletion of '+padId); }
81
82 // Cascade deletion process
83 // 0. Get the readonly name of the pad
84 db.get('pad2readonly:'+padId, function(err, readonly2pad) {
85 if (err) { return exitIfErr(err); }
86
87 // 1. Delete the readonly2pad record
88 db.remove('readonly2pad:'+readonly2pad, function(err) {
89 if (err) { return exitIfErr(err); }
90
91 // 2. Delete the pad2readonly:padId record
92 db.remove('pad2readonly:'+padId, function(err) {
93 if (err) { return exitIfErr(err); }
94
95 // 3. The pad:padId record has already been deleted through PadManager.removePad
96 // called from MyPads
97
98 // 4. Check for revs records
99 db.findKeys('pad:'+padId+':revs:*', null, function(err, keys) {
100 if (err) { return exitIfErr(err); }
101
102 // 5. Delete the revs records
103 eachSeries(keys, removeRecord, function(err) {
104 if (err) { return exitIfErr(err); }
105
106 // 6. Check for chat records
107 db.findKeys('pad:'+padId+':chat:*', null, function(err, keys) {
108 if (err) { return exitIfErr(err); }
109
110 // 7. Delete the chat records
111 eachSeries(keys, removeRecord, function(err) {
112 if (err) { return exitIfErr(err); }
113
114 // 8. Remove the job
115 db.remove('mypads:jobqueue:deletePad:'+padId, function(err) {
116 if (err) { return exitIfErr(err); }
117
118 if (!program.quiet) { console.log('End deletion of '+padId); }
119 return next();
120 });
121 });
122 });
123 });
124 });
125 });
126 });
127 });
128 }, function(err) {
129 if (err) { return exitIfErr(err); }
130
131 if (program.oneshot) {
132 return db.doShutdown(function() { process.exit(0); });
133 } else {
134 nextLoop();
135 }
136 });
137 } else {
138 if (!program.quiet) { console.log('No pad to process'); }
139
140 if (program.oneshot) {
141 return db.doShutdown(function() { process.exit(0); });
142 } else {
143 setTimeout(nextLoop, 1000);
144 }
145 }
146 });
147}
148
149/*
150 * Start loop
151 */
152db.init(function(err) {
153 if (err) { return exitIfErr(err); }
154 if (program.oneshot) {
155 deletePads();
156 } else {
157 forever(deletePads, exitIfErr);
158 }
159});