microsoft/botframework-sdk

how we can store conversation state in our own database (sql or nosql)

Closed this issue · 18 comments

how we can store conversation state in our own database (sql or nosql)

  1. LINK= [https://docs.botframework.com/en-us/technical-faq/#where-is-conversation-state-stored]

Knowledge:
If you want to store this data within your data centres, you can provide a custom implementation of the state service. This can be done at least two ways:

the REST layer with a custom IBotState service, or
the language (Node or C#) layer, with the builder interfaces

what does it means "Bots built using Bot Builder are designed to be stateless so that they can easily be scaled to run across multiple compute nodes." ?

Solution in c#
I got exmaple "Use Redis to store conversation state"
link = [https://ankitbko.github.io/2016/10/Microsoft-Bot-Framework-Use-Redis-to-store-conversation-state/]

It is not clear and available in c# but I want to do it into node.js.

is their any example available for our custom storage in bot framework.

Yes, I believe we have some example state storage implementations - @carlosscastro where are they located in Node?

can you please point out example either by REST layer with a custom IBotState service or language (Node) layer.

Hi @Aakashvit and @willportnoy, this is actually not published for Node yet, but it will be published this week. We'll provide a separate package that will have implementations for Azure Table and Azure DocDb, but will also allow you to create your own storage client. I'll update this thread once we do.

sound good. Thanks!

any update?

@carlosscastro curious if this gets published this week.

Hi @Aakashvit and @charx0r,

We've published the Bot Framework SDK Azure Extensions to this repository.

We have 2 samples that demonstrate using DocDb and Azure Table for your bot:

To use your own custom store, you'd need to implement the IStorageClient interface and then pass it in to the AzureBotStorage constructor like the samples I linked above. Feel free to open issues in that repo if you have questions or problems :)

Hi @carlosscastro and @willportnoy I have tested bot example ("Doc Db" and "Azure Table") which is working fine, but not able to code for my custom storage . Can you please help me.
let say I want to store state and conversation in my own storage then how will be my code ..

`var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log('%s listening to %s', server.name, server.url);
});

// Create chat bot
var connector = new builder.ChatConnector({
appId: 'id',
appPassword: 'password'
});
var bot = new builder.UniversalBot(connector);
server.post('/api/messages', connector.listen());

bot.dialog('/', [
function (session, args, next) {
if (!session.userData.name) {
session.beginDialog('/profile');
} else {
next();
}
},
function (session, results) {
session.send('Hello %s!', session.userData.name);
}
]);

bot.dialog('/profile', [
function (session) {
builder.Prompts.text(session, 'Hi! What is your name?');
},
function (session, results) {
session.userData.name = results.response;
session.endDialog();
}
]);`

@Aakashvit is your question on how to enable the custom storage providers from that library?

@willportnoy yeah exactly.I want to use my own storage.But not getting how I will implement IStorageClient interface .It will better if You can provide any custom storage example along with azure table and document db example.
and let's say I want to store log information in Document DB, So can we use Document Db example concept to store log??

@Aakashvit in C#, we have an IActivityLogger interface you can implement to log all incoming and outgoing activities.

In Node, you might consider using send and receive middleware, though I don't know of any examples for that.

@Aakashvit did you get your answer from #2073 (comment) ?

@willportnoy @carlosscastro I am still facing problem with custom storage . how i will use that interface. can you provide any basic example with IStorageClient interface. I google it as well as I saw in every closed issue but i am not able to fine any clue about this interface how we will use.
this example confused more #1313 . In this example they are not using any IStorageClient.
Thanks!

@willportnoy in #2073 (comment) , we talked about activity logger, but here my requirement to store session data into custom storage.
Means let's say session.userdata.name="aakash" it should store in my custom storage.

Hi aakashvit,

Thank you for your submission. 

#1313 is using the Bot Framework internal state service to store user information (not an IStorageClient).

#2073 (comment) Provides an example of how to implement IActivityLogger.

There is also this Stack Overflow question related to yours: https://stackoverflow.com/questions/42908620/how-to-create-a-sql-server-db-implemented-in-microsoft-bot-framework And this one: http://stackoverflow.com/questions/43153824/how-to-store-session-data-into-custom-storage-in-bot-builder/43156472#43156472 explaining in more detail how IStorageClient is implemented.

Storing data in a database from within a Bot is no different from storing data in a database within any other web application.


Please Note:
The Microsoft Bot Framework team prefers that how to questions be submitted on Stack Overflow. The official Bot Framework Github repo  is the preferred platform for submitting bug fixes and feature requests. 

I have closed this issue. Please feel free to resubmit your question over on Stack Overflow and one of our support engineers will help you out as soon as possible.

I written code for custom storage (Mongo db ) code code with description

`["use strict";
var Consts = require('./Consts');
var mongodb_1 = require("mongodb");
var replaceDot_Atrate = require("./replaceDot");
var mongoDbConnection = require('./connection.js');
var conf = require('../config');
var conversational_collname = conf.db.conversationalCollection;

var IStorageClient = (function () {

function IStorageClient(options) {
    this.options = options;
}

IStorageClient.prototype.retrieve = function (partitionKey, rowKey, callback) {
    var id = partitionKey + ',' + rowKey;
    if(rowKey!=="userData"){
        var query={"$and":[{"userid":id}]}
            mongoDbConnection(function(err,db) {
            var iterator= db.collection(conversational_collname).find(query);
            iterator.toArray(function (error, result, responseHeaders) {
                if (error) {
                    console.log("Error",error)
                    callback(error, null, null);
                }
                else if (result.length == 0) {
                    callback(null, null, null);
                }
                else {
                    var document_1 = result[0];
                    var finaldoc=replaceDot_Atrate.substituteKeyDeep(document_1, /\@/g, '.');
                    finaldoc["id"]=id
                    callback(null, finaldoc, null);
                }
            });
        }); 
    }
    else{
        var query={"$and":[{"userid":partitionKey}]}
        mongoDbConnection(function(err,db) { 

            var iterator= db.collection(conversational_collname).find(query);
            iterator.toArray(function (error, result, responseHeaders) {
                if (error) {
                    callback(error, null, null);
                }
                else if (result.length == 0) {
                    //console.log("result length 0")
                    callback(null, null, null);
                }
                else {
                    var document_1 = result[0];
                    callback(null, document_1, null);
                }
            });
        });
    }
};

IStorageClient.prototype.initialize = function (callback) {
    var _this = this;
    var client=mongodb_1.MongoClient;
    this.client = client;
 
    mongoDbConnection(function(err,database) {    
            _this.database = database;
            _this.collection = database.collection(conversational_collname);
            callback(null);
     });
};

IStorageClient.prototype.insertOrReplace = function (partitionKey, rowKey, entity, isCompressed, callback) {
    var id=partitionKey + ',' + rowKey
    var docDbEntity = { id: partitionKey + ',' + rowKey, data: entity, isCompressed: isCompressed };
    if(rowKey!=="userData"){
        var newEntitiy=replaceDot_Atrate.substituteKeyDeep(entity, /\./g, '@');
        var conditions1 = {
            'userid': id
        };
        var updateobj1 = {
            "$set": {"data":newEntitiy,"isCompressed":false}
        };   
        mongoDbConnection(function(error,db) {    
            db.collection(conversational_collname).update(conditions1,updateobj1,{upsert: true},function(err,res){
            callback(error, null,"");
        });
        });
    }
    else{
        var conditions = {
            'userid': partitionKey
        };
        var update = {
            "$set": {"data":entity}
        }
        mongoDbConnection(function(error,db) {    
            db.collection(conversational_collname).update(conditions,update,{upsert: true},function(err,res){
            callback(error, null,"");
       })
    });
    } 
};


IStorageClient.getError = function (error) {
    if (!error)
        return null;
    return new Error('Error Code: ' + error.code + ' Error Body: ' + error.body);
};

return IStorageClient;

}());
exports.IStorageClient = IStorageClient;`](url)

@aakashkag Thank you so much!

Hi, Guys, I am able to store user conversation on MongoDB but it is storing last chat with the user only. Is there any method so that I can store all the conversations of the user in that database?