Skip to content

Commit

Permalink
Added watch support.
Browse files Browse the repository at this point in the history
  • Loading branch information
Stevenic committed Mar 8, 2017
1 parent 125f22b commit b77f683
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 10 deletions.
90 changes: 86 additions & 4 deletions Node/core/lib/Session.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var Message_1 = require("./Message");
var consts = require("./consts");
var sprintf = require("sprintf-js");
var events = require("events");
var async = require("async");
var Session = (function (_super) {
__extends(Session, _super);
function Session(options) {
Expand Down Expand Up @@ -39,6 +40,7 @@ var Session = (function (_super) {
userData: this.userData,
conversationData: this.conversationData,
privateConversationData: this.privateConversationData,
dialogData: this.dialogData,
localizer: this.localizer,
logger: this.logger,
dialogStack: function () { return _this.dialogStack(); },
Expand Down Expand Up @@ -489,6 +491,53 @@ var Session = (function (_super) {
this.error(new Error('Invalid Dialog Stack.'));
}
};
Session.prototype.watch = function (variable, enable) {
if (enable === void 0) { enable = true; }
var name = variable.toLowerCase();
if (!this.userData.hasOwnProperty(consts.Data.DebugWatches)) {
this.userData[consts.Data.DebugWatches] = {};
}
if (watchableHandlers.hasOwnProperty(name)) {
var entry = watchableHandlers[name];
this.userData[consts.Data.DebugWatches][entry.name] = enable;
}
else {
throw new Error("Invalid watch statement. '" + variable + " isn't watchable");
}
return this;
};
Session.prototype.watchList = function () {
var watches = [];
if (this.userData.hasOwnProperty(consts.Data.DebugWatches)) {
for (var name_1 in this.userData[consts.Data.DebugWatches]) {
if (this.userData[consts.Data.DebugWatches][name_1]) {
watches.push(name_1);
}
}
}
return watches;
};
Session.watchable = function (variable, handler) {
if (handler) {
watchableHandlers[variable.toLowerCase()] = { name: variable, handler: handler };
}
else {
var entry = watchableHandlers[variable.toLowerCase()];
if (entry) {
handler = entry.handler;
}
}
return handler;
};
Session.watchableList = function () {
var variables = [];
for (var name_2 in watchableHandlers) {
if (watchableHandlers.hasOwnProperty(name_2)) {
variables.push(watchableHandlers[name_2].name);
}
}
return variables;
};
Session.prototype.onSave = function (cb) {
var _this = this;
this.options.onSave(function (err) {
Expand Down Expand Up @@ -519,12 +568,36 @@ var Session = (function (_super) {
};
Session.prototype.onFinishBatch = function (cb) {
var _this = this;
this.logger.flush(function (err) {
_this.sendingBatch = false;
var ctx = this.toRecognizeContext();
async.each(this.watchList(), function (variable, cb) {
var entry = watchableHandlers[variable];
if (entry && entry.handler) {
try {
entry.handler(ctx, function (err, value) {
if (!err) {
_this.logger.dump(variable, value);
}
cb(err);
});
}
catch (e) {
cb(e);
}
}
else {
cb(new Error("'" + variable + "' isn't watchable."));
}
}, function (err) {
if (err) {
console.error(err);
_this.logger.error(_this.dialogStack(), err);
}
cb();
_this.logger.flush(function (err) {
_this.sendingBatch = false;
if (err) {
console.error(err);
}
cb();
});
});
};
Session.prototype.startBatch = function () {
Expand Down Expand Up @@ -642,3 +715,12 @@ var Session = (function (_super) {
return Session;
}(events.EventEmitter));
exports.Session = Session;
var watchableHandlers = {
'userdata': { name: 'userData', handler: function (ctx, cb) { return cb(null, ctx.userData); } },
'conversationdata': { name: 'conversationData', handler: function (ctx, cb) { return cb(null, ctx.conversationData); } },
'privateconversationdata': { name: 'privateConversationData', handler: function (ctx, cb) { return cb(null, ctx.privateConversationData); } },
'dialogdata': { name: 'dialogData', handler: function (ctx, cb) { return cb(null, ctx.dialogData); } },
'dialogstack': { name: 'dialogStack', handler: function (ctx, cb) { return cb(null, ctx.dialogStack()); } },
'preferredlocale': { name: 'preferredLocale', handler: function (ctx, cb) { return cb(null, ctx.preferredLocale()); } },
'libraryname': { name: 'libraryName', handler: function (ctx, cb) { return cb(null, ctx.libraryName); } }
};
3 changes: 2 additions & 1 deletion Node/core/lib/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ exports.Data = {
Field: 'BotBuilder.Data.Field',
FirstRunVersion: 'BotBuilder.Data.FirstRunVersion',
PreferredLocale: 'BotBuilder.Data.PreferredLocale',
DebugAddress: 'BotBuilder.Data.DebugAddress'
DebugAddress: 'BotBuilder.Data.DebugAddress',
DebugWatches: 'BotBuilder.Data.DebugWatches'
};
exports.DialogId = {
Prompts: 'BotBuilder:Prompts',
Expand Down
105 changes: 101 additions & 4 deletions Node/core/src/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export interface ISessionMiddleware {
(session: Session, next: Function): void;
}

export interface IWatchableHandler {
(context: IRecognizeContext, callback: (err: Error, value: any) => void): void;
}

export class Session extends events.EventEmitter {
private msgSent = false;
private _isReset = false;
Expand Down Expand Up @@ -89,6 +93,7 @@ export class Session extends events.EventEmitter {
userData: this.userData,
conversationData: this.conversationData,
privateConversationData: this.privateConversationData,
dialogData: this.dialogData,
localizer: this.localizer,
logger: this.logger,
dialogStack: () => { return this.dialogStack(); },
Expand Down Expand Up @@ -603,6 +608,62 @@ export class Session extends events.EventEmitter {
}
}

//-----------------------------------------------------
// Watch Statements
//-----------------------------------------------------

/** Enables/disables the watch statment for a given variable. */
public watch(variable: string, enable = true): this {
let name = variable.toLowerCase();
if (!this.userData.hasOwnProperty(consts.Data.DebugWatches)) {
this.userData[consts.Data.DebugWatches] = {};
}
if (watchableHandlers.hasOwnProperty(name)) {
var entry = watchableHandlers[name];
this.userData[consts.Data.DebugWatches][entry.name] = enable;
} else {
throw new Error("Invalid watch statement. '" + variable + " isn't watchable");
}
return this;
}

/** Returns the list of enabled watch statements for the session. */
public watchList(): string[] {
var watches: string[] = [];
if (this.userData.hasOwnProperty(consts.Data.DebugWatches)) {
for (let name in this.userData[consts.Data.DebugWatches]) {
if (this.userData[consts.Data.DebugWatches][name]) {
watches.push(name);
}
}
}
return watches;
}

/** Adds or retrieves a watchable variable from the session. */
static watchable(variable: string, handler?: IWatchableHandler): IWatchableHandler {
if (handler) {
watchableHandlers[variable.toLowerCase()] = { name: variable, handler: handler };
} else {
let entry = watchableHandlers[variable.toLowerCase()];
if (entry) {
handler = entry.handler;
}
}
return handler;
}

/** Returns the list of watchable variables. */
static watchableList(): string[] {
let variables: string[] = [];
for (let name in watchableHandlers) {
if (watchableHandlers.hasOwnProperty(name)) {
variables.push(watchableHandlers[name].name);
}
}
return variables;
}

//-----------------------------------------------------
// PRIVATE HELPERS
//-----------------------------------------------------
Expand Down Expand Up @@ -637,12 +698,36 @@ export class Session extends events.EventEmitter {
}

private onFinishBatch(cb: Function): void {
this.logger.flush((err) => {
this.sendingBatch = false;
// Dump watchList
var ctx = this.toRecognizeContext();
async.each(this.watchList(), (variable, cb) => {
let entry = watchableHandlers[variable];
if (entry && entry.handler) {
try {
entry.handler(ctx, (err, value) => {
if (!err) {
this.logger.dump(variable, value);
}
cb(err);
});
} catch (e) {
cb(e);
}
} else {
cb(new Error("'" + variable + "' isn't watchable."));
}
}, (err) => {
// Flush logs
if (err) {
console.error(err);
this.logger.error(this.dialogStack(), err);
}
cb();
this.logger.flush((err) => {
this.sendingBatch = false;
if (err) {
console.error(err);
}
cb();
});
});
}

Expand Down Expand Up @@ -774,3 +859,15 @@ export class Session extends events.EventEmitter {
return this.message.sourceEvent;
}
}

// Initialize default list of watchable variables.
let watchableHandlers: { [name: string]: { name: string; handler: IWatchableHandler; }; } = {
'userdata': { name: 'userData', handler: (ctx, cb) => cb(null, ctx.userData) },
'conversationdata': { name: 'conversationData', handler: (ctx, cb) => cb(null, ctx.conversationData) },
'privateconversationdata': { name: 'privateConversationData', handler: (ctx, cb) => cb(null, ctx.privateConversationData) },
'dialogdata': { name: 'dialogData', handler: (ctx, cb) => cb(null, ctx.dialogData) },
'dialogstack': { name: 'dialogStack', handler: (ctx, cb) => cb(null, ctx.dialogStack()) },
'preferredlocale': { name: 'preferredLocale', handler: (ctx, cb) => cb(null, ctx.preferredLocale()) },
'libraryname': { name: 'libraryName', handler: (ctx, cb) => cb(null, ctx.libraryName) }
};

3 changes: 2 additions & 1 deletion Node/core/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ export const Data = {
Field: 'BotBuilder.Data.Field',
FirstRunVersion: 'BotBuilder.Data.FirstRunVersion',
PreferredLocale: 'BotBuilder.Data.PreferredLocale',
DebugAddress: 'BotBuilder.Data.DebugAddress'
DebugAddress: 'BotBuilder.Data.DebugAddress',
DebugWatches: 'BotBuilder.Data.DebugWatches'
};

export const DialogId = {
Expand Down
1 change: 1 addition & 0 deletions Node/core/src/dialogs/IntentRecognizerSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface IRecognizeContext {
userData: any;
conversationData: any;
privateConversationData: any;
dialogData: any;
localizer: ILocalizer;
logger: SessionLogger;
preferredLocale(): string;
Expand Down

0 comments on commit b77f683

Please sign in to comment.