Как эффективно синхронизировать кеш Apollo, используя подписки и AWS AppSync - PullRequest
0 голосов
/ 07 ноября 2018

Я использую aws-appsync в клиенте Node.js для хранения кэшированного списка элементов данных. Этот кэш должен быть доступен постоянно, в том числе, когда он не подключен к Интернету.

Когда мое приложение Node запускается, оно вызывает запрос, который возвращает весь список элементов из источника данных AppSync. Это кэшируется кеш-хранилищем Apollo, которое позволяет выполнять будущие запросы (используя тот же запрос GraphQL), используя только кеш.

Приложение также делает подписку на мутации, которые могут изменять список на других клиентах. При изменении элемента в списке новые данные отправляются в приложение. Это может инициировать повторный выбор исходного запроса для всего списка, тем самым поддерживая актуальность кэша.

Получение всего списка, когда изменился только один элемент, неэффективно. Как я могу поддерживать кеш в актуальном состоянии, минимизируя при этом количество данных, которое нужно извлекать при каждом изменении?

Решение должно предоставлять единую точку для доступа к кэшированным данным. Это может быть либо запрос GraphQL, либо прямой доступ к хранилищу кеша. Однако использование результатов нескольких запросов недопустимо.


Документация Apollo указывает на то, что это должно быть возможно:

В некоторых случаях простого использования [автоматических обновлений магазина] недостаточно для правильного обновления приложения. Например, если вы хотите добавить что-то в список объектов без повторной загрузки всего списка ... Клиент Apollo не может обновить существующие запросы для вас.

Альтернативы, которые он предлагает, - это повторное получение (по сути, то, что я описал выше) и использование обратного вызова update для ручного обновления результатов кэшированного запроса в хранилище.

Использование update дает вам полный контроль над кэшем, позволяя вносить изменения в модель данных в ответ на мутацию любым удобным вам способом. update - рекомендуемый способ обновления кэша после запроса.

Однако здесь речь идет о мутациях, сделанных одним и тем же клиентом, а не о синхронизации между клиентами с использованием подписок. Опция обратного вызова update не доступна для подписки (которая предоставляет обновленные данные элемента) или запроса (который может получить обновленные данные элемента).

1 Ответ

0 голосов
/ 07 ноября 2018

Поскольку ваша подписка включает в себя полный добавленный ресурс, это должно быть возможно путем непосредственного чтения и записи в кэш. Давайте предположим, что у нас есть такая подписка из документов:

const COMMENTS_SUBSCRIPTION = gql`
  subscription onCommentAdded {
    commentAdded {
      id
      content
    }
  }
`;

Компонент Subscription включает onSubscriptionData prop, поэтому мы должны быть в состоянии сделать что-то вроде этого:

<Subscription
  subscription={COMMENTS_SUBSCRIPTION}
  onSubscriptionData={({ client, subscriptionData: { data, error } }) => {
    if (!data) return
    const current = client.readQuery({ query: COMMENTS_QUERY })
    client.writeQuery({
      query: COMMENTS_QUERY,
      data: {
        comments: [...current.comments, data.commentAdded],
      },
    })
  }}
/>

Или, если вы используете простой JavaScript вместо React:

const observable = client.subscribe({ query: COMMENTS_SUBSCRIPTION })
observable.subscribe({
  next: (data) => {
    if (!data) return
    const current = client.readQuery({ query: COMMENTS_QUERY })
    client.writeQuery({
      query: COMMENTS_QUERY,
      data: {
        comments: [...current.comments, data.commentAdded],
      },
    })
  },
  complete: console.log,
  error: console.error
})        
...