Commit e74f4914 authored by Tristan Cavelier's avatar Tristan Cavelier Committed by Sebastien Robin

Improve Job management.

parent c96a5bc7
...@@ -132,31 +132,62 @@ test ('All tests', function () { ...@@ -132,31 +132,62 @@ test ('All tests', function () {
module ( 'Jio Job Managing' ); module ( 'Jio Job Managing' );
test ('Add 2 same jobs', function () { test ('Simple Job Elimination', function () {
// Check possibilities when adding 2 same jobs.
var o = {}, clock = this.sandbox.useFakeTimers(), id = 0; var o = {}, clock = this.sandbox.useFakeTimers(), id = 0;
o.f1 = this.spy(); o.f2 = this.spy()
o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'},
{'ID':'jiotests'});
id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f1});
ok(LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'],
'job creation');
clock.tick(10);
o.jio.removeDocument({'fileName':'file','fileContent':'content',
'callback':o.f2});
deepEqual(LocalOrCookieStorage.getItem('jio/jobObject/'+id)['1'],
undefined,'job elimination');
});
test ('Simple Job Replacement', function () {
// Test if the second job write over the first one // Test if the second job write over the first one
var o = {}, clock = this.sandbox.useFakeTimers(), id = 0;
o.f1 = this.spy(); o.f2 = this.spy()
o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'}, o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'},
{'ID':'jiotests'}); {'ID':'jiotests'});
id = o.jio.id; id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content'}); o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f1});
clock.tick(10); clock.tick(10);
o.jio.saveDocument({'fileName':'file','fileContent':'content'}); o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f2});
deepEqual(LocalOrCookieStorage.getItem( deepEqual(LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['1'].date,10, 'jio/jobObject/'+id)['1'].date,10,
'The first job date have to be equal to the second job date.'); 'The first job date have to be equal to the second job date.');
clock.tick(500);
ok(!o.f1.calledOnce,'no callback for the first save request');
ok(o.f2.calledOnce,'second callback is called once');
o.jio.stop(); o.jio.stop();
clock.tick(-10);
});
test ('Simple Job Waiting', function () {
// Test if the second job doesn't erase the first ongoing one // Test if the second job doesn't erase the first ongoing one
var o = {}, clock = this.sandbox.useFakeTimers(), id = 0;
o.f3 = this.spy(); o.f4 = this.spy();
o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'}, o.jio = JIO.createNew({'type':'dummyallok','userName':'dummy'},
{'ID':'jiotests'}); {'ID':'jiotests'});
id = o.jio.id; id = o.jio.id;
o.jio.saveDocument({'fileName':'file','fileContent':'content'}); o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f3});
clock.tick(200); clock.tick(200);
o.jio.saveDocument({'fileName':'file','fileContent':'content'}); o.jio.saveDocument({'fileName':'file','fileContent':'content',
'callback':o.f4});
ok(LocalOrCookieStorage.getItem( ok(LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['2'] && 'jio/jobObject/'+id)['2'] &&
LocalOrCookieStorage.getItem( LocalOrCookieStorage.getItem(
...@@ -166,16 +197,15 @@ test ('Add 2 same jobs', function () { ...@@ -166,16 +197,15 @@ test ('Add 2 same jobs', function () {
'jio/jobObject/'+id)['2'].status === 'wait' && 'jio/jobObject/'+id)['2'].status === 'wait' &&
LocalOrCookieStorage.getItem( LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['2'].waitingFor && 'jio/jobObject/'+id)['2'].waitingFor &&
LocalOrCookieStorage.getItem( JSON.stringify (LocalOrCookieStorage.getItem(
'jio/jobObject/'+id)['2'].waitingFor.jobID === '1', 'jio/jobObject/'+id)['2'].waitingFor.jobIdArray) === '["1"]',
'The second job must be waiting for the first to end'); 'The second job must be waiting for the first to end');
clock.tick(500);
ok(o.f3.calledOnce,'first request passed');
ok(o.f4.calledOnce,'restore waiting job');
o.jio.stop(); o.jio.stop();
}); });
test ('Restore a previous waiting job', function () {
ok(false,'not implemented yet');
});
module ( 'Jio LocalStorage' ); module ( 'Jio LocalStorage' );
test ('Check name availability', function () { test ('Check name availability', function () {
...@@ -591,25 +621,29 @@ test ('Check name availability', function () { ...@@ -591,25 +621,29 @@ test ('Check name availability', function () {
}; };
// DummyStorageAllOK,OK // DummyStorageAllOK,OK
o.jio = JIO.createNew({'type':'replicate','storageArray':[ o.jio = JIO.createNew({'type':'replicate','storageArray':[
{'type':'dummyallok'},{'type':'dummyallok'}]}, {'type':'dummyallok','userName':'1'},
{'type':'dummyallok','userName':'2'}]},
{'ID':'jiotests'}); {'ID':'jiotests'});
mytest('DummyStoragesAllOK,OK : name available',true); mytest('DummyStoragesAllOK,OK : name available',true);
o.jio.stop(); o.jio.stop();
// DummyStorageAllOK,Fail // DummyStorageAllOK,Fail
o.jio = JIO.createNew({'type':'replicate','storageArray':[ o.jio = JIO.createNew({'type':'replicate','storageArray':[
{'type':'dummyallok'},{'type':'dummyallfail'}]}, {'type':'dummyallok','userName':'1'},
{'type':'dummyallfail','userName':'2'}]},
{'ID':'jiotests'}); {'ID':'jiotests'});
mytest('DummyStoragesAllOK,Fail : name not available',false); mytest('DummyStoragesAllOK,Fail : name not available',false);
o.jio.stop(); o.jio.stop();
// DummyStorageAllFail,OK // DummyStorageAllFail,OK
o.jio = JIO.createNew({'type':'replicate','storageArray':[ o.jio = JIO.createNew({'type':'replicate','storageArray':[
{'type':'dummyallfail'},{'type':'dummyallok'}]}, {'type':'dummyallfail','userName':'1'},
{'type':'dummyallok','userName':'2'}]},
{'ID':'jiotests'}); {'ID':'jiotests'});
mytest('DummyStoragesAllFail,OK : name not available',false); mytest('DummyStoragesAllFail,OK : name not available',false);
o.jio.stop(); o.jio.stop();
// DummyStorageAllFail,Fail // DummyStorageAllFail,Fail
o.jio = JIO.createNew({'type':'replicate','storageArray':[ o.jio = JIO.createNew({'type':'replicate','storageArray':[
{'type':'dummyallfail'},{'type':'dummyallfail'}]}, {'type':'dummyallfail','userName':'1'},
{'type':'dummyallfail','userName':'2'}]},
{'ID':'jiotests'}); {'ID':'jiotests'});
mytest('DummyStoragesAllFail,Fail : name not available',false); mytest('DummyStoragesAllFail,Fail : name not available',false);
o.jio.stop(); o.jio.stop();
......
...@@ -32,6 +32,74 @@ ...@@ -32,6 +32,74 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// jio globals // jio globals
jioGlobalObj = { jioGlobalObj = {
// For more information, see documentation
'jobManagingMethod':{
'canSelect':function (job1,job2) {
if (JSON.stringify (job1.storage) ===
JSON.stringify (job2.storage) &&
JSON.stringify (job1.applicant) ===
JSON.stringify (job2.applicant) &&
job1.fileName === job2.fileName) {
return true;
}
return false;
},
'canRemoveFailOrDone':function (job1,job2) {
if (job1.method === job2.method &&
(job1.status === 'fail' ||
job1.status === 'done')) {
return true;
}
return false;
},
'canEliminate':function (job1,job2) {
if (job1.status !== 'ongoing' &&
job2.method === 'removeDocument' &&
(job1.method === 'removeDocument' ||
job1.method === 'saveDocument')) {
return true;
}
return false;
},
'canReplace':function (job1,job2) {
if (job1.status !== 'ongoing' &&
job1.method === job2.method &&
JSON.stringify (job1.options) ===
JSON.stringify (job2.options) &&
job1.fileContent === job2.fileContent) {
return true;
}
return false;
},
'cannotAccept':function (job1,job2) {
if (job1.status !== 'ongoing' ) {
if (job1.method === 'removeDocument' &&
job2.method === 'loadDocument') {
return true;
}
} else {
if (job1.method === 'loadDocument') {
if (job2.method === 'loadDocument') {
return true;
}
} else if (job1.method === 'removeDocument') {
if (job2.method === 'loadDocument' ||
job2.method === 'removeDocument') {
return true;
}
} else if (job1.method === job2.method === 'saveDocument' &&
job1.fileContent === job2.fileContent &&
JSON.stringify (job1.options) ===
JSON.stringify (job2.options)) {
return true;
}
}
return false;
},
'mustWait':function (job1,job2) {
return true;
}
},
'localStorage': null, // where the browser stores data 'localStorage': null, // where the browser stores data
'queueID': 1, 'queueID': 1,
'storageTypeObject': {} // ex: {'type':'local','creator': fun ...} 'storageTypeObject': {} // ex: {'type':'local','creator': fun ...}
...@@ -47,6 +115,8 @@ ...@@ -47,6 +115,8 @@
console.error ('Fail to load ' + name); console.error ('Fail to load ' + name);
retval = false; retval = false;
}; };
try { if (!JSON) { err('JSON'); } }
catch (e) { err('JSON'); }
try { if (!jQuery) { err('jQuery'); } } try { if (!jQuery) { err('jQuery'); } }
catch (e) { err('jQuery'); } catch (e) { err('jQuery'); }
try { if (!LocalOrCookieStorage) { err('LocalOrCookieStorage'); } } try { if (!LocalOrCookieStorage) { err('LocalOrCookieStorage'); } }
...@@ -200,19 +270,88 @@ ...@@ -200,19 +270,88 @@
this.jobObjectName,this.jobObject); this.jobObjectName,this.jobObject);
}, },
createJob: function ( options ) { createJob: function ( options ) {
this.addJob ( new Job ( options ) ); return this.addJob ( new Job ( options ) );
}, },
addJob: function ( job ) { addJob: function ( job ) {
// Add a job to the queue // Add a job to the queue TODO DocString
// job : the job object // job : the job object
// set job id var res = {'newone':true,'elimArray':[],'waitArray':[],
job.id = this.jobid; 'removeArray':[]},
this.jobid ++; id=0;
// save the new job into the queue
this.jobObject[job.id] = job; //// browsing current jobs
for (id in this.jobObject) {
if (jioGlobalObj.jobManagingMethod.canSelect(
this.jobObject[id],job)) {
if (jioGlobalObj.jobManagingMethod.canRemoveFailOrDone(
this.jobObject[id],job)) {
res.removeArray.push(id);
}
if (jioGlobalObj.jobManagingMethod.canEliminate(
this.jobObject[id],job)) {
console.log ('Elimitated: ' +
JSON.stringify (this.jobObject[id]));
res.elimArray.push(id);
continue;
}
if (jioGlobalObj.jobManagingMethod.canReplace(
this.jobObject[id],job)) {
console.log ('Replaced: ' +
JSON.stringify (this.jobObject[id]));
this.jobObject[id].date = job.date;
// no need to copy fileContent or userName
this.jobObject[id].callback = job.callback;
res.newone = false;
break;
}
if (jioGlobalObj.jobManagingMethod.cannotAccept(
this.jobObject[id],job)) {
console.log ('Make not accepted: ' +
JSON.stringify (this.jobObject[id]));
// Job not accepted
return false;
}
if (jioGlobalObj.jobManagingMethod.mustWait(
this.jobObject[id].job)) {
console.log ('Waited: ' +
JSON.stringify (this.jobObject[id]) +
'\nby : ' + JSON.stringify (job));
res.waitArray.push(id);
continue;
}
// one of the previous tests must be ok.
// the program must not reach this part of the 'for'.
}
}
//// end browsing current jobs
if (res.newone) {
// if it is a new job, we can eliminate deprecated jobs and
// set this job dependencies.
for (id in res.elimArray) {
this.removeJob(this.jobObject[res.elimArray[id]]);
}
if (res.waitArray.length > 0) {
job.status = 'wait';
job.waitingFor = {'jobIdArray':res.waitArray};
for (id in res.waitArray) {
this.jobObject[res.waitArray[id]].maxtries = 1;
}
}
for (id in res.removeArray) {
this.removeJob(this.jobObject[res.removeArray[id]]);
}
// set job id
job.id = this.jobid;
this.jobid ++;
// save the new job into the queue
this.jobObject[job.id] = job;
console.log ('new one: ' + JSON.stringify (job));
}
// save into localStorage // save into localStorage
this.copyJobQueueToLocalStorage(); this.copyJobQueueToLocalStorage();
return true;
}, // end addJob }, // end addJob
removeJob: function ( options ) { removeJob: function ( options ) {
...@@ -223,23 +362,23 @@ ...@@ -223,23 +362,23 @@
// options.job : the job object containing at least {id:..}. // options.job : the job object containing at least {id:..}.
// options.where : remove values where options.where(job) === true // options.where : remove values where options.where(job) === true
//// set tests functions
var settings = $.extend ({'where':function (job) {return true;}}, var settings = $.extend ({'where':function (job) {return true;}},
options),k='key',andwhere,found=false; options),k='key',andwhere,found=false;
if (settings.job) {
andwhere = function (job) {return (job.id===settings.job.id);};
} else {
andwhere = function (job) {return true;};
}
//// end set tests functions
//// modify the job list //// modify the job list
for (k in this.jobObject) { if (settings.job) {
if (settings.where(this.jobObject[k]) && if (this.jobObject[settings.job.id] && settings.where(
andwhere(this.jobObject[k]) ) { this.jobObject[settings.job.id]) ) {
delete this.jobObject[k]; delete this.jobObject[settings.job.id];
found = true; found = true;
} }
}else {
for (k in this.jobObject) {
if (settings.where(this.jobObject[k])) {
delete this.jobObject[k];
found = true;
}
}
} }
if (!found) { if (!found) {
$.error ('No jobs was found, when trying to remove some.'); $.error ('No jobs was found, when trying to remove some.');
...@@ -260,16 +399,41 @@ ...@@ -260,16 +399,41 @@
invokeAll: function () { invokeAll: function () {
// Do all jobs in the queue. // Do all jobs in the queue.
var i = 'id'; var i = 'id', j = 'ind', ok = false;
//// do All jobs //// do All jobs
for (i in this.jobObject) { for (i in this.jobObject) {
if (this.jobObject[i].status === 'initial') { if (this.jobObject[i].status === 'initial') {
// if status initial
// invoke new job // invoke new job
this.invoke(this.jobObject[i]); this.invoke(this.jobObject[i]);
} else if (this.jobObject[i].status === 'wait' && } else if (this.jobObject[i].status === 'wait') {
this.jobObject[i].retryAt >= Date.now()) { // if status wait
// invoke waiting job if (this.jobObject[i].waitingFor.jobIdArray) {
this.invoke(this.jobObject[i]); // wait job
ok = true;
// browsing job id array
for (j in this.jobObject[i].waitingFor.jobIdArray) {
if (this.jobObject[this.jobObject[i].
waitingFor.jobIdArray[j]]) {
// if a job is still exist, don't invoke
ok = false;
break;
}
}
if (ok) {
// invoke waiting job
this.invoke(this.jobObject[i]);
}
} else if (this.jobObject[i].waitingFor.time) {
// wait time
if (this.jobObject[i].waitingFor.time > Date.now()) {
// it is time to restore the job!
this.invoke(this.jobObject[i]);
}
} else {
// wait nothing
this.invoke(this.jobObject[i]);
}
} }
} }
this.copyJobQueueToLocalStorage(); this.copyJobQueueToLocalStorage();
...@@ -550,6 +714,10 @@ ...@@ -550,6 +714,10 @@
// options.applicant : the applicant (optional) // options.applicant : the applicant (optional)
// options.callback(result) : called to get the result. // options.callback(result) : called to get the result.
// returns: - null if dependencies are missing
// - false if the job was not added
// - true if the job was added or replaced
// example : // example :
// jio.checkNameAvailability({'userName':'myName','callback': // jio.checkNameAvailability({'userName':'myName','callback':
// function (result) { alert('is available? ' + // function (result) { alert('is available? ' +
...@@ -578,6 +746,10 @@ ...@@ -578,6 +746,10 @@
// options.applicant : the applicant (optional) // options.applicant : the applicant (optional)
// options.callback(result) : called to get the result. // options.callback(result) : called to get the result.
// returns: - null if dependencies are missing
// - false if the job was not added
// - true if the job was added or replaced
// jio.saveDocument({'fileName':'file','fileContent':'content', // jio.saveDocument({'fileName':'file','fileContent':'content',
// 'callback': function (result) { alert('saved?' + // 'callback': function (result) { alert('saved?' +
// result.isSaved); }}); // result.isSaved); }});
...@@ -605,6 +777,10 @@ ...@@ -605,6 +777,10 @@
// options.applicant : the applicant (optional) // options.applicant : the applicant (optional)
// options.callback(result) : called to get the result. // options.callback(result) : called to get the result.
// returns: - null if dependencies are missing
// - false if the job was not added
// - true if the job was added or replaced
// jio.loadDocument({'fileName':'file','callback': // jio.loadDocument({'fileName':'file','callback':
// function (result) { alert('content: '+ // function (result) { alert('content: '+
// result.doc.fileContent + ' creation date: ' + // result.doc.fileContent + ' creation date: ' +
...@@ -631,6 +807,10 @@ ...@@ -631,6 +807,10 @@
// options.applicant : the applicant (optional) // options.applicant : the applicant (optional)
// options.callback(result) : called to get the result. // options.callback(result) : called to get the result.
// returns: - null if dependencies are missing
// - false if the job was not added
// - true if the job was added or replaced
// jio.getDocumentList({'callback': // jio.getDocumentList({'callback':
// function (result) { alert('list: '+result.list); }}); // function (result) { alert('list: '+result.list); }});
...@@ -654,6 +834,10 @@ ...@@ -654,6 +834,10 @@
// options.applicant : the applicant (optional) // options.applicant : the applicant (optional)
// options.callback(result) : called to get the result. // options.callback(result) : called to get the result.
// returns: - null if dependencies are missing
// - false if the job was not added
// - true if the job was added or replaced
// jio.removeDocument({'fileName':'file','callback': // jio.removeDocument({'fileName':'file','callback':
// function (result) { alert('removed? '+result.isRemoved); }}); // function (result) { alert('removed? '+result.isRemoved); }});
......
...@@ -713,6 +713,7 @@ ...@@ -713,6 +713,7 @@
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// ReplicateStorage // ReplicateStorage
ReplicateStorage = function ( options ) { ReplicateStorage = function ( options ) {
// TODO Add a tests that check if there is no duplicate storages.
this.queue = options.queue; this.queue = options.queue;
this.id = null; this.id = null;
this.length = options.storage.storageArray.length; this.length = options.storage.storageArray.length;
...@@ -750,7 +751,7 @@ ...@@ -750,7 +751,7 @@
job.callback(res); job.callback(res);
} }
}; };
this.queue.createJob ( newjob ); this.queue.createJob ( newjob ) ;
} }
}, },
saveDocument: function ( job, jobendcallback ) { saveDocument: function ( job, jobendcallback ) {
...@@ -766,9 +767,8 @@ ...@@ -766,9 +767,8 @@
// returns {'status':string,'message':string,'isSaved':boolean, // returns {'status':string,'message':string,'isSaved':boolean,
// 'resultArray':Array} in the jobendcallback arguments. // 'resultArray':Array} in the jobendcallback arguments.
// TODO // TODO
}, },
loadDocument: function ( job, jobendcallback ) { loadDocument: function ( job, jobendcallback ) {
// TODO // TODO
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment