Как эффективно синхронизировать кеш Apollo, используя подписки и AWS AppSync

77
8

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

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

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

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

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

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

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

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

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

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

спросил(а) 2018-11-07T09:27:00+03:00 1 год, 8 месяцев назад
1
Решение
55

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

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

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

<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
})

ответил(а) 2018-11-07T16:14:00+03:00 1 год, 8 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема