Browse Source

Updating hci

Luis Figueiredo 8 years ago
parent
commit
4d6757df37

+ 6 - 7
bundles/core-http/index.js

@@ -1,20 +1,19 @@
 const http = require('http');
-const log = require('hlogger').createLogger('hci-http');
+const log = require('hlogger').createLogger('core-http');
 
 var activator = {
 
 	start(context) {
 		this.server = http.createServer((req,res) => {
-			var lurl = req.url.replace(/^\/|\/$/g,'');  // Replace all starting "/" or ending "/"
+			var lurl = req.url.replace(/^\/|\/$/g,'');  // remove all starting "/" or ending "/"
 			// New
-			context
-				.channel(context.name).channel(req.method)
+			context.events
+				.channel(context.name, "request",req.method)
 				.propagate(lurl,req,res)
-				.done((e) => {
-					if(e.count == 0) {
+				.then((e) => {
+					if(e.count == 0 || res.statusCode == 404) {
 						res.writeHead(404,"Not found");
 						res.end("Not found");
-						console.log("Every thing is done");
 					}
 				});
 			// Different way

+ 2 - 2
bundles/core-installer/index.js

@@ -16,12 +16,12 @@ var installerActivator = {
 		this.runPath = context.manager.config.runPath;
 		if(this.deployPath == undefined) {
 			log.warn("There is no deploy path configured");
-			context.channel(context.name).set("installed",true);
+			context.events.channel(context.name).set("installed",true);
 			//context.emit('installed');
 			return;
 		}
 		if(this.runPath == undefined) {
-			context.channel(context.name).set("installed",true);
+			context.events.channel(context.name).set("installed",true);
 			return;
 		}
 

+ 8 - 6
bundles/core-loader/index.js

@@ -17,7 +17,7 @@ var loaderActivator = {
 			log.warn("There is no runPath configured in manager");
 			return;
 		}
-		context
+		context.events
 			.channel('core-installer')
 			.watch('installed',(value) => {
 				console.log("core-installer:installed is:",value);
@@ -37,18 +37,19 @@ var loaderActivator = {
 		}
 	},
 	startPlugin(plugPath) {
-		var dirparts = path.basename(plugPath).split(path.sep);
+		this.manager.load(plugPath);
+		/*var dirparts = path.basename(plugPath).split(path.sep);
 		var dirname = dirparts[dirparts.length-1];
 
 		//var plugInfo = require(path.join(plugPath , "package.json"));
 		var plugName = dirname;
-		this.manager.register({name:plugName, bundle:plugPath});
+		this.manager.register({name:plugName, bundle:plugPath});*/
 	},
 
 	registerShell(context) {
 		//var prefix = context.prefix(".*:cmd"); // Any cmd sender
-		context
-			.channel('core-shell').channel('cmd')
+		context.events
+			.channel('core-shell','cmd')
 			.on('lb',(req,res) => {
 				var tbl = [];
 				for(var k in context.manager.registry) {
@@ -86,7 +87,8 @@ var loaderActivator = {
 			}
 			return bcontext;
 		}
-		context.channel('core-shell').channel('cmd')
+		context.events
+			.channel('core-shell','cmd')
 			.on('stop',(req,res) => {
 				var bcontext = commonGetBundle(req,res,1);
 				if(bcontext == null) { return; }

+ 1 - 1
bundles/core-monitor/index.js

@@ -21,7 +21,7 @@ var monitor = {
 	},
 
 	registerCommands(context) {
-		context
+		context.events
 			.channel('core-shell:cmd')
 			.on('stat',(req,res,e) => {
 				this.showStat(res); // Should pass stdout

+ 19 - 17
bundles/core-shell/index.js

@@ -5,13 +5,13 @@ var path = require('path');
 
 
 var shellActivator = {
-
 	start(context) {
 		this.context = context;
 		this.manager = context.manager;
 
 		this.stdout = process.stdout;
 		this.registerCommands(context);	
+
 		this.cli = readline.createInterface(process.stdin,this.stdout,(str) => this.completer(str));
 		this.cli.setPrompt("HCI> ");
 	
@@ -20,16 +20,15 @@ var shellActivator = {
 			var [cmd,...args] = cmd.split(/\s/);
 			var req = { cmd:cmd, args:args }
 			var res = this.stdout;
-			context
-				.channel(context.name).channel('cmd')
-				.emit(cmd,req,res)
-				.done((evt)=> {
-					if(evt.count == 0) {
-						context
-							.channel(context.name)
-							.emit("cmd",req,res).done(() => { this.cli.prompt() });
-					}
+			context.events
+				.channel(context.name,'cmd')
+				.propagate(cmd,req,res)
+				.then((evt)=> {
+					if(evt.count == 0) console.log("Command not found:" + cmd);
+						// This is wrong perhaps
 					this.cli.prompt();	
+				}).catch((err) => {
+					console.log("Promise error: ", err);
 				});
 		});
 
@@ -40,14 +39,17 @@ var shellActivator = {
 		this.cli.close();
 	},
 	completer(str) {
-		var hits = this.manager.listeners
-			.filter((v)=> {
-				var re = new RegExp("^"+ this.context.name + ":cmd:" +str + ".*");
-				if(re.test(v.name)) {
-					return v;
+		// Hack
+		var re = new RegExp("^"+ this.context.name + "/cmd/(" + str + ".*)");
+		var hits = [];
+		this.manager.eventual._events.ctx.forEach((ctx) => {
+			Object.keys(ctx.listeners).forEach((k) => {
+				var res = k.match(re);
+				if(res) {
+					hits.push(res[1]);
 				}
-			}).map((v) => v.name.split(":")[2] + " ");
-
+			});
+		});
 		return [hits,str];
 	},
 	output(str) {

+ 5 - 0
doc/README.md

@@ -0,0 +1,5 @@
+# HCI - Continuous Integration
+
+
+##
+

+ 7 - 9
doc/TODO.md

@@ -1,7 +1,5 @@
 
 ###
-* Possible bug, toggleOn if a module is registered, and unloaded, toggleOn remains?
-* 
 * A bug seems to exist that if module is stopped it keeps emitting events
 		find a way to prevent events from being emitted if stopped
 
@@ -10,21 +8,21 @@
 	figure if use a public key set on manager or a simple module to handle configuration
 	create a Load path method
 
+* Reduce the Context complexity having proper names 
+* consider the command context for proper commandEntry, check restcli how its done
+*
+### Done
+* Consider creating a contextual link for the possibility of modules add data to other modules
+	but when one of those is removed it wont leave any traces, either by name (persistent) or ctx
 * Consider returning a events on context as in
 	context.events.on('hci-http');
 		instead of
 	context.on('hci-http');
-	
 	context.events.on('hci-http:start');
 	context.manager.with('pak1','pak2').do().else();
 
-* Reduce the Context complexity having proper names 
 
-* consider the command context for proper commandEntry, check restcli how its done
-* Consider creating a contextual link for the possibility of modules add data to other modules
-	but when one of those is removed it wont leave any traces, either by name (persistent) or ctx
-
-### Done
+* Possible bug, toggleOn if a module is registered, and unloaded, toggleOn remains?
 * transform this to a module and separate the app, as in remove index.js from starting manager
 * Create method to solve module name:
 	manager.load(path);

+ 3 - 0
doc/eventual/emit.md

@@ -0,0 +1,3 @@
+## Eventual.emit
+
+Changed process return to a promise, seems to suit better 

+ 2 - 0
doc/hci/context.md

@@ -0,0 +1,2 @@
+## TODO:
+avoid code repetition on the events side, context should be handled appart

+ 0 - 32
doc/ideas.js

@@ -1,32 +0,0 @@
-// This JS doesn't do anything, just want to have syntax highlight on my thoughts
-//
-//
-
-/*
-watcher and set pattern for any case of flags
-lets say loader wants to wait for installer state, can't be an event since it will
-
-
-
-
-
-commChannel with two points
-
-	obj1 <- channel -> obj2
-
-
-as obj2:  channel.send('hello');
-
-obj1:
-	// Seems like a 2 way event system
-	channel.on('hello');
-
-
-
-this
-	.observe('something:value')
-
-		
-
-subscribe()
-

+ 2 - 0
index.js

@@ -1,2 +1,4 @@
 module.exports = require('./lib/bundle-manager');
 
+
+

+ 6 - 4
lib/bundle-context.js

@@ -97,6 +97,8 @@ class BundleContext /*extends XEventEmitter*/ {
 		}
 		this.info.state = 1;
 		this.info.startDate = new Date();
+
+		this.events.channel(this.name).emit('start');
 	}
 
 	stop() {
@@ -117,9 +119,9 @@ class BundleContext /*extends XEventEmitter*/ {
 		this.info.state = 0;
 	}
 
-	channel(name) {
-		return this.events.channel(name);
-	}
+	/*channel(...names) {
+		return this.events.channel(...names);
+	}*/
 	/*emit(name,...args) {
 		return this.events.emit(this.name + ":" +name,...args);
 	}
@@ -163,7 +165,7 @@ class BundleContext /*extends XEventEmitter*/ {
 	 * @param {variable} ...args
 	 */
 	call(name,...args) {
-		return this.manager.call(name,args);
+		return this.manager.call(name,...args);
 	}
 
 	// Auto clear helpers

+ 2 - 2
lib/bundle-manager.js

@@ -170,7 +170,7 @@ class BundleManager {
 	}
 
 	// Batch call
-	call(name,args) {
+	call(name,...args) {
 		var [ctxName, method] = name.split(":")
 		var matchCtx = new RegExp(ctxName);
 		var fretList = [];
@@ -184,7 +184,7 @@ class BundleManager {
 				ret.result = 0;
 				ret.error = "method not found";
 			} else {
-				ret.result = ctx.instance[method](args);
+				ret.result = ctx.instance[method](...args);
 			}
 			fretList.push(ret);
 		}

+ 13 - 11
lib/eventual/lib/context/channel.js

@@ -1,5 +1,4 @@
 
-const chs = "/"; // Channel separator
 
 
 class Channel {
@@ -8,23 +7,27 @@ class Channel {
 		this._name = name; // Full name
 	}
 	name(name) {
-		if(name == undefined) return this._name;
-		return this._name + chs + name;
+		if(name == undefined || name.length === 0) return this._name;
+		return this._name + Channel.SEP + name;
 	}
 	channel(...names) { // Sub channel
-		var name = names.join("/");
-		return new Channel(this.context,this.name(name));
-	}
-	on(sname,callback,order) {
+		var name = names.join(Channel.SEP);
+		var finalName = this.name(name);
+		//console.log("Desired channel:" , names, "Result", finalName);
+		return new Channel(this.context,finalName);
+	}
+	on(sname,callback,order = 0) {
+		if(typeof(sname) != "string"){
+			throw new Error("First argument should be a string");
+		}
 		var name = this.name(sname);
 		var listener = this.context.get(name,true);
 		listener.callbacks.push({name,callback,order});
 		//this.context.on(this.name(name),cb,order);
-		
 		return this;
 	}
 	after(name,cb) {
-		this.on(this.name(name),cb,1000);
+		this.on(name,cb,1000);
 		return this;
 	}
 	emit(name,...args){
@@ -46,8 +49,7 @@ class Channel {
 
 		//this.context.watch(this.name + ":" + name,cb);
 	}
-
-
 }
+Channel.SEP = "/"; // Channel separator
 
 module.exports = Channel;

+ 7 - 5
lib/eventual/lib/context/context.js

@@ -1,10 +1,10 @@
 var Channel = require("./channel");
 
 
-class EventualContext {
+class Context {
 
 	constructor(eventual) {
-		this.version = "Context MAP version";
+		this.version = "Context obj MAP version";
 		this.eventual = eventual;
 		//this.listeners = new Map();
 		this.listeners = {}; // Flat map
@@ -13,8 +13,10 @@ class EventualContext {
 	destroy() {
 		this.eventual.destroyContext(this);
 	}
-	channel(name) {
-		return new Channel(this,name);
+	// Create a master channel inheritance?	
+	channel(...names) {
+		var finalName = names.join(Channel.SEP);
+		return new Channel(this,finalName);
 	}
 	get(name,create) {
 		if(!this.listeners[name] && create) {
@@ -47,4 +49,4 @@ class EventualContext {
 	}
 }
 
-module.exports = EventualContext;
+module.exports = Context;

+ 7 - 1
lib/eventual/lib/event-param.js

@@ -1,13 +1,19 @@
 // Create event .js
 class Event {
 	constructor(donecb,args) {
-		this.count = 0;
+		this._count = 0;
 		this._dowait = 0;
 		this._dostop = 0;
 		this.done= donecb; // Callback
 		this.errors = [];
 		this.params = args;
 	}
+	get count() {
+		return this._count;
+	}
+	consume() {
+		this._count++;
+	}
 	wait() {
 		this._dowait = 1;
 	}

+ 43 - 9
lib/eventual/lib/eventual.js

@@ -2,6 +2,7 @@
  * Substitute for xeventx
  * */
 
+const Channel = require('./context/channel');
 const EventualContext = require('./context');
 const EventParam = require('./event-param');
 
@@ -43,32 +44,29 @@ class Eventual {
 		this.set(name,undefined);
 	}
 
+	// Private?
 	emit(name,...args) {
 		// Special send to all eventual contexts
 		var tocall = this.callbacks(name);
-
 		return this.process(tocall,args)
 	}
 	propagate(name,nameto,...args) {
-		var nparts = name.split("/");
+		var nparts = name.split(Channel.SEP);
 		var tocall = [];
 
 		var sname = name;
 		while(nparts.length && sname != nameto)  {
 			var localCall = this.callbacks(sname);
-			console.log("Found: " + localCall.length + " in : " + sname);
 			// Limitation on argument size
 			tocall.push(...localCall);
 			nparts.pop();
-			sname = nparts.join("/");
+			sname = nparts.join(Channel.SEP);
 		}
 		var localCall = this.callbacks(sname);
-		console.log("Found: " + tocall.length + " in : " + sname);
 		tocall.push(...localCall);
 		return this.process(tocall,args);	
 	}
 
-
 	callbacks(name) {
 		var tocall = [];		
 		this._events.ctx.forEach((c) => {
@@ -83,11 +81,47 @@ class Eventual {
 			l.callback(...nargs);
 		});
 	}
-	// process should be handled here
 	process(tocall,nargs) {
+		var args = nargs || [];
+
+		tocall = tocall.sort((a,b) => {
+			return (a.order - b.order);
+		});
+		var iter = tocall[Symbol.iterator]();
+		var ret = new Promise((resolve,reject) => {
+			var evt = new EventParam(next,args);
+			function next() {
+				process.nextTick(()=> chain(iter));
+			}
+			function chain(iter) {
+				var v = iter.next();
+				if(v.done) { resolve(evt); return; }
+				try {
+					var entry = v.value;
+					evt.args = args;
+					evt.name = entry.name;
+					entry.callback(...args,evt);
+					evt.consume();
+					if(evt._dostop == 1) {
+						resolve(evt);
+						return;	
+					}
+				} catch(e)  {
+					console.log(e);
+					evt.errors.push(e);
+				}
+				if(!evt._dowait) next();
+				evt._dowait = 0;
+			}
+			next(); // Start chain
+		});
+		return ret;
+	}
+	// process should be handled here
+	processRetDone(tocall,nargs) {
 		var args = nargs || [];	 // or empty
 		var evt = new EventParam(next,args); // Travel between events
-		
+
 		var callback,dotrigger = 0;
 		function triggerDone() {
 			if(callback) callback(evt);
@@ -131,7 +165,7 @@ class Eventual {
 					triggerDone();
 					return;	
 				}
-				evt.count++;
+				evt.consume();
 			}catch(e) {
 				console.log(e);
 				evt.errors.push(e);

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "@hexasoftware/hci",
-  "version": "0.0.6",
+  "version": "0.0.9",
   "description": "Hexa Continuous Integration",
   "main": "index.js",
   "author": {

+ 30 - 0
test/eventual-test/chain.js

@@ -0,0 +1,30 @@
+var Eventual = require('../../lib/eventual');
+
+
+
+
+
+
+
+var events = new Eventual();
+
+
+var ctx = events.createContext();
+
+ctx
+	.channel('core')
+	.on('hello',(e) => {
+		e.wait();
+		setTimeout(() => {
+			console.log("Someone said hello?");
+			e.done();
+		},2000);	
+	});
+	
+ctx
+	.channel('core')
+	.emit('hello')
+	.then((evt) => {
+		console.log("evt: ", evt);	
+	});
+

+ 2 - 1
test/hci-usecase/bundles/hci-http-monitor/index.js

@@ -21,12 +21,13 @@ function loadControllers() {
 
 function bundleStart(context) {
 	var controllers = loadControllers();
-	var channel = context
+	context.events
 		.channel('core-http')
 		.on('stop',()=> {
 			console.log("Stopping http monitor");
 			context.stop();
 		})
+		.channel('request')
 		.on('GET/monitor/api',(req,res,e) => {
 			e.stop();
 			// Manual router

+ 1 - 1
test/hci-usecase/bundles/memory-monitor/index.js

@@ -2,7 +2,7 @@ var log = require('hlogger').createLogger('memory-monitor');
 
 var activator = {
 	start(context) {
-		context
+		context.events
 			.channel('core-shell:cmd')
 			.on('memory',(req,res) => {
 				if(req.cmd == "start") {

+ 3 - 2
test/hci-usecase/bundles/shell-test/index.js

@@ -6,12 +6,13 @@ function bundleStart(context) {
 	log.info("Command provider installed");
 
 	// Create a bash and transport commands
-	context.channel('core-shell')
+	context.events
+		.channel('core-shell')
 		.after('cmd',(req,res,e) => {
+			if(e.count != 0) return;
 			e.wait();	
 			var shcmd = req.cmd + " " + req.args.join(" ");
 			var proc = child.exec(shcmd);
-			res.write("\n");
 			proc.stdout.pipe(res);
 			proc.stderr.pipe(process.stderr);
 			proc.on('close',function() {

+ 3 - 2
test/hci-usecase/bundles/stress-test/http-test/index.js

@@ -1,8 +1,9 @@
 
 var activator = {
 	start(context) {
-		context.channel('core-http')
-			.on('hci-http:req:/test',(req,res) => {
+		context.events
+			.channel('core-http')
+			.on('GET/test',(req,res) => {
 				res.end('Hello word');
 			});
 	}

+ 2 - 2
test/hci-usecase/bundles/stress-test/index.js

@@ -18,7 +18,7 @@ module.exports.bundleActivator = {
 	start(context) {
 		context.manager.load(__dirname + "/http-test");
 		this.context = context;
-		context
+		context.events
 			.channel('core-shell').channel('cmd')
 			.on('test',(req,res,e) => {
 				var cmds = ["events","cpu","mem","ping","siege"]; 
@@ -34,7 +34,7 @@ module.exports.bundleActivator = {
 
 		var lastPing; 
 
-		var lchannel = context.channel('stress-test');
+		var lchannel = context.events.channel('stress-test');
 		lchannel
 			.on('ping',(e) => {
 				lastPing = process.hrtime();