OfficeDev/teams-toolkit

FindMember become slower when stored conversations number increase

Closed this issue · 5 comments

Hello !

Describe the bug
On the TeamsFX NodeJS SDK (latest), the findMember method has become very slow since I have more than 100 persisted conversations in my storage.
When I first put my Teams Bot into production, sending proactive notifications to a Teams user took about 7 seconds (With less conversations stored ~10), now it's 2 minutes.

To Reproduce
Steps to reproduce the behavior:

  1. Send any adaptive card to my endpoint (See code below)
  2. The request is being processed
  3. findMember list every conversations on the bucket, get them and try to get member informations from an MS API.
  4. While getting member informations, I see some errors spawning. some users may have blocked the conversation with the bot (See Screenshot below)
  5. The user receive the notification, 2min after the request started to be processed

Expected behavior
The time to send a notification is way too long.

Screenshots
Capture d’écran 2024-05-30 à 10 02 25

Additional context
The bot only send notifications to my users.
To find the right user, I use the findMember method available on BotBuilderCloudAdapter.ConversationBot class.
The condition used for matching is member.account.email === email.
1:1 conversations are stored in an S3 compatible bucket.

Here is the bot declaration :

export const notificationApp = new ConversationBot({
  adapterConfig: {
    MicrosoftAppId: config.botId,
    MicrosoftAppPassword: config.botPassword,
    MicrosoftAppType: "MultiTenant",
  },
  notification: {
    enabled: true,
    store: new S3ConversationReferenceStore(s3, config.s3BucketName),
  },
});

And the endpoint code:

type Payload = {
  email: string;
  card: AdaptiveCards.Schema;
}

server.post(
  "/api/notification",
  restify.plugins.queryParser(),
  restify.plugins.bodyParser(),
  async (req, res) => {
    const { email, card }: Payload = req.body;

    const member = await notificationApp?.notification?.findMember(async (m) => m.account.email === email)

    if (!member) {
      console.log(`Could not find member with email ${email}`);
      return res.json({
        code: 404,
      });
    }

    await member.sendAdaptiveCard(card, async (err) => {
      console.log(`error while sending adaptive card to ${email}`, err);
    });

    res.json({
      code: 200,
    });
  }
);

If the notifications are sent only to personal chat (1:1 conversation), you may set search scope to personal chat while calling findMember. It helps reduce the calls of listing all members from group or channel conversations.

The code would be like:

const member = await notificationApp?.notification?.findMember(
  async (m) => m.account.email === email, 
  BotBuilderCloudAdapter.SearchScope.Person
)

If the notifications are sent only to personal chat (1:1 conversation), you may set search scope to personal chat while calling findMember. It helps reduce the calls of listing all members from group or channel conversations.

The code would be like:

const member = await notificationApp?.notification?.findMember(
  async (m) => m.account.email === email, 
  BotBuilderCloudAdapter.SearchScope.Person
)

I've already come across this solution but it's no good. I only have 1:1 conversations with users.
How to speed up the process if I have only 1 type of conversation ?

I've already come across this solution but it's no good. I only have 1:1 conversations with users. How to speed up the process if I have only 1 type of conversation ?

For your scenario, as you already customized the conversation reference store, you may consider inserting new property like userEmail into the conversation reference item while adding it, then add a method to query conversation reference with the new property.

then the code would be like:

const conversationReference = S3ConversationReferenceStore.findConversationReferenceByUserEmail("foo@bar.com");
const target = notificationApp.notification.buildTeamsBotInstallation(conversationReferece);
await target.sendAdaptiveCard(card);

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 7 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate.

Due to lack of details for further investigation, we will archive the issue for now. In case you still have following-up questions on this issue, please always feel free to reopen the issue by clicking ‘reopen issue’ button below the comment box. We will get back to you as soon as possible.