more work in progress, message bus diags

This commit is contained in:
Sam Saffron 2013-02-18 15:27:44 +11:00
parent 1228e351a8
commit cb0e53e701
9 changed files with 1111 additions and 436 deletions

View File

@ -9,12 +9,22 @@ window.App.start();
App.IndexRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('content', App.IndexModel.create());
model = App.IndexModel.create();
model.ensureSubscribed();
controller.set('content', model);
}
});
App.IndexView = Ember.View.extend({
App.IndexView = Ember.View.extend({});
App.Process = Ember.View.extend({
uniqueId: function(){
return this.get('hostname') + this.get('pid');
}.property('hostname', 'pid'),
hup: function(){
$.post("/message-bus/_diagnostics/hup/" + this.get('hostname') + "/" + this.get('pid'));
}
});
App.IndexModel = Ember.Object.extend({
@ -22,8 +32,31 @@ App.IndexModel = Ember.Object.extend({
return this.get("discovering") ? "disabled" : null;
}.property("discovering"),
ensureSubscribed: function() {
var processes;
var _this = this;
if(this.get("subscribed")) { return; }
MessageBus.callbackInterval = 500;
MessageBus.subscribe("/_diagnostics/process-discovery", function(data){
processes = _this.get('processes');
processes.pushObject(App.Process.create(data));
processes = processes.sort(function(a,b){
return a.get('uniqueId') < b.get('uniqueId') ? -1 : 1;
});
// somewhat odd ...
_this.set('processes', null);
_this.set('processes', processes);
});
this.set("subscribed", true);
},
discover: function(){
var _this = this;
this.set('processes', Em.A());
this.ensureSubscribed();
this.set("discovering", true);
Ember.run.later(function(){
@ -31,11 +64,6 @@ App.IndexModel = Ember.Object.extend({
}, 1 * 1000);
$.post("/message-bus/_diagnostics/discover");
MessageBus.subscribe("/process-discovery", function(data){
console.log(data);
});
}
});
@ -43,5 +71,9 @@ App.IndexModel = Ember.Object.extend({
App.IndexController = Ember.ObjectController.extend({
discover: function(){
this.get("content").discover();
},
hup: function(process) {
process.hup();
}
});

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,27 @@
/*
Copyright (C) 2011 by Yehuda Katz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// lib/handlebars/base.js
/*jshint eqnull:true*/
@ -5,7 +29,13 @@ this.Handlebars = {};
(function(Handlebars) {
Handlebars.VERSION = "1.0.rc.2";
Handlebars.VERSION = "1.0.0-rc.3";
Handlebars.COMPILER_REVISION = 2;
Handlebars.REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
2: '>= 1.0.0-rc.3'
};
Handlebars.helpers = {};
Handlebars.partials = {};
@ -618,9 +648,13 @@ return new Parser;
// lib/handlebars/compiler/base.js
Handlebars.Parser = handlebars;
Handlebars.parse = function(string) {
Handlebars.parse = function(input) {
// Just return if an already-compile AST was passed in.
if(input.constructor === Handlebars.AST.ProgramNode) { return input; }
Handlebars.Parser.yy = Handlebars.AST;
return Handlebars.Parser.parse(string);
return Handlebars.Parser.parse(input);
};
Handlebars.print = function(ast) {
@ -702,8 +736,11 @@ Handlebars.print = function(ast) {
for(var i=0,l=parts.length; i<l; i++) {
var part = parts[i];
if(part === "..") { depth++; }
else if(part === "." || part === "this") { this.isScoped = true; }
if (part === ".." || part === "." || part === "this") {
if (dig.length > 0) { throw new Handlebars.Exception("Invalid path: " + this.original); }
else if (part === "..") { depth++; }
else { this.isScoped = true; }
}
else { dig.push(part); }
}
@ -853,6 +890,26 @@ Handlebars.JavaScriptCompiler = function() {};
return out.join("\n");
},
equals: function(other) {
var len = this.opcodes.length;
if (other.opcodes.length !== len) {
return false;
}
for (var i = 0; i < len; i++) {
var opcode = this.opcodes[i],
otherOpcode = other.opcodes[i];
if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
return false;
}
for (var j = 0; j < opcode.args.length; j++) {
if (opcode.args[j] !== otherOpcode.args[j]) {
return false;
}
}
}
return true;
},
guid: 0,
@ -944,7 +1001,7 @@ Handlebars.JavaScriptCompiler = function() {};
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('pushHash');
this.opcode('emptyHash');
this.opcode('blockValue');
} else {
this.ambiguousMustache(mustache, program, inverse);
@ -953,7 +1010,7 @@ Handlebars.JavaScriptCompiler = function() {};
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('pushHash');
this.opcode('emptyHash');
this.opcode('ambiguousBlockValue');
}
@ -977,6 +1034,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('assignToHash', pair[0]);
}
this.opcode('popHash');
},
partial: function(partial) {
@ -1017,17 +1075,19 @@ Handlebars.JavaScriptCompiler = function() {};
},
ambiguousMustache: function(mustache, program, inverse) {
var id = mustache.id, name = id.parts[0];
var id = mustache.id,
name = id.parts[0],
isBlock = program != null || inverse != null;
this.opcode('getContext', id.depth);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('invokeAmbiguous', name);
this.opcode('invokeAmbiguous', name, isBlock);
},
simpleMustache: function(mustache, program, inverse) {
simpleMustache: function(mustache) {
var id = mustache.id;
if (id.type === 'DATA') {
@ -1158,7 +1218,7 @@ Handlebars.JavaScriptCompiler = function() {};
if(mustache.hash) {
this.hash(mustache.hash);
} else {
this.opcode('pushHash');
this.opcode('emptyHash');
}
return params;
@ -1175,7 +1235,7 @@ Handlebars.JavaScriptCompiler = function() {};
if(mustache.hash) {
this.hash(mustache.hash);
} else {
this.opcode('pushHash');
this.opcode('emptyHash');
}
return params;
@ -1189,7 +1249,7 @@ Handlebars.JavaScriptCompiler = function() {};
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function(parent, name, type) {
nameLookup: function(parent, name /* , type*/) {
if (/^[0-9]+$/.test(name)) {
return parent + "[" + name + "]";
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
@ -1204,7 +1264,11 @@ Handlebars.JavaScriptCompiler = function() {};
if (this.environment.isSimple) {
return "return " + string + ";";
} else {
return "buffer += " + string + ";";
return {
appendToBuffer: true,
content: string,
toString: function() { return "buffer += " + string + ";"; }
};
}
},
@ -1225,6 +1289,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.isChild = !!context;
this.context = context || {
programs: [],
environments: [],
aliases: { }
};
@ -1234,6 +1299,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.stackVars = [];
this.registers = { list: [] };
this.compileStack = [];
this.inlineStack = [];
this.compileChildren(environment, options);
@ -1255,11 +1321,11 @@ Handlebars.JavaScriptCompiler = function() {};
},
nextOpcode: function() {
var opcodes = this.environment.opcodes, opcode = opcodes[this.i + 1];
var opcodes = this.environment.opcodes;
return opcodes[this.i + 1];
},
eat: function(opcode) {
eat: function() {
this.i = this.i + 1;
},
@ -1297,7 +1363,6 @@ Handlebars.JavaScriptCompiler = function() {};
// Generate minimizer alias mappings
if (!this.isChild) {
var aliases = [];
for (var alias in this.context.aliases) {
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
}
@ -1322,16 +1387,48 @@ Handlebars.JavaScriptCompiler = function() {};
params.push("depth" + this.environment.depths.list[i]);
}
// Perform a second pass over the output to merge content when possible
var source = this.mergeSource();
if (!this.isChild) {
var revision = Handlebars.COMPILER_REVISION,
versions = Handlebars.REVISION_CHANGES[revision];
source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
}
if (asObject) {
params.push(this.source.join("\n "));
params.push(source);
return Function.apply(this, params);
} else {
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}';
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
return functionSource;
}
},
mergeSource: function() {
// WARN: We are not handling the case where buffer is still populated as the source should
// not have buffer append operations as their final action.
var source = '',
buffer;
for (var i = 0, len = this.source.length; i < len; i++) {
var line = this.source[i];
if (line.appendToBuffer) {
if (buffer) {
buffer = buffer + '\n + ' + line.content;
} else {
buffer = line.content;
}
} else {
if (buffer) {
source += 'buffer += ' + buffer + ';\n ';
buffer = undefined;
}
source += line + '\n ';
}
}
return source;
},
// [blockValue]
//
@ -1369,6 +1466,9 @@ Handlebars.JavaScriptCompiler = function() {};
var current = this.topStack();
params.splice(1, 0, current);
// Use the options value generated from the invocation
params[params.length-1] = 'options';
this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
},
@ -1392,6 +1492,9 @@ Handlebars.JavaScriptCompiler = function() {};
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function() {
// Force anything that is inlined onto the stack so we don't have duplication
// when we examine local
this.flushInline();
var local = this.popStack();
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
if (this.environment.isSimple) {
@ -1406,15 +1509,9 @@ Handlebars.JavaScriptCompiler = function() {};
//
// Escape `value` and append it to the buffer
appendEscaped: function() {
var opcode = this.nextOpcode(), extra = "";
this.context.aliases.escapeExpression = 'this.escapeExpression';
if(opcode && opcode.opcode === 'appendContent') {
extra = " + " + this.quotedString(opcode.args[0]);
this.eat(opcode);
}
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
},
// [getContext]
@ -1438,7 +1535,7 @@ Handlebars.JavaScriptCompiler = function() {};
// Looks up the value of `name` on the current context and pushes
// it onto the stack.
lookupOnContext: function(name) {
this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context'));
this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
},
// [pushContext]
@ -1486,7 +1583,7 @@ Handlebars.JavaScriptCompiler = function() {};
//
// Push the result of looking up `id` on the current data
lookupData: function(id) {
this.pushStack(this.nameLookup('data', id, 'data'));
this.push(this.nameLookup('data', id, 'data'));
},
// [pushStringParam]
@ -1509,13 +1606,25 @@ Handlebars.JavaScriptCompiler = function() {};
}
},
pushHash: function() {
this.push('{}');
emptyHash: function() {
this.pushStackLiteral('{}');
if (this.options.stringParams) {
this.register('hashTypes', '{}');
}
},
pushHash: function() {
this.hash = {values: [], types: []};
},
popHash: function() {
var hash = this.hash;
this.hash = undefined;
if (this.options.stringParams) {
this.register('hashTypes', '{' + hash.types.join(',') + '}');
}
this.push('{\n ' + hash.values.join(',\n ') + '\n }');
},
// [pushString]
//
@ -1534,7 +1643,8 @@ Handlebars.JavaScriptCompiler = function() {};
//
// Push an expression onto the stack
push: function(expr) {
this.pushStack(expr);
this.inlineStack.push(expr);
return expr;
},
// [pushLiteral]
@ -1577,12 +1687,14 @@ Handlebars.JavaScriptCompiler = function() {};
invokeHelper: function(paramSize, name) {
this.context.aliases.helperMissing = 'helpers.helperMissing';
var helper = this.lastHelper = this.setupHelper(paramSize, name);
this.register('foundHelper', helper.name);
var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
this.pushStack("foundHelper ? foundHelper.call(" +
helper.callParams + ") " + ": helperMissing.call(" +
helper.helperMissingParams + ")");
this.push(helper.name);
this.replaceStack(function(name) {
return name + ' ? ' + name + '.call(' +
helper.callParams + ") " + ": helperMissing.call(" +
helper.helperMissingParams + ")";
});
},
// [invokeKnownHelper]
@ -1594,7 +1706,7 @@ Handlebars.JavaScriptCompiler = function() {};
// so a `helperMissing` fallback is not required.
invokeKnownHelper: function(paramSize, name) {
var helper = this.setupHelper(paramSize, name);
this.pushStack(helper.name + ".call(" + helper.callParams + ")");
this.push(helper.name + ".call(" + helper.callParams + ")");
},
// [invokeAmbiguous]
@ -1609,19 +1721,18 @@ Handlebars.JavaScriptCompiler = function() {};
// This operation emits more code than the other options,
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function(name) {
invokeAmbiguous: function(name, helperCall) {
this.context.aliases.functionType = '"function"';
this.pushStackLiteral('{}');
var helper = this.setupHelper(0, name);
this.pushStackLiteral('{}'); // Hash value
var helper = this.setupHelper(0, name, helperCall);
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
this.register('foundHelper', helperName);
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
var nextStack = this.nextStack();
this.source.push('if (foundHelper) { ' + nextStack + ' = foundHelper.call(' + helper.callParams + '); }');
this.source.push('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.apply(depth0) : ' + nextStack + '; }');
},
@ -1640,7 +1751,7 @@ Handlebars.JavaScriptCompiler = function() {};
}
this.context.aliases.self = "this";
this.pushStack("self.invokePartial(" + params.join(", ") + ")");
this.push("self.invokePartial(" + params.join(", ") + ")");
},
// [assignToHash]
@ -1651,17 +1762,19 @@ Handlebars.JavaScriptCompiler = function() {};
// Pops a value and hash off the stack, assigns `hash[key] = value`
// and pushes the hash back onto the stack.
assignToHash: function(key) {
var value = this.popStack();
var value = this.popStack(),
type;
if (this.options.stringParams) {
var type = this.popStack();
type = this.popStack();
this.popStack();
this.source.push("hashTypes['" + key + "'] = " + type + ";");
}
var hash = this.topStack();
this.source.push(hash + "['" + key + "'] = " + value + ";");
var hash = this.hash;
if (type) {
hash.types.push("'" + key + "': " + type);
}
hash.values.push("'" + key + "': (" + value + ")");
},
// HELPERS
@ -1675,11 +1788,27 @@ Handlebars.JavaScriptCompiler = function() {};
child = children[i];
compiler = new this.compiler();
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
var index = this.context.programs.length;
child.index = index;
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context);
var index = this.matchExistingProgram(child);
if (index == null) {
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
index = this.context.programs.length;
child.index = index;
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context);
this.context.environments[index] = child;
} else {
child.index = index;
child.name = 'program' + index;
}
}
},
matchExistingProgram: function(child) {
for (var i = 0, len = this.context.environments.length; i < len; i++) {
var environment = this.context.environments[i];
if (environment && environment.equals(child)) {
return i;
}
}
},
@ -1723,57 +1852,111 @@ Handlebars.JavaScriptCompiler = function() {};
},
pushStackLiteral: function(item) {
this.compileStack.push(new Literal(item));
return item;
return this.push(new Literal(item));
},
pushStack: function(item) {
this.flushInline();
var stack = this.incrStack();
this.source.push(stack + " = " + item + ";");
if (item) {
this.source.push(stack + " = " + item + ";");
}
this.compileStack.push(stack);
return stack;
},
replaceStack: function(callback) {
var stack = this.topStack(),
item = callback.call(this, stack);
var prefix = '',
inline = this.isInline(),
stack;
// Prevent modification of the context depth variable. Through replaceStack
if (/^depth/.test(stack)) {
stack = this.nextStack();
// If we are currently inline then we want to merge the inline statement into the
// replacement statement via ','
if (inline) {
var top = this.popStack(true);
if (top instanceof Literal) {
// Literals do not need to be inlined
stack = top.value;
} else {
// Get or create the current stack name for use by the inline
var name = this.stackSlot ? this.topStackName() : this.incrStack();
prefix = '(' + this.push(name) + ' = ' + top + '),';
stack = this.topStack();
}
} else {
stack = this.topStack();
}
this.source.push(stack + " = " + item + ";");
var item = callback.call(this, stack);
if (inline) {
if (this.inlineStack.length || this.compileStack.length) {
this.popStack();
}
this.push('(' + prefix + item + ')');
} else {
// Prevent modification of the context depth variable. Through replaceStack
if (!/^stack/.test(stack)) {
stack = this.nextStack();
}
this.source.push(stack + " = (" + prefix + item + ");");
}
return stack;
},
nextStack: function(skipCompileStack) {
var name = this.incrStack();
this.compileStack.push(name);
return name;
nextStack: function() {
return this.pushStack();
},
incrStack: function() {
this.stackSlot++;
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
return this.topStackName();
},
topStackName: function() {
return "stack" + this.stackSlot;
},
flushInline: function() {
var inlineStack = this.inlineStack;
if (inlineStack.length) {
this.inlineStack = [];
for (var i = 0, len = inlineStack.length; i < len; i++) {
var entry = inlineStack[i];
if (entry instanceof Literal) {
this.compileStack.push(entry);
} else {
this.pushStack(entry);
}
}
}
},
isInline: function() {
return this.inlineStack.length;
},
popStack: function() {
var item = this.compileStack.pop();
popStack: function(wrapped) {
var inline = this.isInline(),
item = (inline ? this.inlineStack : this.compileStack).pop();
if (item instanceof Literal) {
if (!wrapped && (item instanceof Literal)) {
return item.value;
} else {
this.stackSlot--;
if (!inline) {
this.stackSlot--;
}
return item;
}
},
topStack: function() {
var item = this.compileStack[this.compileStack.length - 1];
topStack: function(wrapped) {
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
item = stack[stack.length - 1];
if (item instanceof Literal) {
if (!wrapped && (item instanceof Literal)) {
return item.value;
} else {
return item;
@ -1788,22 +1971,22 @@ Handlebars.JavaScriptCompiler = function() {};
.replace(/\r/g, '\\r') + '"';
},
setupHelper: function(paramSize, name) {
setupHelper: function(paramSize, name, missingParams) {
var params = [];
this.setupParams(paramSize, params);
this.setupParams(paramSize, params, missingParams);
var foundHelper = this.nameLookup('helpers', name, 'helper');
return {
params: params,
name: foundHelper,
callParams: ["depth0"].concat(params).join(", "),
helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
};
},
// the params and contexts arguments are passed in arrays
// to fill in
setupParams: function(paramSize, params) {
setupParams: function(paramSize, params, useRegister) {
var options = [], contexts = [], types = [], param, inverse, program;
options.push("hash:" + this.popStack());
@ -1848,7 +2031,13 @@ Handlebars.JavaScriptCompiler = function() {};
options.push("data:data");
}
params.push("{" + options.join(",") + "}");
options = "{" + options.join(",") + "}";
if (useRegister) {
this.register('options', options);
params.push('options');
} else {
params.push(options);
}
return params.join(", ");
}
};
@ -1886,23 +2075,23 @@ Handlebars.JavaScriptCompiler = function() {};
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
Handlebars.precompile = function(string, options) {
if (typeof string !== 'string') {
throw new Handlebars.Exception("You must pass a string to Handlebars.compile. You passed " + string);
Handlebars.precompile = function(input, options) {
if (!input || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
var ast = Handlebars.parse(string);
var ast = Handlebars.parse(input);
var environment = new Handlebars.Compiler().compile(ast, options);
return new Handlebars.JavaScriptCompiler().compile(environment, options);
};
Handlebars.compile = function(string, options) {
if (typeof string !== 'string') {
throw new Handlebars.Exception("You must pass a string to Handlebars.compile. You passed " + string);
Handlebars.compile = function(input, options) {
if (!input || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
}
options = options || {};
@ -1911,7 +2100,7 @@ Handlebars.compile = function(string, options) {
}
var compiled;
function compile() {
var ast = Handlebars.parse(string);
var ast = Handlebars.parse(input);
var environment = new Handlebars.Compiler().compile(ast, options);
var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
return Handlebars.template(templateSpec);
@ -1946,12 +2135,32 @@ Handlebars.VM = {
}
},
programWithDepth: Handlebars.VM.programWithDepth,
noop: Handlebars.VM.noop
noop: Handlebars.VM.noop,
compilerInfo: null
};
return function(context, options) {
options = options || {};
return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
var compilerInfo = container.compilerInfo || [],
compilerRevision = compilerInfo[0] || 1,
currentRevision = Handlebars.COMPILER_REVISION;
if (compilerRevision !== currentRevision) {
if (compilerRevision < currentRevision) {
var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
"Please update your runtime to a newer version ("+compilerInfo[1]+").";
}
}
return result;
};
},
@ -1990,4 +2199,3 @@ Handlebars.VM = {
Handlebars.template = Handlebars.VM.template;
;

View File

@ -1 +1,25 @@
<button {{action discover}} {{bindAttr disabled="disabled"}}>Discover Processes</button>
<table>
<thead>
<tr>
<td>pid</td>
<td>full_path</td>
<td>hostname</td>
<td>uptime</td>
<td></td>
</tr>
</thead>
<tbody>
{{#each processes}}
<tr>
<td>{{pid}}</td>
<td>{{full_path}}</td>
<td>{{hostname}}</td>
<td>{{uptime}} secs</td>
<td><button {{action hup this}}>HUP</button></td>
</tr>
{{/each}}
</tbody>
</table>

View File

@ -39,7 +39,7 @@ window.MessageBus = (function() {
callback.last_id = message.message_id;
callback.func(message.data);
}
if (message["channel"] === "/__status") {
if (message.channel === "/__status") {
if (message.data[callback.channel] !== void 0) {
callback.last_id = message.data[callback.channel];
}
@ -60,7 +60,7 @@ window.MessageBus = (function() {
start: function(opts) {
var poll,
_this = this;
if (opts == null) {
if (opts === null) {
opts = {};
}
poll = function() {

View File

@ -9,6 +9,7 @@ require "message_bus/reliable_pub_sub"
require "message_bus/client"
require "message_bus/connection_manager"
require "message_bus/message_handler"
require "message_bus/diagnostics"
require "message_bus/rack/middleware"
require "message_bus/rack/diagnostics"
@ -126,9 +127,7 @@ module MessageBus::Implementation
end
def enable_diagnostics
subscribe('/discover') do |msg|
MessageBus.publish '/process-discovery', Process.pid, user_id: msg.data[:user_id]
end
MessageBus::Diagnostics.enable
end
def publish(channel, data, opts = nil)

View File

@ -0,0 +1,44 @@
class MessageBus::Diagnostics
def self.full_process_path
begin
info = `ps -eo "%p|$|%a" | grep '^\\s*#{Process.pid}'`
info.strip.split('|$|')[1]
rescue
# skip it ... not linux or something weird
end
end
def self.hostname
begin
`hostname`.strip
rescue
# skip it
end
end
def self.enable
full_path = full_process_path
start_time = Time.now.to_f
hostname = self.hostname
# it may make sense to add a channel per machine/host to streamline
# process to process comms
MessageBus.subscribe('/_diagnostics/hup') do |msg|
if Process.pid == msg.data["pid"] && hostname == msg.data["hostname"]
$shutdown = true
sleep 4
Process.kill("HUP", $$)
end
end
MessageBus.subscribe('/_diagnostics/discover') do |msg|
MessageBus.publish '/_diagnostics/process-discovery', {
pid: Process.pid,
process_name: $0,
full_path: full_path,
uptime: (Time.now.to_f - start_time).to_i,
hostname: hostname
}, user_ids: [msg.data["user_id"]]
end
end
end

View File

@ -38,7 +38,7 @@ class MessageBus::Rack::Diagnostics
<body>
<div id="app"></div>
#{js_asset "jquery-1.8.2.js"}
#{js_asset "handlebars-1.0.rc.2.js"}
#{js_asset "handlebars.js"}
#{js_asset "ember.js"}
#{js_asset "message-bus.js"}
#{js_asset "application.handlebars"}
@ -72,7 +72,14 @@ HTML
return index unless route
if route == '/discover'
MessageBus.publish('/discover', {user_id: MessageBus.user_id_lookup.call(env)})
user_id = MessageBus.user_id_lookup.call(env)
MessageBus.publish('/_diagnostics/discover', user_id: user_id)
return [200, {}, ['ok']]
end
if route =~ /^\/hup\//
hostname, pid = route.split('/hup/')[1].split('/')
MessageBus.publish('/_diagnostics/hup', {hostname: hostname, pid: pid.to_i})
return [200, {}, ['ok']]
end

View File

@ -9,6 +9,8 @@ class MessageBus::Rack::Middleware
def self.start_listener
unless @started_listener
MessageBus.subscribe do |msg|
p msg.channel
p msg.message_id
EM.next_tick do
@@connection_manager.notify_clients(msg) if @@connection_manager
end