Apollo-link: [apollo-link-offline] ¿Cuál es tu idea?

Creado en 5 oct. 2017  ·  38Comentarios  ·  Fuente: apollographql/apollo-link

Hola, estaría muy feliz de participar en esta creación de funciones. Porque realmente lo necesito para el presente proyecto. Pero necesito algunos consejos para empezar. ¿Alguien tiene alguna idea?

enhancement

Comentario más útil

Hola amigos, he intentado armar una implementación básica para react-native que tiene un comportamiento similar a apollo-offline .
(haciendo ping https://github.com/Malpaux/apollo-offline/issues/14)

Puede consultarlo en esta esencia: https://gist.github.com/lachenmayer/2e364a5ca9ae0918eb032867d0c6720d

Es una combinación de:

Cuando el dispositivo se desconecta, las solicitudes se pondrán en cola y se quitarán cuando vuelva a estar en línea. ( apollo-link-queue )

Cualquier solicitud que falle con un error de red se reintentará (actualmente de forma infinita). ( apollo-link-retry )
Tenga en cuenta que esto podría deberse a que el dispositivo está fuera de línea o simplemente no se puede acceder al backend (por ejemplo, si está inactivo).

Sin embargo, si podemos resolver la consulta desde la caché, no se volverá a intentar y, en su lugar, los datos de la caché se utilizarán como respuesta. Esto se implementa en la función optimisticFetchLink .

En mi opinión, este comportamiento de "búsqueda optimista" es una de las partes más importantes de apollo-offline, y cualquier implementación futura de apollo-link-offline debería ser compatible con esto. Esto permite al usuario seguir usando la aplicación como de costumbre mientras está fuera de línea, siempre que los datos se hayan recuperado y persistido en algún momento. En mi opinión, este debería ser el comportamiento predeterminado de la política de recuperación network-and-cache , pero desafortunadamente no parece que esto vaya a cambiar pronto (consulte https://github.com/apollographql/react-apollo/issues/ 604 # issuecomment-355648596).

Si guarda la esencia como offlineLink.js , puede usarla de la siguiente manera:

import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'

// get this from https://gist.github.com/lachenmayer/2e364a5ca9ae0918eb032867d0c6720d
import { createOfflineLink } from './offlineLink'

const cache = new InMemoryCache()
const networkLink = createHttpLink()

const offlineLink = createOfflineLink({ cache })

const link = ApolloLink.from([
  // ... + other links ...
  offlineLink,
  networkLink,
])

const client = new ApolloClient({
  cache,
  link,
}

Problemas conocidos / bits faltantes

  • Esto solo funciona con react-native por ahora. El cheque isOnline debe abstraerse para hacer esta plataforma multiplataforma.
  • Si solo tiene una respuesta parcial en la caché, obtendrá una promesa rechazada en algún lugar de la línea que le indicará que la respuesta está incompleta. Todavía no he investigado cómo solucionarlo, o cómo apollo-offline resuelve esto. Si desea intentar solucionar este problema, le agradecería cualquier sugerencia al respecto.
  • Actualmente no puede cambiar ninguna de las configuraciones de reintento; esto debe agregarse como un parámetro de configuración adicional.
  • No tienes control sobre la búsqueda optimista. Debería poder configurar esto de forma independiente para cada consulta. No soy un gran admirador de la implementación de apollo-offline de esto (estableciendo una variable de consulta {__online_: true} ), pero definitivamente debería haber alguna forma de hacerlo.
  • Obviamente, tampoco hay pruebas.

Apreciaría que cualquiera que esté buscando una solución para esto lo pruebe, y luego posiblemente podamos convertir esto en un módulo npm adecuado con mecanografía, pruebas, documentos y todo. Este comportamiento es muy importante en mi opinión, y es una verdadera lástima que apollo-client 2 aún no tenga una solución adecuada para esto.

Bonito ✌️

Todos 38 comentarios

¿Cuál consideraría usted como caso de uso típico?

Como aplicación sin conexión:

  • Todas las solicitudes de graphql se agregan a la cola. (se puede almacenar en la caché).
  • Cuando la aplicación recibe la señal en línea, informa al enlace para que vuelva a enviar la solicitud anterior.

Imagino que se usa así:

import { NetInfo } from 'react-native';
import OfflineLink from 'apollo-link-offline';

const offlineLink = new OfflineLink({
  isOnlineAsync: () => NetInfo.isConnected.fetch(),
});

NetInfo.isConnected.addEventListener('change', (isConnected) => {
  if (isConnected) {
    offlineLink.resubmit();
  }
});

Creo que esta sería una función asombrosa. La forma en que veo que podría suceder, sería hacer que Apollo-link-offline defina un conjunto de consultas y mutaciones que deben usarse sin conexión.

Una vez definidos, en el fondo de la aplicación, podríamos obtener todos los datos de las consultas y almacenarlos en el almacenamiento local. Para las mutaciones, necesitaríamos todos los campos creados en el almacenamiento local para que podamos almacenar cualquier dato que se cree sin conexión.

De esta manera aún podemos realizar la funcionalidad sin conexión mientras almacenamos los datos en una caché local.
También aprobaríamos las pruebas PWA de Google si pudiéramos vincularnos a Service Workers
Luego, cuando la aplicación vuelva a estar en línea, todas las mutaciones que ocurrieron en la memoria caché local se pueden transferir a la API.

Obviamente, sería necesario que exista algún tipo de protección de simultaneidad.

Mi preocupación es que el Usuario A (fuera de línea) actualiza la Tabla X mientras que el Usuario B (en línea) ha actualizado la Tabla X mientras el Usuario A estaba fuera de línea. Necesitaríamos algún tipo de reglas de simultaneidad aquí. Supongo que podría depender de la fecha, pero no resuelve el problema si el usuario A anula los datos del usuario B sin que el usuario B lo sepa.

O simplemente podríamos fallar la mutación y dejar que el usuario se actualice manualmente cuando vuelva a estar en línea.

Apollo Client 2 es increíble, pero esta pieza de funcionalidad sería una auténtica locura

Yo también sería un gran admirador de esto. Sé que ha habido varios intentos de abordar esto con la tienda Redux de 1.0, pero convertirlo en un ciudadano pleno del ecosistema Apollo 2.0 con un enfoque coherente sería bastante maravilloso.

La mayor parte de lo que se cubrió aquí ya tiene mucho sentido para mí; básicamente, quiero conservar mis datos en el almacenamiento local y luego tirarlos de allí a Apollo después del hecho. En segundo lugar, hacer cola para las mutaciones.

Como una especie de objetivo terciario, poder absorber aún más datos en segundo plano también sería genial, y algo que estaré buscando hacer independientemente. De hecho, también me gustaría almacenar casi todos los datos del usuario localmente, solo para hacer que las operaciones de consulta comunes sean mucho más rápidas y luego rehidratarlas para obtener una precisión total, lo que permite la red. Por lo tanto, sería excelente algún tipo de solución para ese ángulo de carga ansiosa para más tarde, particularmente porque los trabajadores de servicios están comenzando a ser viables con Safari que finalmente los tiene en la versión preliminar tecnológica.

Yo también estoy emocionado por esto. @danieljvdm Tuve un poco de ventaja en la persistencia en un problema en el repositorio apollo-client .

Creo que RetryLink será útil para administrar errores de red y reintentos, aunque me gustaría ver algún tipo de caída como redux-offline .

Esto está muy bien. El problema al que hace referencia

Todavía podría ser un lugar decente para comenzar y construir sobre él. Lo que señalé en ese número es que actualmente no tengo una buena forma de monitorear el caché en busca de cambios. De hecho, traté de implementar la sugerencia inicial de @ 2WheelCoder el día de hoy, pero encontré problemas similares. El problema con la creación de un ApolloLink para "monitorear los cambios en la tienda" es que solo vive en el contexto entre una acción del cliente y luego la escritura de caché subsiguiente. Entonces puedo interceptar la solicitud antes de que se apague (middleware) e interceptarla antes de que se escriba en la memoria caché (software posterior), pero no sé cuándo se ha escrito; solo puedo adivinar (mi truco actual es un tiempo de espera de 1000 ms ).

Otro defecto fatal con el uso de un enlace para la persistencia fuera de línea es que no tiene en cuenta las suscripciones. Un enlace de suscripción solo se activará cuando se abra la suscripción, no en eventos posteriores (¿tal vez haya una forma de hacer esto que me perdí?).

Esto es básicamente donde estoy ahora, y estoy bastante atascado; creo que para llegar más lejos, es posible que tenga que abrir un PR en apollo-cache-inmemory.

@danieljvdm Estoy en el mismo lugar y creo que tiene sentido manejar la persistencia directamente en el caché después de encontrar el mismo problema que tu. HttpLink simplemente no es adecuado para él, ya que el observable se completa después de la solicitud, pero (generalmente) antes de que se actualice la caché.

Si bien puede valer la pena abrir un PR en apollo-cache-inmemory, también me pregunto si sería mejor bifurcarlo en un nuevo proyecto. La modularidad de Apollo 2 alrededor de la caché y el enlace parece sugerir que si necesita un tipo diferente de caché, simplemente puede construirlo. Tal vez un problema en apollo-client sea el siguiente paso (no creo que apollo-cache-inmemory tenga su propio repositorio).

Disculpas por salirte un poco del tema de los enlaces aquí.

@holman, ¿tendrías una referencia sobre el trabajador de servicio en la vista previa de safari tech?

@sedubois cayó (un poco de repente) hace uno o dos meses. Está en la versión preliminar de tecnología , pero aún queda mucho por hacer .

@ 2WheelCoder Me gusta la idea de un cliente PR to Apollo para un nuevo caché. ¿Quizás apollo-offline-cache que puede extender apollo-cache-inmemory ? Estaría dispuesto a ayudar a trabajar en eso. ¿Quiere abrir un problema allí?

@ 2WheelCoder @danieljvdm ¿qué pasa con el uso de LocalForage para la persistencia? Https://github.com/localForage/localForage Si ustedes abren un PR, estaría dispuesto a echar una mano

@danieljvdm Sí, abriré un problema si quieres hacer un PR. No tengo mucho tiempo durante la próxima semana y media, pero estoy feliz de participar después de eso.

@Eishpirate Definitivamente estoy de acuerdo en que LocalForage es genial. Creo que la forma en que redux-persist logró salvar la tienda fue bastante sólida y probablemente pueda actuar como un patrón decente a seguir en apollo-offline-cache .

Amigos, estoy usando el paquete redux persist para guardar los datos de la tienda en react native AsyncStorage. ¿Cómo hago esto ahora? ¿Alguna idea?

@Eishpirate : ¿funciona localforage para react native? Mirando la tabla de compatibilidad de la biblioteca, no puedo encontrar nada sobre react native. https://github.com/localForage/localForage/wiki/Supported-Browsers-Platforms

Sería muy triste si la función sin conexión de apollo no funcionara para las aplicaciones.

@timLoewel es un muy buen punto. Realmente no había pensado tan lejos como React Native. No crea que lo hace explícitamente.

Esto puede causar problemas inesperados más adelante. Sin embargo, no estoy seguro de si existe una alternativa viable sin tener que reinventar la rueda.

Artículo interesante que podría ser relevante para esta discusión https://blog.logrocket.com/building-an-offline-first-app-with-react-and-rxdb-e97a1fa64356?t=now

Parece realmente prometedor usar rxdb como base de datos sin conexión. Esto es compatible con React, React-Native, Vue, Angular, las opciones más populares.

Sin embargo, el problema que encuentro es que necesita sincronizarse con una base de datos noSQL como PouchDB (derivado de CouchDB). En mi caso de uso, estoy usando una base de datos SQL relacional (Postgres) y toda la validación de mis datos ocurre a nivel de la base de datos. Si tuviera que usar este sistema, necesitaría mantener la validación a través de jsonschema.

No sigue los principios DRY y definitivamente presentaría problemas.

Otra opción que encontré es Kinto http://docs.kinto-storage.org/en/stable/index.html que funciona con Postgres, por lo que debería evitar algunas de las capas adicionales de complejidad que introduciría rxdb. Kinto usa HTTP, por lo que, en teoría, podríamos simplemente conectarlo a Apollo-link-http https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-http

Parece que gran parte del trabajo estará relacionado con el almacenamiento en caché.

¿Qué tal redux? (Lo digo en serio)

Un paquete apollo-link-offline , basado en el trabajo apollo-offline y ...
Un paquete apollo-cache-redux . Utilice redux-offline / redux-persist tal como lo hace ahora apollo-offline.

Apollo creó inmemory-cache como la solución genérica predeterminada; puedo entender por qué no querían estar tan estrechamente vinculados con otra biblioteca. Pero la solución redux / redux-offline / redux-persis está tan probada en batalla ... sigue siendo una gran elección. El desarrollo es muy activo para los tres.

EDITAR: apollo-cache-redux existe ahora, gracias a @rportugal

@giautm He implementado casi exactamente lo que usted describe para un pequeño proyecto mío hace un tiempo, y decidí publicarlo como un paquete realmente simple: apollo-link-queue . Si alguno de ustedes tiene ideas para mejorar, me encantaría recibir sus sugerencias o contribuciones.

Por favor, ¿cuál es el estado de este problema? ¿Hay algo que podamos usar para productos fuera de línea que sea de Apollo y no esté relacionado con Redux Offline?

@smithaitufe ,
Sí, puede usar apollo-cache-persist .

@ Gregor1971
Gracias por esta referencia. Lo probaré y enviaré mis observaciones.
En un aspecto superficial, se ve genial y fácil de implementar.

¿En qué se diferencia esto de apollo-link-queue?

Hola amigos, he intentado armar una implementación básica para react-native que tiene un comportamiento similar a apollo-offline .
(haciendo ping https://github.com/Malpaux/apollo-offline/issues/14)

Puede consultarlo en esta esencia: https://gist.github.com/lachenmayer/2e364a5ca9ae0918eb032867d0c6720d

Es una combinación de:

Cuando el dispositivo se desconecta, las solicitudes se pondrán en cola y se quitarán cuando vuelva a estar en línea. ( apollo-link-queue )

Cualquier solicitud que falle con un error de red se reintentará (actualmente de forma infinita). ( apollo-link-retry )
Tenga en cuenta que esto podría deberse a que el dispositivo está fuera de línea o simplemente no se puede acceder al backend (por ejemplo, si está inactivo).

Sin embargo, si podemos resolver la consulta desde la caché, no se volverá a intentar y, en su lugar, los datos de la caché se utilizarán como respuesta. Esto se implementa en la función optimisticFetchLink .

En mi opinión, este comportamiento de "búsqueda optimista" es una de las partes más importantes de apollo-offline, y cualquier implementación futura de apollo-link-offline debería ser compatible con esto. Esto permite al usuario seguir usando la aplicación como de costumbre mientras está fuera de línea, siempre que los datos se hayan recuperado y persistido en algún momento. En mi opinión, este debería ser el comportamiento predeterminado de la política de recuperación network-and-cache , pero desafortunadamente no parece que esto vaya a cambiar pronto (consulte https://github.com/apollographql/react-apollo/issues/ 604 # issuecomment-355648596).

Si guarda la esencia como offlineLink.js , puede usarla de la siguiente manera:

import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'

// get this from https://gist.github.com/lachenmayer/2e364a5ca9ae0918eb032867d0c6720d
import { createOfflineLink } from './offlineLink'

const cache = new InMemoryCache()
const networkLink = createHttpLink()

const offlineLink = createOfflineLink({ cache })

const link = ApolloLink.from([
  // ... + other links ...
  offlineLink,
  networkLink,
])

const client = new ApolloClient({
  cache,
  link,
}

Problemas conocidos / bits faltantes

  • Esto solo funciona con react-native por ahora. El cheque isOnline debe abstraerse para hacer esta plataforma multiplataforma.
  • Si solo tiene una respuesta parcial en la caché, obtendrá una promesa rechazada en algún lugar de la línea que le indicará que la respuesta está incompleta. Todavía no he investigado cómo solucionarlo, o cómo apollo-offline resuelve esto. Si desea intentar solucionar este problema, le agradecería cualquier sugerencia al respecto.
  • Actualmente no puede cambiar ninguna de las configuraciones de reintento; esto debe agregarse como un parámetro de configuración adicional.
  • No tienes control sobre la búsqueda optimista. Debería poder configurar esto de forma independiente para cada consulta. No soy un gran admirador de la implementación de apollo-offline de esto (estableciendo una variable de consulta {__online_: true} ), pero definitivamente debería haber alguna forma de hacerlo.
  • Obviamente, tampoco hay pruebas.

Apreciaría que cualquiera que esté buscando una solución para esto lo pruebe, y luego posiblemente podamos convertir esto en un módulo npm adecuado con mecanografía, pruebas, documentos y todo. Este comportamiento es muy importante en mi opinión, y es una verdadera lástima que apollo-client 2 aún no tenga una solución adecuada para esto.

Bonito ✌️

@smithaitufe ,

¿En qué se diferencia esto de apollo-link-queue?

Parece que apollo-link-queue hace cosas inteligentes según el estado de la conexión. apollo-cache-persist guarda la caché; permitiendo, por ejemplo, que los usuarios inicien y ejecuten su aplicación mientras están desconectados. Sin conservar la caché, su aplicación necesitaría conectividad para iniciarse,

Es probable que queramos ambos, o mejor aún, la solución de @lachenmayer anterior (que usa apollo-link-queue) y una caché que sea persistente. (estamos chateando en los repositorios de enlaces, por lo que la mayor parte del enfoque aquí está en eso)

@lachenmayer A primera vista, su enfoque parece muy atractivo.

Estoy absolutamente de acuerdo con usted en la necesidad de algo como la función de búsqueda optimista de apollo-offline . Eso (o más bien la falta de él) fue en gran parte lo que me inspiró a comenzar apollo-offline .

Yo mismo no estoy del todo satisfecho con cómo tuve que implementar la habilitación / deshabilitación selectiva de la función de búsqueda optimista en apollo-offline . Las variables de consulta no eran la primera opción, pero parecían la más práctica. ¿Qué propondrías?

Las próximas dos semanas van a ser bastante estresantes para mí. Sin embargo, después de eso, estaré más que feliz de contribuir a la implementación de una primera solución fuera de línea actualizada para Apollo; puede que sea una nueva versión del paquete apollo-offline o algo así como apollo-link-offline .

¡Gracias @MLPXBrachmann!
Siento que la búsqueda optimista debe controlarse usando fetchPolicy ; si no quiero que nada provenga de la caché, debería poder usar network-only .

@lachenmayer @MLPXBrachmann

Estoy más que listo y dispuesto a contribuir.

Yo también estoy buscando opciones para implementar el comportamiento fuera de línea en una aplicación Apollo. El enfoque de @lachenmayer parece muy prometedor, pero como se basa en apollo-link-retry, las mutaciones que no se hayan aplicado con éxito no se conservarán, por lo que si se actualiza la página, cualquier dato que no se haya enviado al servidor se mantendrá. descartado (supongo que es lo mismo en react-native si la aplicación está suspendida). ¿Hay algún trabajo o al menos discusión sobre ese aspecto?

@nicocrm Ya veo ... En este momento, la discusión sobre el soporte fuera de línea se centra principalmente en este tema. Creo que los propios apolo tienen otras prioridades en este momento, por lo que deberíamos crear un proyecto comunitario apollo-link-offline . Con suerte, esto conducirá a más discusión y progreso que en este momento 😄

@benseitz , definitivamente estoy a favor de eso. Hay mucho interés en la función, así que estoy seguro de que hay espacio para un proyecto comunitario; siempre que no esté duplicando o fragmentando el esfuerzo existente, puedo crear un nuevo equipo y repositorio para apollo-link-offline e invitar a todos los interesados. . Tengo un interés personal, así como un cliente que realmente está presionando por esa función, así que tendré algunas horas para dedicarme a ella. Preguntaré en el repositorio apollo-offline para ver si quieren tomar la iniciativa, ya que tienen mucha más experiencia.

Definitivamente también tengo un interés personal en esto; estaría encantado de seguir charlando con usted en este @nicocrm. No he notado ninguna solicitud perdida hasta ahora en react-native, pero tbh realmente no he probado todas estas cosas correctamente (solo con consultas hasta ahora y parece que todo funciona bien).

Siento que tendría sentido iniciar un repositorio para esto. @MLPXBrachmann, quien construyó apollo-offline mencionó anteriormente que no tendrá tiempo para gastar en mejorar apollo-offline en las próximas dos semanas, y creo que tiene más sentido llamarlo apollo-link-offline .

No creo que haya ningún código que sea reutilizable desde apollo-offline ya que es muy específico de redux.

@nicocrm Estoy muy de acuerdo contigo. Las consultas / mutaciones en cola persistentes definitivamente deberían ser algo de lo que apollo-link-offline se encargue.

@benseitz Yo también creo que sería una gran idea comenzar apollo-link-offline como un esfuerzo comunitario y me gustaría mucho participar en su desarrollo.

@lachenmayer Tienes toda la razón, la cantidad de código compartido por apollo-offline y el paquete planificado apollo-link-offline probablemente será casi nula. Sin embargo, creo que muchos de los conceptos subyacentes del primero todavía se aplican al desarrollar un conjunto de herramientas fuera de línea en el universo Apollo 2.0.

En cualquier caso, me complacería discutir ideas para apollo-link-offline , dar comentarios sobre la implementación y, tan pronto como mi agenda se libere un poco, también contribuir con algo de código.

@MLPXBrachmann @lachenmayer @nicocrm ¡ Parece la forma correcta de hacerlo!
Dado que cualquiera puede abrir un canal público en Apollo Slack . Sugeriría abrir uno llamado apollo-link-offline . Quizás esto facilite un poco la comunicación entre nosotros. Todas las decisiones importantes aún deben estar documentadas en Problemas de GitHub.

¿Está de acuerdo con que abra tanto el canal de reposo como el de slack o alguno de ustedes quiere hacer eso?

¡Seguro, gracias!

Los agregué a tres como colaboradores al Repo . Y puedes unirte al canal #apollo-link-offline en Apollo Slack

Por supuesto, todos están invitados a colaborar en GitHub Repo y discutir en Slack :)
Estoy muy emocionado 💯

Para aquellos de ustedes que llegan aquí desde una Búsqueda de Google, he escrito un resumen de todas las tecnologías sin conexión existentes disponibles hoy para Apollo Client 2.0.

https://github.com/benseitz/apollo-link-offline/issues/1#issuecomment -371678922

¿Apollo está trabajando en un equivalente de AWS AppSync? Ya tenemos un servidor GraphQL y necesitamos almacenamiento en caché de clientes fuera de línea para consultas y mutaciones utilizando nuestro servidor, no soluciones de AWS (es decir, Lamda, DynamoDB, Elastic Search).

espero que funcione.

@masull Eso sería absolutamente asombroso. Lo intenté y no pensé que la base de fuego o la plataforma de análisis funcionaran para mí, por lo que tener esta función sería glorioso.
Tener dificultades para configurar todo con muchos paquetes ... no es nada divertido :)

¿Fue útil esta página
0 / 5 - 0 calificaciones