Skip to content

Commit 238403d

Browse files
yaroslav-codefreshitai-codefresh
authored andcommitted
Saas 1975 wait container logger (#23)
1 parent f228386 commit 238403d

File tree

4 files changed

+137
-5
lines changed

4 files changed

+137
-5
lines changed

lib/logger.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Logger {
2020
findExistingContainers,
2121
logSizeLimit
2222
}) {
23-
this.state = { status: 'init' };
23+
this.state = { status: 'init', lastLogsDate: Date.now() };
2424
this.taskLoggerConfig = taskLoggerConfig;
2525
this.loggerId = loggerId;
2626
this.findExistingContainers = findExistingContainers === 'true';
@@ -104,9 +104,9 @@ class Logger {
104104

105105
/**
106106
* will write updates about the attached containers and initial state to a file for future read from isReady.sh script
107-
* @param state
107+
* @param disableLog
108108
*/
109-
_writeNewState() {
109+
_writeNewState(disableLog = false) {
110110
const filePath = `${__dirname}/state.json`;
111111
const currentState = JSON.stringify(this.state);
112112
fs.writeFile(filePath, currentState, (err) => {
@@ -116,7 +116,7 @@ class Logger {
116116
message: 'failed to write state to file'
117117
});
118118
logger.error(error.toString());
119-
} else {
119+
} else if (!disableLog) {
120120
logger.info(`State: ${currentState} updated and written to file: ${filePath}`);
121121
}
122122
});
@@ -214,6 +214,7 @@ class Logger {
214214
});
215215
this.containerLoggers.push(containerLogger);
216216
containerLogger.on('message.logged', this._updateTotalLogSize.bind(this));
217+
containerLogger.on('message.logged', this._updateLastLoggingDate.bind(this));
217218

218219
containerLogger.start()
219220
.done(() => {
@@ -234,6 +235,11 @@ class Logger {
234235
this.taskLogger.setLogSize(this.logSize);
235236
}
236237

238+
_updateLastLoggingDate() {
239+
this.state.lastLogsDate = Date.now();
240+
this._writeNewState(true);
241+
}
242+
237243
/**
238244
* Will check if a container was already handled (no matter what the handling status is)
239245
* @param containerId

lib/waitUntilFinish.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
const fs = require('fs');
3+
const path = require('path');
4+
const Q = require('q');
5+
6+
class Waiter {
7+
8+
constructor(timeout, filepath, lastLogsDate) {
9+
this.timeout = timeout;
10+
this.filepath = filepath;
11+
this.lastLogsDate = lastLogsDate;
12+
this.finished = false;
13+
}
14+
15+
_stateListener(currentFileState) {
16+
this.lastLogsDate = currentFileState.mtimeMs;
17+
}
18+
19+
20+
_finishOnTimeout() {
21+
const diff = Date.now() - this.lastLogsDate;
22+
23+
const date = new Date(this.lastLogsDate);
24+
console.log('Last logs date:', date);
25+
console.log('Current date:', new Date());
26+
27+
if (diff > this.timeout) {
28+
console.log(`Logs haven't been written for the last ${this.timeout} millis. Finishing waiter...`);
29+
this._unwatchState();
30+
this.finished = true;
31+
this.deferred.resolve();
32+
}
33+
}
34+
35+
_checkTimeout() {
36+
this._finishOnTimeout();
37+
if (!this.finished) {
38+
setTimeout(this._checkTimeout.bind(this), 100);
39+
}
40+
}
41+
42+
run() {
43+
this.deferred = Q.defer();
44+
console.log(`Logs waiting timeout: ${this.timeout} millis`);
45+
this._checkTimeout();
46+
this._watchState();
47+
48+
return this.deferred.promise;
49+
}
50+
51+
_watchState() {
52+
fs.watchFile(this.filepath, { persistent: false, interval: 100 }, this._stateListener.bind(this));
53+
}
54+
55+
_unwatchState() {
56+
fs.unwatchFile(this.filepath);
57+
}
58+
59+
static wait(timeout, filepath) {
60+
const state = JSON.parse(fs.readFileSync(filepath, 'utf8'));
61+
return new Waiter(timeout, filepath, state.lastLogsDate).run();
62+
}
63+
}
64+
65+
if (require.main === module) {
66+
const timeout = Number.parseInt(process.argv[process.argv.length - 1]);
67+
const filepath = path.resolve(__dirname, 'state.json');
68+
Waiter.wait(timeout, filepath);
69+
} else {
70+
module.exports = Waiter;
71+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cf-container-logger",
3-
"version": "0.0.6",
3+
"version": "0.0.7",
44
"description": "codefresh container logger",
55
"keywords": [
66
"cf-container-logger"

test/waitUntilFinish.spec.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* jshint ignore:start */
2+
3+
'use strict';
4+
5+
const path = require('path');
6+
const fs = require('fs');
7+
const os = require('os');
8+
const Q = require('q');
9+
10+
const chai = require('chai');
11+
const expect = chai.expect;
12+
const sinon = require('sinon');
13+
const sinonChai = require('sinon-chai');
14+
chai.use(sinonChai);
15+
16+
const Waiter = require('../lib/waitUntilFinish');
17+
sinon.spy(Waiter.prototype, '_finishOnTimeout');
18+
sinon.spy(Waiter.prototype, '_checkTimeout');
19+
20+
const statePath = path.resolve(os.tmpdir(), 'state.json');
21+
const writeDate = (date = Date.now()) => {
22+
console.log(new Date(date));
23+
fs.writeFileSync(statePath, JSON.stringify({ lastLogsDate: date }));
24+
};
25+
26+
27+
describe('waitUntilFinish script test', () => {
28+
beforeEach(() => {
29+
writeDate();
30+
Waiter.prototype._finishOnTimeout.resetHistory();
31+
Waiter.prototype._checkTimeout.resetHistory();
32+
});
33+
34+
it('should finish immediately if now - lastLogsDate > timeout', async () => {
35+
writeDate(Date.now() - 2000);
36+
await Waiter.wait(1000, statePath);
37+
expect(Waiter.prototype._finishOnTimeout).to.have.been.calledOnce;
38+
expect(Waiter.prototype._checkTimeout).to.have.been.calledOnce;
39+
});
40+
41+
it('should wait until now - lastLogsDate > timeout', async () => {
42+
await Waiter.wait(1000, statePath);
43+
expect(Waiter.prototype._finishOnTimeout.getCalls().length).to.be.approximately(11, 1);
44+
expect(Waiter.prototype._checkTimeout.getCalls().length).to.be.approximately(11, 1);
45+
});
46+
47+
it('should wait until now - lastLogsDate > timeout in case when lastLogsDate was updated', async () => {
48+
const promise = Waiter.wait(1000, statePath);
49+
await Q.delay(500);
50+
writeDate();
51+
await promise;
52+
expect(Waiter.prototype._finishOnTimeout.getCalls().length).to.be.approximately(15, 1);
53+
expect(Waiter.prototype._checkTimeout.getCalls().length).to.be.approximately(15, 1);
54+
});
55+
});

0 commit comments

Comments
 (0)