Skip to content

Commit c13c227

Browse files
committed
Merge branch 'master' into next
# Conflicts: # frontend/express/public/javascripts/countly/countly.template.js
2 parents bb144d1 + 57e2e64 commit c13c227

File tree

137 files changed

+1227
-697
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+1227
-697
lines changed

.travis.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ before_script:
2020
- nodejs --version
2121
- ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --version
2222
- cat ${PWD}/mongod.log
23-
script: sudo npm test
23+
script:
24+
- countly shellcheck
25+
- sudo npm test
2426
after_script:
2527
- cat log/countly-api.log
2628
- cat log/countly-dashboard.log

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<p align="right">
55

6-
[![Build Status](https://api.travis-ci.org/Countly/countly-server.png?branch=master)](https://travis-ci.org/Countly/countly-server) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/98c2726f2d734697a5f1ac0d453f0a06)](https://app.codacy.com/app/ar2rsawseen/countly-server?utm_source=github.com&utm_medium=referral&utm_content=Countly/countly-server&utm_campaign=Badge_Grade_Dashboard) [![Install Countly on DigitalOcean](https://count.ly/github/install-on-digital-ocean.svg)](http://do.count.ly)
6+
[![Build Status](https://api.travis-ci.org/Countly/countly-server.png?branch=master)](https://travis-ci.org/Countly/countly-server) [![Install Countly on DigitalOcean](https://count.ly/github/install-on-digital-ocean.svg)](http://do.count.ly)
77

88
</p>
99

api/parts/data/cache.js

+5
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,11 @@ class CacheMaster {
722722
function createCollection(db, name, size = 1e7) {
723723
return new Promise((resolve, reject) => {
724724
db.onOpened(() => {
725+
if (!db._native) {
726+
return setTimeout(() => {
727+
createCollection(db, name, size).then(resolve, reject);
728+
}, 1000);
729+
}
725730
db._native.createCollection(name, {capped: true, size: size}, (e, col) => {
726731
if (e) {
727732
log.e(`Error while creating capped collection ${name}:`, e);

api/parts/data/exports.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ exports.convertData = function(data, type) {
9595
return JSON.stringify(data);
9696
case "csv":
9797
obj = flattenArray(data);
98-
return json2csv.parse(obj.data, {fields: obj.fields});
98+
return json2csv.parse(obj.data, {fields: obj.fields, excelStrings: true});
9999
case "xls":
100100
obj = flattenArray(data);
101101
return json2xls(obj.data, {fields: obj.fields});

api/parts/jobs/job.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ class Job extends EventEmitter {
308308
reject(err);
309309
}
310310
else if (!doc || !doc.ok || !doc.value) {
311-
reject('Not found');
311+
reject('Job not found');
312312
}
313313
else {
314314
resolve(doc.value);
@@ -438,7 +438,7 @@ class Job extends EventEmitter {
438438
log.i('Replacing job %s (%j) with date %d: %j', this.name, this.data, next, query);
439439

440440
Job.updateAtomically(this.db(), query, {$set: {next: next}}).then(resolve, err => {
441-
if (err === 'Not found') {
441+
if (err === 'Job not found') {
442442
log.i('Replacing job %s (%j) with date %d: no future jobs to move', this.name, this.data, next);
443443
query.next = {$lt: next};
444444
Job.findMany(this.db(), query).then(existing => {
@@ -511,7 +511,14 @@ class Job extends EventEmitter {
511511
await Job.updateMany(this.db(), {_id: {$in: others.map(o => o._id)}}, {$set: {status: STATUS.CANCELLED}});
512512
}
513513

514-
let neo = await Job.updateAtomically(this.db(), query, {$set: this._json});
514+
let neo;
515+
try {
516+
neo = await Job.updateAtomically(this.db(), query, {$set: this._json});
517+
}
518+
catch (e) {
519+
log.w('Job was modified while rescheduling, skipping', e);
520+
}
521+
515522
if (!neo) {
516523
log.w('Job was modified while rescheduling, skipping');
517524
return null;

api/parts/jobs/manager.js

+32-7
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ class Manager {
150150
name: j.name
151151
};
152152
}));
153-
this.process(array.filter(j => this.types.indexOf(j.name) !== -1));
153+
this.process(array.filter(j => this.types.indexOf(j.name) !== -1)).catch(e => {
154+
log.e('Error during job resuming', e);
155+
resume();
156+
});
154157
}
155158
else {
156159
this.checkAfterDelay(DELAY_BETWEEN_CHECKS * 5);
@@ -224,7 +227,10 @@ class Manager {
224227
this.checkAfterDelay();
225228
}
226229
else {
227-
this.process(jobs);
230+
this.process(jobs).catch(e => {
231+
log.e('Error during job processing', e);
232+
this.checkAfterDelay();
233+
});
228234
}
229235
});
230236
}
@@ -256,12 +262,13 @@ class Manager {
256262

257263
if (!this.canRun(job)) {
258264
jobs = jobs.filter(j => j.name !== job.name);
265+
log.d('Cannot run %s:%s:%s, skipping for now', json.name, json._id, new Date(json.next));
259266
continue;
260267
}
261268

262269
if (job instanceof JOB.IPCJob) {
263270
if (!this.hasResources(job)) {
264-
log.i('All resources are busy for %j, skipping for now', json);
271+
log.i('All resources are busy for %s:%s:%s, skipping for now', json.name, json._id, new Date(json.next));
265272
continue;
266273
}
267274
}
@@ -287,15 +294,33 @@ class Manager {
287294
continue;
288295
}
289296

290-
let old = await JOB.Job.updateAtomically(this.db, {
291-
_id: job._id,
292-
status: {$in: [STATUS.RUNNING, STATUS.SCHEDULED, STATUS.PAUSED]}
293-
}, update, false);
297+
let old;
298+
try {
299+
old = await JOB.Job.updateAtomically(this.db, {
300+
_id: job._id,
301+
status: {$in: [STATUS.RUNNING, STATUS.SCHEDULED, STATUS.PAUSED]}
302+
}, update, false);
303+
}
304+
catch (e) {
305+
log.i('Job %s wasn\'t found', job._id, e);
306+
}
307+
294308
if (old) {
295309
if (old.status === STATUS.RUNNING) {
296310
log.i('Job %s is running on another server, won\'t start it here', job.id);
297311
}
298312
else if (old.status === STATUS.SCHEDULED || old.status === STATUS.PAUSED) {
313+
if (job instanceof JOB.IPCJob) {
314+
if (!this.hasResources(job)) {
315+
log.i('Started the job, but all resources are busy for %j, putting it back to SCHEDULED', json);
316+
await JOB.Job.updateAtomically(this.db, {
317+
_id: job._id,
318+
status: STATUS.RUNNING
319+
}, {$set: {status: STATUS.SCHEDULED}}, false);
320+
return;
321+
}
322+
}
323+
299324
let p = this.start(job);
300325
if (!p) {
301326
await JOB.Job.updateAtomically(this.db, {

api/parts/jobs/resource.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ class ResourceFaçade extends ResourceInterface {
317317
* Run job
318318
* @param {Job} job to run
319319
* @returns {Promise} promise
320-
**/
320+
**/
321321
run(job) {
322322
if (this.isBusy) {
323323
log.w('[façade]: Resource façade %j is busy in %d: %j', this.name, this._worker.pid, this.id);
@@ -340,7 +340,7 @@ class ResourceFaçade extends ResourceInterface {
340340
/**
341341
* Close resource
342342
* @returns {Promise} promise
343-
**/
343+
**/
344344
close() {
345345
if (this.isOpen) {
346346
log.w('Closing underlying resource %s from façade', this.id);
@@ -362,7 +362,7 @@ class ResourceFaçade extends ResourceInterface {
362362
/**
363363
* Kill resource
364364
* @returns {Promise} promise
365-
**/
365+
**/
366366
kill() {
367367
return new Promise((resolve) => {
368368
this._worker.kill();
@@ -375,7 +375,7 @@ class ResourceFaçade extends ResourceInterface {
375375
/**
376376
* Open resource
377377
* @returns {Promise} promise
378-
**/
378+
**/
379379
open() {
380380
if (this.isOpen) {
381381
return Promise.resolve();
@@ -404,7 +404,7 @@ class ResourceFaçade extends ResourceInterface {
404404
* Abort job
405405
* @param {Job} job to abort
406406
* @returns {Promise} promise
407-
**/
407+
**/
408408
abort(job) {
409409
if (!this.job) {
410410
log.w('[façade]: Resource façade %j is not open in %d: %j', this.name, this._worker.pid, this.id);
@@ -421,7 +421,7 @@ class ResourceFaçade extends ResourceInterface {
421421

422422
/**
423423
* Resolve job
424-
**/
424+
**/
425425
resolve() {
426426
if (this._resolve) {
427427
log.w('[façade]: Resolving %s', this.job.channel);
@@ -443,7 +443,7 @@ class ResourceFaçade extends ResourceInterface {
443443
/**
444444
* Reject job
445445
* @param {Error} error with which to reject
446-
**/
446+
**/
447447
reject(error) {
448448
if (this._reject) {
449449
log.w('[façade]: Rejecting %s', this.job.channel);

api/tcp_example.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ net.createServer(function(socket) {
7575
* Accepting req data in format {"url":"endpoint", "body":"data"}
7676
* Example: {"url":"/o/ping"}
7777
* Example: {"url":"/i", "body":{"device_id":"test","app_key":"APP_KEY","begin_session":1,"metrics":{}}}
78-
**/
78+
**/
7979
//creating request context
8080
var params = {
8181
//providing data in request object

api/utils/authorizer.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ authorizer.read = function(options) {
102102
* @param {object} options.db - database connection
103103
* @param {string} options.token - token to rvalidate
104104
* @param {function} options.callback - function called when reading was completed or errored, providing error object as first param, true or false if expired as second, seconds till expiration as third.(-1 if never expires, 0 - if expired)
105-
*/
105+
*/
106106
authorizer.check_if_expired = function(options) {
107107
options.db = options.db || common.db;
108108
options.token = options.token + "";

api/utils/common.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2200,7 +2200,7 @@ common.checkDatabaseConfigMatch = (apiConfig, frontendConfig) => {
22002200
* ]
22012201
* }
22022202
* }
2203-
*/
2203+
*/
22042204
else if (Object.prototype.hasOwnProperty.call(apiConfig, 'replSetServers') && Object.prototype.hasOwnProperty.call(frontendConfig, 'replSetServers')) {
22052205
if (apiConfig.replSetServers.length === frontendConfig.replSetServers.length && apiConfig.db === frontendConfig.db) {
22062206
let isCorrect = true;

bin/backup/run.sh

+7-6
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414

1515

1616
# make relative paths work.
17-
cd $(dirname $0)
17+
cd "$(dirname "$0")"
1818

1919
function check_connectivity_mongo() {
20-
local MONGO_OK=$(mongo \
20+
local MONGO_OK;
21+
MONGO_OK=$(mongo \
2122
--quiet \
2223
--eval "db.serverStatus().ok == true")
2324

@@ -32,16 +33,16 @@ function check_connectivity_mongo() {
3233
# generic check connectivity function
3334
function check_connectivity() {
3435
retries=600
35-
until eval "check_connectivity_$@"; do
36+
until eval "check_connectivity_$*"; do
3637
sleep 1
3738
let retries--
3839
if [ $retries == 0 ]; then
39-
echo "time out while waiting for $@ is ready"
40+
echo "time out while waiting for $* is ready"
4041
exit 1
4142
fi
42-
echo "$@ is not reachable yet, trying again..."
43+
echo "$* is not reachable yet, trying again..."
4344
done
44-
echo "$@ is up and running..."
45+
echo "$* is up and running..."
4546
}
4647

4748
# wait till mongo becomes online.

0 commit comments

Comments
 (0)