Skip to content

DataStore v3.x Migration Guide

Ankur Oberoi edited this page Feb 8, 2018 · 6 revisions

The v3.15.0 release of @slack/client has deprecated use of the SlackDataStore interface and its implementations (including SlackMemoryDataStore). In v4.0.0 (release milestone), these types and APIs using these types will be removed.

Why remove this useful feature?

The data store APIs have helped apps keep track of team state since this feature was released. But as the Slack platform has evolved, the model has become out of date in tricky and unexpected ways. The data store was designed to behave like the Slack web and desktop applications, managing the type of state that a logged in human user would typically need. But bots and Slack apps have a whole new (and more powerful in many ways) perspective of the world!

At a high level, here are the design issues that could not be addressed in a backwards compatible way:

  • Synchronous calling convention - In order to plug in storage destinations other than memory (SlackMemoryDataStore) the code to reach that destination would need to be asynchronous. This is important if you want to share state across many processes while horizontally scaling an app. As a result, the maintainers have never seen an implementation of the SlackDataStore interface other than the memory-based one provided.

  • Names versus IDs - While we always thought it was a good idea to use IDs anywhere possible in programmatic use, the Slack platform wasn't overly strict about it. With the introduction of Shared Channels, we cannot preserve any guarantees of uniqueness for usernames, as we mentioned in this changelog entry. In fact, channel names also lose these types of guarantees. The APIs in the SlackDataStore that operate on names instead of IDs start to break since the fundamental assumptions are not true anymore.

  • Missing Users - We want the SDK to be clear and easy to use across many use cases, including applications developed for Enterprise Grid and Shared Channels. In this context, an application is likely to receive events from users it does not recognize and for whom it cannot get more information. SlackDataStore cannot deal with these scenarios. If your application has more than one RTM client connected to different workspaces, and those workspaces are joined by a shared channel, there is no general purpose way to deduplicate the messages and arrive at a consistent deterministic state. The Slack platform has solved for this issue using the Events API (which deduplicates events on your app's behalf).

For the full discussion, see #330.

What should I change in my app to prepare for v4?

This is the right question to ask! We highly recommend updating to v4 as soon as it is available (the maintainers have been trying to keep v3.x compatible with deprecated versions of Node for over a year, but as some packages that v3.x depends on are missing patches for known security vulnerabilities, we must prepare for a major version).

You can start preparing for this transition today. When you initialize an RtmClient object, turn on the useRtmConnect option and turn off the dataStore option as below:

const { RtmClient } = require('@slack/client');

const rtm = new RtmClient('your-token-here', {
  useRtmConnect: true,
  dataStore: false,
});

Next look through your code for any places you might reference the .dataStore property of the RtmClient. In most cases, you'll be able to replace finding data in the dataStore with finding that data using a WebClient.

const { RtmClient, WebClient } = require('@slack/client');
const web = new WebClient('your-token-here');

// Before:
// const channel = rtm.dataStore.getChannelById(channelId);
// console.log(`channel info: ${JSON.stringify(channel)}`);

// After:
web.conversations.info(channelId)
  .then(resp => console.log(`channel info: ${JSON.stringify(resp.channel)}`)
  .catch(error => /* TODO: handle error */);

If you aren't sure how to translate a specific data store method into a Web API call, file a new question issue and we will help you figure it out.

You'll notice that this code has become asynchronous. This will likely be the largest challenge in migrating away from the data store, but for most developers it will be worth it.

For the majority of apps, you will be ready for v4 at this point. If your app is having performance related issues, there's room to make improvements by caching the data that is relevant to your app. This should only be taken on if you believe its necessary, since cache invalidation is one of the only two hard things in computer science.

The approach for caching data that we recommend is to pick out the data your app needs, store it at connection time, and update it according to a determined policy. You may want to disable the useRtmConnect option in order to get more data at connection time.

Can we make this easier?

We've started to build requirements for a replacement of the deprecated data store APIs. This work has not yet resulted in a timeline or commitment to build it, but we are open to your thoughts, concerns, and contributions. That discussion is taking place in this issue.