Skip to content

Commit

Permalink
support passing the first step from a previous already create step, b…
Browse files Browse the repository at this point in the history
…y passing its id
  • Loading branch information
itai-codefresh committed Aug 31, 2016
1 parent 1851134 commit 63d2a6c
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 54 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cf-common",
"version": "0.0.21",
"version": "0.0.22",
"description": "common modules for codefresh runtime and api",
"main": "index.js",
"scripts": {
Expand Down
125 changes: 73 additions & 52 deletions taskLogger/taskLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,35 @@ var util = require('util');
* @param queueConfig - sends the build-manager an event whenever a new step is created
* @returns {{create: create, finish: finish}}
*/
var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, FirebaseLib, queueConfig) {
var TaskLogger = function (jobId, firstStepCreationTime, baseFirebaseUrl, FirebaseLib, queueConfig, initializeStepReference) {
var self = this;
EventEmitter.call(self);

if (!jobId){
if (!jobId) {
throw new CFError(ErrorTypes.Error, "failed to create taskLogger because jobId must be provided");
}
else if (!baseFirebaseUrl){
else if (!baseFirebaseUrl) {
throw new CFError(ErrorTypes.Error, "failed to create taskLogger because baseFirebaseUrl must be provided");
}
else if (!FirebaseLib){
else if (!FirebaseLib) {
throw new CFError(ErrorTypes.Error, "failed to create taskLogger because Firebase lib reference must be provided");
}
else if (!queueConfig){
else if (!queueConfig) {
throw new CFError(ErrorTypes.Error, "failed to create taskLogger because queue configuration must be provided");
}

var buildManagerQueue = new Queue('BuildManagerEventsQueue', queueConfig);

var progressRef = new FirebaseLib(baseFirebaseUrl + jobId);

var fatal = false;
var fatal = false;
var finished = false;
var steps = {};
var steps = {};
var handler;


var listenForManualTermination = function(snapshot){ // this is here to handle termination asked by user to signify stop of the progress and stop accepting additional logs
// this is here to handle termination asked by user to signify stop of the progress and stop accepting additional logs
// this logic can't be moved to the step because there are times that it is possible that no steps will be available
var listenForManualTermination = function(snapshot){
var status = snapshot.val();
if (status !== "running"){
progressRef.child("status").off("value", listenForManualTermination);
Expand All @@ -52,66 +53,86 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
};
progressRef.child("status").on("value", listenForManualTermination);

var create = function(name) {
var listenOnTopLevelStatus = function (step, snapshot) { // this is here to handle termination asked by user to signify stop of the progress and stop accepting additional logs
var status = snapshot.val();
if (status !== "running") {
progressRef.child("status").off("value", listenOnTopLevelStatus);
if ((status === "terminating" || status === "terminated") && step.status === "running") {
step.finishTimeStamp = +(new Date().getTime() / 1000).toFixed();
step.status = "terminated";
step.firebaseRef.update({status: step.status, finishTimeStamp: step.finishTimeStamp});
step.firebaseRef.child("logs").push("Process terminated");
progressRef.child("lastUpdate").set(new Date().getTime());
}
}
};

if (initializeStepReference) {
var initializeStep = {
name:"Initializing Process",
status: "running",
firebaseRef: new FirebaseLib(initializeStepReference)
};
steps["Initializing Process"] = initializeStep;
progressRef.child("status").on("value", listenOnTopLevelStatus.bind(this, initializeStep));
}

var create = function (name) {

if (fatal || finished){
if (fatal || finished) {
return {
write: function(){},
debug: function(){},
warning: function(){},
info: function(){},
finish: function(){}
getReference: function () {
},
write: function () {
},
debug: function () {
},
warning: function () {
},
info: function () {
},
finish: function () {
}
};
}

var step = steps[name];
if (!step) {
step = {
name:name,
name: name,
creationTimeStamp: +(new Date().getTime() / 1000).toFixed(),
status: "running",
logs: {}
};
if (firstStepCreationTime && _.isEmpty(steps)){ // a workaround so api can provide the first step creation time from outside
if (firstStepCreationTime && _.isEmpty(steps)) { // a workaround so api can provide the first step creation time from outside
step.creationTimeStamp = firstStepCreationTime;
}
steps[name] = step;
var stepsRef = new FirebaseLib(baseFirebaseUrl + jobId + "/steps");
steps[name] = step;
var stepsRef = new FirebaseLib(baseFirebaseUrl + jobId + "/steps");
step.firebaseRef = stepsRef.push(step);

step.firebaseRef.on("value", function(snapshot){
step.firebaseRef.on("value", function (snapshot) {
var val = snapshot.val();
if (val && val.name === name){
if (val && val.name === name) {
stepsRef.off("value");
self.emit("step-pushed", name);
}
});

buildManagerQueue.request({action:"new-progress-step", jobId: jobId, name: name}); //update build model

var listenOnTopLevelStatus = function(snapshot){ // this is here to handle termination asked by user to signify stop of the progress and stop accepting additional logs
var status = snapshot.val();
if (status !== "running"){
progressRef.child("status").off("value", listenOnTopLevelStatus);
if ((status === "terminating" || status === "terminated") && step.status === "running"){
step.finishTimeStamp = +(new Date().getTime() / 1000).toFixed();
step.status = "terminated";
step.firebaseRef.update({status: step.status, finishTimeStamp: step.finishTimeStamp});
step.firebaseRef.child("logs").push("Process terminated");
progressRef.child("lastUpdate").set(new Date().getTime());
}
}
};
progressRef.child("status").on("value", listenOnTopLevelStatus);
buildManagerQueue.request({action: "new-progress-step", jobId: jobId, name: name}); //update build model

progressRef.child("status").on("value", listenOnTopLevelStatus.bind(this, step));
}
else {
step.status = "running";
step.firebaseRef.update({status: step.status, finishTimeStamp: ""}); //this is a workaround because we are creating multiple steps with the same name so we must reset the finishtime so that we won't show it in the ui
}

handler = {
write: function(message) {
getReference: function () {
return step.firebaseRef.toString();
},
write: function (message) {
if (fatal) return;
if (step.status === "running") {
step.firebaseRef.child("logs").push(message);
Expand All @@ -121,7 +142,7 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
self.emit("error", new CFError(ErrorTypes.Error, "progress-logs 'write' handler was triggered after the job finished with message: %s", message));
}
},
debug: function(message) {
debug: function (message) {
if (fatal) return;
if (step.status === "running") {
step.firebaseRef.child("logs").push(message + '\r\n');
Expand All @@ -131,7 +152,7 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
self.emit("error", new CFError(ErrorTypes.Error, "progress-logs 'debug' handler was triggered after the job finished with message: %s", message));
}
},
warning: function(message) {
warning: function (message) {
if (fatal) return;
if (step.status === "running") {
step.hasWarning = true;
Expand All @@ -142,7 +163,7 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
self.emit("error", new CFError(ErrorTypes.Error, "progress-logs 'warning' handler was triggered after the job finished with message: %s", message));
}
},
info: function(message) {
info: function (message) {
if (fatal) return;
if (step.status === "running") {
step.firebaseRef.child("logs").push(message + '\r\n');
Expand All @@ -152,23 +173,23 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
self.emit("error", new CFError(ErrorTypes.Error, "progress-logs 'info' handler was triggered after the job finished with message: %s", message));
}
},
finish: function(err) {
finish: function (err) {
if (fatal) return;
if (step.status === "running") {
step.finishTimeStamp = +(new Date().getTime() / 1000).toFixed();
step.status = err ? "error" : "success";
if (step.hasWarning){ //this is a workaround to mark a step with warning status. we do it at the end of the step
step.status = err ? "error" : "success";
if (step.hasWarning) { //this is a workaround to mark a step with warning status. we do it at the end of the step
step.status = "warning";
}
if (err){
if (err) {
step.firebaseRef.child("logs").push(err.toString());
}
step.firebaseRef.update({status: step.status, finishTimeStamp: step.finishTimeStamp});
progressRef.child("lastUpdate").set(new Date().getTime());
handler = undefined;
}
else if (step.status !== "terminated") {
if (err){
if (err) {
self.emit("error", new CFError(ErrorTypes.Error, "progress-logs 'finish' handler was triggered after the job finished with err: %s", err.toString()));
}
else {
Expand All @@ -180,21 +201,21 @@ var TaskLogger = function(jobId, firstStepCreationTime, baseFirebaseUrl, Firebas
return handler;
};

var finish = function(err) {
var finish = function (err) {
if (fatal) return;
if (handler){
if (handler) {
handler.finish(err);
}
finished = true;
};

var fatalError = function(err) {
if (!err){
var fatalError = function (err) {
if (!err) {
throw new CFError(ErrorTypes.Error, "fatalError was called without an error. not valid.");
}
if (fatal) return;

if (handler){
if (handler) {
handler.finish(err);
}
else {
Expand Down
20 changes: 19 additions & 1 deletion taskLogger/taskLogger.unit.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ describe('taskLogger tests', function () {
expect(stepLogger.info()).to.equal(undefined);
expect(stepLogger.finish()).to.equal(undefined);
});

it('1.1.6 create a new logger with a reference to a previous step defined in a different instance', function () {
var Firebase = createMockFirebase();
var Logger = createMockLogger();
var logger = new Logger("progress_id", null, "firebaseUrl", Firebase, {servers: ['address']}, "previousStepReference");
expect(logger).to.exist; // jshint ignore:line
expect(logger.create).to.exist; // jshint ignore:line
expect(logger.finish).to.exist; // jshint ignore:line
});

});

describe('negative', function(){
Expand Down Expand Up @@ -372,6 +382,14 @@ describe('taskLogger tests', function () {

});

it('3.8 trigger getReference handler', function(){

var Firebase = createMockFirebase();
var Logger = createMockLogger();
var logger = new Logger("progress_id", null, "firebaseUrl", Firebase, {servers: ['address']});
var stepLogger = logger.create("step1");
stepLogger.getReference();
});

});

Expand Down Expand Up @@ -442,7 +460,6 @@ describe('taskLogger tests', function () {
stepLogger.finish("not good!");
});


it('4.7 should emit an error when triggering finish handler after step has finished', function(done){
var Firebase = createMockFirebase();
var Logger = createMockLogger();
Expand Down Expand Up @@ -473,6 +490,7 @@ describe('taskLogger tests', function () {
logger.fatalError(new Error("fatal error"));
var stepLogger = logger.create("new step");
stepLogger.write("hey");
stepLogger.getReference();
expect(childSpy.callCount).to.equal(4); // jshint ignore:line
});

Expand Down

0 comments on commit 63d2a6c

Please sign in to comment.