Reworking resource loader to be completly driven by node-cmu

This commit is contained in:
140b8f67-ec51-4b64-9606-bff2dffa0170 2016-04-11 23:48:11 -07:00
parent 2fbbddc878
commit 55310971c8
3 changed files with 198 additions and 173 deletions

View file

@ -0,0 +1,8 @@
/**
* Test Worker
*/
module.exports = function(input, done) {
};

View file

@ -34,10 +34,12 @@ const VERSION = "0.0.1";
* @const
*/
const _webSocketServer = require("ws").Server;
const _socket = require("ws").Server;
const _extend = require("./cmu-utils").extend;
const _spawn = require('threads').spawn;
const fs = require("fs");
/**
* Minimal Command
* @constants
@ -45,7 +47,7 @@ const fs = require("fs");
const REQUEST_VERSION = "version";
const REQUEST_PING = "ping";
const REQUEST_APPDRIVE = "appdrive";
const REQUEST_SETUP = "setup";
const RESULT_OK = 200;
const RESULT_PONG = 201;
@ -121,10 +123,10 @@ cmu.prototype = {
__construct: function()
{
// initial app drive
this.findAppDrive();
this.updateAppDrive();
// create webserver
this.__socket = new _webSocketServer({
this.__socket = new _socket({
port: this.network.port
});
@ -151,69 +153,24 @@ cmu.prototype = {
// assing
this.client.on('message', function(message) {
this._log('client:message', message);
this.handleClientData(client, message);
}.bind(this));
this.client.on('close', function() {
// do nothing
});
this._log('client:closed');
}.bind(this));
this.client.on('error', function(e) {
// do nothing
});
// let's try this
this.requestLoadJavascript(['test.js']);
this._log('client:error', e.message);
}.bind(this));
},
/**
* [requestLoadJavascript description]
* @param {[type]} files [description]
* @param {[type]} path [description]
* @return {[type]} [description]
*/
requestLoadJavascript: function(files, path) {
return this.sendCommand(COMMAND_LOAD_JS, {
filenames: files,
path: path
});
},
/**
* [requestLoadCSS description]
* @param {[type]} files [description]
* @param {[type]} path [description]
* @return {[type]} [description]
*/
requestLoadCSS: function(files, path) {
return this.sendCommand(COMMAND_LOAD_CSS, {
filenames: files,
path: path
});
},
/**
* Sends a command to the client
* @param {[type]} command [description]
* @param {[type]} payload [description]
* @param {[type]} client [description]
* @return {[type]} [description]
*/
sendCommand: function(command, attributes, client) {
this.sendFromPayload(client || this.client, {
command: command,
attributes: attributes,
});
},
/**
* Handles a client message
* @param object client The client instance
@ -223,7 +180,7 @@ cmu.prototype = {
handleClientData: function(client, message, flags) {
try {
var payload = JSON.parse(message);
let payload = JSON.parse(message);
// process minimal command interfae
if(payload.request) {
@ -253,14 +210,20 @@ cmu.prototype = {
break;
/**
* Finds the AppDrive
* @type REQUEST_APPDRIVE
* Setup
* @type REQUEST_SETUP
*/
case REQUEST_APPDRIVE:
case REQUEST_SETUP:
this.sendFromPayload(client, payload, {
appdrive: this.appdrive
});
if(this.appdrive && this.appdrive.enabled) {
// load javascripts
this.requestLoadJavascript(this.resources.js);
// load css
this.requestLoadCSS(this.resources.css);
}
break;
@ -289,7 +252,7 @@ cmu.prototype = {
*/
sendFromPayload: function(client, payload, data, resultCode) {
var final = JSON.stringify(_extend({}, payload, data, {
let final = JSON.stringify(_extend({}, payload, data, {
result: resultCode || RESULT_OK
}));
@ -297,6 +260,70 @@ cmu.prototype = {
},
/**
* Sends a command to the client
* @param {[type]} command [description]
* @param {[type]} payload [description]
* @param {[type]} client [description]
* @return {[type]} [description]
*/
sendCommand: function(command, attributes, client) {
this.sendFromPayload(client || this.client, {
command: command,
attributes: attributes,
});
},
/**
* [requestLoadJavascript description]
* @param {[type]} files [description]
* @return {[type]} [description]
*/
requestLoadJavascript: function(files) {
return this.invokeLoadCommand(COMMAND_LOAD_JS, files);
},
/**
* [requestLoadCSS description]
* @param {[type]} files [description]
* @return {[type]} [description]
*/
requestLoadCSS: function(files) {
return this.invokeLoadCommand(COMMAND_LOAD_CSS, files);
},
/**
* [invokeLoadCommand description]
* @param {[type]} command [description]
* @param {[type]} files [description]
* @return {[type]} [description]
*/
invokeLoadCommand: function(command, files) {
let source = files instanceof Array ? files : ([].push(files)),
data = [];
source.forEach(function(filename) {
if(this._isFile(filename)) {
data.push({
contents: (fs.readFileSync(filename)).toString(),
location: filename
});
}
}.bind(this));
this.sendCommand(command, {
data
});
},
/**
* Returns the version
* @getter
@ -312,21 +339,27 @@ cmu.prototype = {
* @param function callback A callback
* @return void
*/
findAppDrive: function(callback) {
updateAppDrive: function(callback) {
this.appdrive = {
locations: {},
applications: {},
enabled: false,
};
this.workers = {};
this.resources = {
js: [],
css: [],
};
var result = [],
let result = [],
mountPoints = ['sd_nav', 'sda', 'sdb', 'sdc', 'sdd', 'sde', 'sdf'];
mountPoints.forEach(function(mountPoint) {
var appDrivePath = [MOUNTROOT_PATH, mountPoint, APPDRIVE_PATH].join(""),
let appDrivePath = [MOUNTROOT_PATH, mountPoint, APPDRIVE_PATH].join(""),
appDriveFilename = [appDrivePath, APPDRIVE_JSON].join(""),
@ -359,9 +392,11 @@ cmu.prototype = {
* Load Framework
*/
this.appdrive.js.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_JS].join(""));
this.resources.js.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_JS].join(""));
this.appdrive.css.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_CSS].join(""))
this.resources.css.push([systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_CSS].join(""))
this.appdrive.enabled = true;
/**
* Prepare system mount
@ -379,7 +414,7 @@ cmu.prototype = {
* Find Applications
*/
var appFiles = fs.readdirSync(applicationsPath);
let appFiles = fs.readdirSync(applicationsPath);
if(appFiles.length) appFiles.forEach(function(appId) {
@ -390,11 +425,11 @@ cmu.prototype = {
if(!this.appdrive.applications[appId]) {
var applicationPath = [applicationsPath, appId, "/"].join("");
let applicationPath = [applicationsPath, appId, "/"].join("");
if(this._isDir(applicationPath)) {
var profile = {
let profile = {
id: appId,
path: applicationPath,
files: {},
@ -404,7 +439,7 @@ cmu.prototype = {
parts.forEach(function(filename) {
var fullFilename = [applicationPath, filename].join("");
let fullFilename = [applicationPath, filename].join("");
if(this._isFile(fullFilename)) {
@ -423,6 +458,8 @@ cmu.prototype = {
if(found >= 1) {
this.appdrive.applications[appId] = profile;
this.registerWorker(appId);
}
}
}
@ -435,6 +472,30 @@ cmu.prototype = {
if(callback) callback(this.appdrive);
},
/**
* Registers a worker to the appid
* @param {[type]} appId [description]
* @return {[type]} [description]
*/
registerWorker: function(appId) {
// ensure applications is registered
if(!this.appdrive.applications[appId]) return false;
// ensure worker is eligible
if(!this._isFile(this.appdrive.applications[appId].files[APPLICATION_WORKER])) return false;
// create worker
this.workers[appId] = {
appId: appId,
thread: _spawn(this.appdrive.applications[appId].files[APPLICATION_WORKER])
};
},
/**
* Checks if the file exists
* @param string path A string that represents a file path
@ -473,6 +534,27 @@ cmu.prototype = {
return false;
},
/**
* [__log description]
* @param {[type]} name [description]
* @param {[type]} description [description]
* @param {[type]} attributes [description]
* @return {[type]} [description]
*/
_log: function(name, description, attributes) {
console.log("[" + name + "]", description, attributes ? function() {
let result = [];
Object.keys(attributes).forEach(function(element, key, _array) {
result.push("[" + element + "=" + _array[key] + "]");
});
return result.join(" ");
}.call() : "");
},
};
/**

View file

@ -46,7 +46,7 @@ window.CMU = {
requests: {
REQUEST_PING: 'ping',
REQUEST_APPDRIVE: 'appdrive',
REQUEST_SETUP: 'setup',
},
/**
@ -80,7 +80,7 @@ window.CMU = {
this.initialized = true;
this.requests = {};
this.requestBuffer = {};
this.obtainConnection();
}
@ -125,6 +125,8 @@ window.CMU = {
this.__log("connection open");
this.requestSetup();
}.bind(this);
/**
@ -175,6 +177,15 @@ window.CMU = {
}
},
/**
* [requestSetup description]
* @return {[type]} [description]
*/
requestSetup: function() {
this.request(this.requests.REQUEST_SETUP);
},
/**
* [request description]
* @return {[type]} [description]
@ -186,12 +197,12 @@ window.CMU = {
// prepare id
var id = false;
while(!id || this.requests[id]) {
while(!id || this.requestBuffer[id]) {
id = (new Date()).getTime();
}
// register request
this.requests[id] = callback;
this.requestBuffer[id] = callback;
// sanity check
payload = payload || {};
@ -201,6 +212,8 @@ window.CMU = {
payload.request = request;
console.log(payload);
// execute
return this.client.send(JSON.stringify(payload));
},
@ -235,16 +248,16 @@ window.CMU = {
default:
// check against active requests
if(payload.requestId && this.requests[payload.requestId]) {
if(payload.requestId && this.requestBuffer[payload.requestId]) {
var callback = this.requests[payload.requestId];
var callback = this.requestBuffer[payload.requestId];
if(typeof(callback) == "function") {
callback(payload.result == this.results.RESULT_ERROR, payload);
}
delete this.requests[payload.requestId];
delete this.requestBuffer[payload.requestId];
return; // all done
}
@ -270,117 +283,39 @@ window.CMU = {
/** @type {LOADJS} [description] */
case this.commands.LOAD_JS:
this.loadJavascript(attributes.filenames, attributes.path);
this.__loadInvoker(attributes, 'script', 'text/javascript');
break;
/** @type {LOADCSS} */
case this.commands.LOAD_CSS:
this.__loadInvoker(attributes, 'style', 'text/css');
break;
}
},
/**
* (loadJavascript)
*/
loadJavascript: function(scripts, path, callback, options) {
this.__loadInvoker(scripts, path, function(filename, next) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = filename;
script.onload = next;
document.body.appendChild(script);
}, callback, options);
},
/**
* (loadCSS)
*/
loadCSS: function(css, path, callback, options) {
this.__loadInvoker(css, path, function(filename, next) {
var css = document.createElement('link');
css.rel = "stylesheet";
css.type = "text/css";
css.href = filename
css.onload = async ? callback : next;
document.body.appendChild(css);
}, callback, options);
},
/**
* (__loadInvoker)
*/
__loadInvoker: function(input, path, build, callback, options) {
__loadInvoker: function(attributes, tag, type) {
// sanity checks
if(typeof(build) != "function") return false;
if(!attributes.data || !attributes.data instanceof Array) return false;
// initialize
var ids = false, result = false, options = options ? options : {timeout: 1000}, timeout = false;
attributes.data.forEach(function(item) {
// items need to be an array
var items = input instanceof Array ? input : function() {
if(item.location && item.contents) {
var newArray = [];
var element = document.createElement(tag);
element.setAttribute("data-script-url", item.location);
element.appendChild(document.createTextNode(item.contents));
newArray.push(input);
return newArray;
}.call();
// loaded handler
var loaded = 0, next = function(failure) {
loaded++;
if(loaded >= items.length) {
if(typeof(callback) == "function") {
callback(result);
}
}
};
// process items
items.forEach(function(filename, index) {
try {
filename = (path ? path : "") + filename;
if(options.timeout) {
clearTimeout(timeout);
timeout = setTimeout(function() {
this.__error("__loadInvoker:timeout", {filename: filename});
// just do the next one
next(true);
}.bind(this), options.timeout);
}
try {
build(filename, function(resource) {
next();
}.bind(this), ids ? ids[index] : false);
} catch(error) {
next(true);
}
} catch(error) {
this.__error("__loadInvoker:loaderror", {error: error, filename: filename});
if(type) element.setAttribute("type", type);
document.head.appendChild(element);
}
}.bind(this));
return true;
});
},
/**