Botbuilder-js: TableStorage might be broken

Created on 13 Jun 2018  路  8Comments  路  Source: microsoft/botbuilder-js

Hey,

It seems like TableStorage might be broken. While MemoryStorage and FileStorage are working fine, when switching to TableStorage the following errors are thrown on the CLI after the first message is being sent to the bot:

Console Error:

$ node -v
v8.9.4

$ node app.js
restify listening to http://[::]:3978
BotFrameworkAdapter.processActivity(): 500 ERROR - StorageError: An error occurred while processing this request.
RequestId:42eb8cb1-9002-0014-16e9-02d663000000
Time:2018-06-13T07:39:06.5854152Z
(node:76997) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): StorageError: An error occurred while processing this request.
RequestId:42eb8cb1-9002-0014-16e9-02d663000000
Time:2018-06-13T07:39:06.5854152Z

botbuilder versions:

  "dependencies": {
    "botbuilder": "^4.0.0-preview1.2",
    "botbuilder-azure": "^4.0.0-preview1.2",
    "botbuilder-dialogs": "^4.0.0-preview1.2",
    "dotenv": "^6.0.0",
    "restify": "^7.1.1"
  }

The issue can be reproduced via this code:

const { FileStorage, BotStateSet, BotFrameworkAdapter, ConversationState, UserState, MessageFactory } = require('botbuilder');
const { TableStorage } = require('botbuilder-azure');
const { DialogSet } = require('botbuilder-dialogs');
const restify = require('restify');

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

const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

//Add state middleware
const storage = new TableStorage({ tableName: 'test123', storageAccountOrConnectionString: 'DefaultEndpointsProtocol=https;AccountName=xxxx;AccountKey=xxxx;EndpointSuffix=core.windows.net' });
// Bot works fine with FileStorage
//const storage = new FileStorage("/Users/csiebler/xyz/storage/");
const conversationState = new ConversationState(storage);
const userState = new UserState(storage);
adapter.use(new BotStateSet(conversationState, userState));

// Listen for incoming requests 
server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        if (context.activity.type === 'message') {
            const state = conversationState.get(context);
            const dc = dialogs.createContext(context, state);

            // Continue the current dialog if one is currently active
            await dc.continue();

            // If we do not have a dialog active, start the root dialog
            if (!context.responded) {
                await dc.begin('RootDialog');
            }
        }
    });
});

const dialogs = new DialogSet();

dialogs.add('RootDialog', [
    async function (dc) {
        const options = ["Option 1", "Option 2"];
        const actions = MessageFactory.suggestedActions(options, "Hello, I'm here to help you with these 2 things! How can I help you?");
        await dc.context.sendActivity(actions);
    },
    async function (dc, result) {
        switch (result) {
            case "Option 1":
                await dc.begin('Option1');
                break;
            case "Option 2":
                await dc.begin('Option2');
                break;
            default:
                await dc.context.sendActivity("Sorry, I don't understand that command. Please choose an option from the list below.");
                break;
        }
        await dc.endAll().begin('RootDialog');
    }
]);

dialogs.add('Option1', [
    async function (dc, args) {
        await dc.context.sendActivity(`This will become the Option1Dialog`);
        await dc.end();
    }
]);

dialogs.add('Option2', [
    async function (dc, args) {
        await dc.context.sendActivity(`This will become the Option2Dialog`);
        await dc.end();
    }
]);

I might be doing something wrong here, but according to the documentation, the code should be working.

Thanks,
Clemens

bug

All 8 comments

I'll look into this shortly.

Up @Stevenic :) What's the alternative? The tutorials have to be updated accordingly :/

@Stevenic @stevengum I understand this was a part of the PR to remove some explicit middleware, but I'm not sure why table storage was completely removed as a state storage option with no alternative, while the other storage options remain. Can we get this put back in, or are you phasing out Azure Table Storage support?

@csiebler we decided from a design perspective to move to supporting blob storage, as we believe supporting blob storage gives you the same functionality as table storage

@sgellock Any reason not to support both? Is it a resource constraint in terms of code maintenance?

If it鈥檚 definitely gone, can we spin it out as a separate community OSS modules?

@sgellock Thanks for the update!

@szul, yes. the decision to reduce our surface area was a big contributor for the change. We'd totally be supportive of the community spinning it out and making it a separate module.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

christopheranderson picture christopheranderson  路  6Comments

Batta32 picture Batta32  路  3Comments

tomlm picture tomlm  路  3Comments

saranyuavh picture saranyuavh  路  5Comments

juharris picture juharris  路  3Comments