Skip to content

Commit

Permalink
restrucutured systemAdapter to scheduler and extracted scheduler for …
Browse files Browse the repository at this point in the history
…unix' at. further organized files in subfolders for more clearity
  • Loading branch information
Manuel Alabor committed Jan 15, 2014
1 parent 5e445ca commit 5afc425
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 169 deletions.
6 changes: 3 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var cli = require('./cli')
, days = require('./days')
, days = require('./model/days')
, parser = require('./parser')
, Schedule = require('./schedule')
, Task = require('./task');
, Schedule = require('./model/schedule')
, Task = require('./model/task');

module.exports = {
cli: cli
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/parser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var time = require('time-js')
, days = require('./days')
, days = require('./model/days')
, daysByName = Object.keys(days);

/** Function: parseDay
Expand Down
85 changes: 85 additions & 0 deletions lib/scheduler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
var Task = require('./model/task');

/** Class: Scheduler
* The <Scheduler> adapts the information of a <Schedule> and its <Task> to
* a system understandable instruction set. In practice this means:
*
* * A shutdown task translates to a `at`-job
* * A start task is reflected as an entry in the
* `/sys/class/rtc/rtc0/wakealarm` file
*
* Shutdown:
*
* Start:
*
*
*/
var Scheduler = function Scheduler(options) {
if(!options) {
options = {};
}

if(!options.schedule) {
throw new Error('No schedule option passed');
}

this.schedule = options.schedule;
};



/** Function: scheduleNextUpcomingStart
*
*
* See also:
* * <scheduleWithAt>
*
* Parameters:
* (Function) callback
* (Function) scheduler - Scheduler function to schedule the next upcoming
* task.
*/
Scheduler.prototype.scheduleNextUpcomingStart =
function scheduleNextUpcomingStart(callback, scheduler) {

if(!scheduler) {
callback(new Error('Called without passing a scheduler.'));
}


var now = new Date()
, nextTask = this.schedule.getNextUpcomingTask(
now
, Task.prototype.START
);

if(nextTask) {
scheduler(nextTask, function(err) {
if(err === null) {
callback(null, nextTask);
} else {
callback(err, nextTask);
}
});
} else {
callback(new Error('No upcoming start task found'));
}
};

Scheduler.prototype.scheduleNextUpcomingShutdown =
function scheduleNextUpcomingShutdown(callback) {

var now = new Date()
, nextTask = this.schedule.getNextUpcomingTask(
now
, Task.prototype.SHUTDOWN
);

if(nextTask) {
callback(null, nextTask);
} else {
callback(new Error('No upcoming shutdown task found'));
}
};

module.exports = Scheduler;
67 changes: 67 additions & 0 deletions lib/scheduler/at.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
var spawn = require('child_process').spawn;

/** Function: scheduleWithAt
* Schedules the execution of a <Task> using the `at` utilities. To accomplish
* this, `at` is started as a child process using time and date of the <Task>
* as parameters. The actual action is written to `at`s `stdin`.
* After closing stdin, the `stderr` stream returns a message like
* `job 11 at Thu Jan 16 06:40:00 2014` containing an identifier of the
* scheduled task.
*
* The `callback` from the arguments is called after completing the scheduling.
* After success, the first parameter contains `null`, the second the job id
* which `at` assigned to our freshly scheduled job. If there was a problem,
* only an `Error` object with error description is given as first argument.
*
* See also:
* * http://unixhelp.ed.ac.uk/CGI/man-cgi?at
*
* Parameters:
* (Task) task - The task to schedule using `at`
* (Function) callback - Called after completion
*/
function scheduleWithAt(task, callback) {
var childProcess
, errorText
, jobId
, time = task.date.getHours() + ':' + task.date.getMinutes()
, date = task.date.getDate() + '.' +
(task.date.getMonth()+1) + '.' +
task.date.getFullYear();

childProcess = spawn('at', [time, date]);
childProcess.stdin.setEncoding('utf-8');
childProcess.stderr.setEncoding('utf-8');

// Feed the action to `at` and close stdin afterwards:
childProcess.stdin.write('subl', function() {
childProcess.stdin.end();
});

// Fetch any errors or the successful scheduled job id:
childProcess.stderr.on('data', function(data) {
// Example data value: job 11 at Thu Jan 16 06:40:00 2014
var jobidExtractor = /job\s(\d+)\sat/i
, matches = data.match(jobidExtractor);

if(matches) {
jobId = matches[1];
} else {
errorText = data;
}
});

// Execute the callback after child process terminates:
childProcess.on('close', function(signal) {
if(callback) {
if(signal === 0) {
callback(null, jobId);
} else {
callback(new Error('Scheduling task with `at` returned ' +
'signal ' + signal + '. stderr was: ' + errorText));
}
}
});
}

module.exports = scheduleWithAt;
61 changes: 0 additions & 61 deletions lib/systemAdapter.js

This file was deleted.

33 changes: 22 additions & 11 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
/*var powerbuddy = require('../index.js');
var spawn = require('child_process').spawn
, at = spawn('at', ['6:55AM', '15.01.2014']);

powerbuddy.planShutdown('everyday', '01:00');
powerbuddy.planStart('weekend', '10:00');
powerbuddy.planStart('weekday', '5pm');
powerbuddy.planShutdown(['sunday', 'monday'], '10am');
powerbuddy.plan('monday', '10am', '10pm');
*/
at.stdin.setEncoding('utf-8');
at.stdin.write('subl', function() {
at.stdin.end();
});

//var parser = require('../lib/parser');
//console.log(parser.parseTime('11am'));
at.stderr.setEncoding('utf-8');
at.stderr.on('data', function(data) {
// Example data value: job 11 at Thu Jan 16 06:40:00 2014
// Extract the job number.
var regex = /job\s(\d+)\sat/i
, matches = data.match(regex);

//var time = require('time-js');
//console.log(time('2pm').period());
if(matches) {
console.log('Scheduled task with id', matches[1]);
} else {
console.log('Could not schedule task :( Error:', data);
}
});

at.on('close', function(signal) {
console.log('signal: ', signal);
});
14 changes: 7 additions & 7 deletions test/lib/fakeFactory.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var days = require('../../lib/days')
, Schedule = require('../../lib/schedule')
, Task = require('../../lib/task')
var days = require('../../lib/model/days')
, Schedule = require('../../lib/model/schedule')
, Task = require('../../lib/model/task')
, Time = require('time-js')
, SystemAdapter = require('../../lib/systemAdapter');
, Scheduler = require('../../lib/scheduler');

function createTask(day, time, action) {
var scheduledDays = day || days.weekdays
Expand All @@ -28,9 +28,9 @@ function createSchedule(tasks) {
return schedule;
}

function createSystemAdapter() {
function createScheduler() {
var schedule = createSchedule()
, systemAdapter = new SystemAdapter({
, systemAdapter = new Scheduler({
schedule: schedule
});

Expand All @@ -40,5 +40,5 @@ function createSystemAdapter() {
module.exports = {
createTask: createTask
, createSchedule: createSchedule
, createSystemAdapter: createSystemAdapter
, createScheduler: createScheduler
};
2 changes: 1 addition & 1 deletion test/spec/days.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global describe, it, expect */
describe('Days', function() {
var days = require('../../lib/days');
var days = require('../../lib/model/days');

it('should define sunday with value 0', function() {
expect(days.sunday).to.be(0);
Expand Down
6 changes: 3 additions & 3 deletions test/spec/schedule.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* global describe, it, expect, before, after */
describe('Schedule', function() {
var Schedule = require('../../lib/schedule')
, Task = require('../../lib/task')
, days = require('../../lib/days')
var Schedule = require('../../lib/model/schedule')
, Task = require('../../lib/model/task')
, days = require('../../lib/model/days')
, Time = require('time-js')
, path = require('path')
, fs = require('fs')
Expand Down
Loading

0 comments on commit 5afc425

Please sign in to comment.