Cómo ahorrar durante la colaboración en tiempo real

10

Quiero que varios usuarios editen el mismo documento. El problema que estoy enfrentando es cuando un nuevo usuario se une, puede ver un documento desactualizado. ¿Cómo me aseguro de que los nuevos usuarios obtengan los cambios más recientes?

Algunas soluciones en las que pensé:

  • Ahorre en cada cambio. No me gusta esta solución porque ralentizará las cosas en la interfaz de usuario y pondrá carga en db.

  • Cuando se une un nuevo usuario, active guardar en todos los demás clientes. Después de que otros clientes hayan guardado, cargue el documento. Con esto todavía puede haber inconsistencia.

Cualquier otra sugerencia sería útil.

ACTUALIZACIÓN: Después de buscar la solución sugerida, la API de Google Realtime, descubrí que:

  1. Los usuarios de su aplicación deben tener Google Drive y darle acceso a su disco . En el mejor de los casos, esto podría presentar un flujo de interfaz de usuario incómodo o evitar que los usuarios que no tienen Google Drive usen la función en tiempo real.

  2. Todas las configuraciones de uso compartido que se realizan de su lado deben replicarse para el documento de Google.

ACTUALIZACIÓN 2: Para lograr el objetivo, fui con Firebase de Google

desarrollador
fuente
¿Por qué hay una diferencia entre un usuario nuevo y usuarios activos que editan / ven el mismo documento?
Andy
@Andy Lo que estoy haciendo actualmente es transmitir a través de sockets todos los cambios que hacen los usuarios. Estos cambios actualizan la IU para los usuarios que tienen sus navegadores abiertos pero no se guardan instantáneamente en la base de datos. Así que tengo una situación, cuando un nuevo usuario se une, carga el documento de la base de datos y no ve todos los cambios recientes que aún no se guardaron.
dev.e.loper
1
si ya está enviando cambios y desea dejar el mismo comportamiento que ahora, puede pedirle a uno de los clientes que envíe la última vista al nuevo cliente o puede tener un cliente virtual en el servidor, que recibe todos los cambios y cuando el nuevo cliente se une envía lo último Verlo.
Dainius

Respuestas:

14

Google Drive

Si está intentando crear su propia versión de Google Docs, le sugiero que eche un vistazo a la API de Google Realtime . Google lanzó recientemente esto con la intención de permitir que otros desarrolladores utilicen las mismas herramientas que hicieron para permitir la colaboración en tiempo real. Esto le permitiría ahorrar tiempo en su desarrollo y obtener un producto que funcione antes.

Puede tomar fácilmente los datos que están en el documento e insertarlos en su base de datos a intervalos regulares, o hacer que la base de datos sea un "participante" del intercambio, simplemente escuchando y registrando todos los cambios. También permite que un usuario defina sus propias estructuras de datos que luego se pueden usar en la API en tiempo real, por lo que puede extenderlas como mejor le parezca.

No es Google Drive

Entonces, según su investigación, Google Drive no es una opción. Eso está bien, pero será más difícil y posiblemente no funcione tan bien, dependiendo de cuánto le pongas.

Aquí hay una estrategia general que usaría para llevar a cabo este problema:

  1. Que el servidor sea el multiplexor de comunicación. Cada persona habla con el servidor, y el servidor envía esa información a todos los demás. De esta manera, el servidor siempre tiene la vista más actualizada del documento.

  2. Encuentre un algoritmo / módulo de terceros para la resolución de conflictos. La resolución de conflictos es difícil, y es algo que aún no es perfecto. Hacer esto solo podría aumentar fácilmente el alcance del proyecto para que sea demasiado grande. Si no puede utilizar un algoritmo de terceros, le sugiero que solo permita que un usuario edite un área de una vez, de modo que el usuario debe obtener un bloqueo antes de editar un área, o corre el riesgo de destruir el trabajo de otros usuarios, lo que se pondrá muy viejo, muy rápido.

  3. Cuando se une un nuevo usuario, entréguele el documento más reciente y comience a transmitir los comandos automáticamente. El servidor tiene la vista más reciente y, por lo tanto, puede distribuirlo automáticamente.

  4. Copia de seguridad en la base de datos a ciertos intervalos. Decida con qué frecuencia desea realizar una copia de seguridad (cada 5 minutos o tal vez cada 50 cambios). Esto le permite mantener la copia de seguridad que desea.

Problemas: esta no es una solución perfecta, así que aquí hay algunos problemas que puede enfrentar.

  1. El rendimiento del servidor podría obstaculizar el rendimiento

  2. Demasiadas personas que leen o escriben podrían sobrecargar el servidor

  3. Las personas pueden perder la sincronización si se pierde un mensaje, por lo que es posible que desee asegurarse de sincronizar en puntos regulares. Esto significa enviar el mensaje completo nuevamente, lo que puede ser costoso, pero de lo contrario las personas podrían no tener el mismo documento y no saberlo.

Ampt
fuente
Sí, los cambios se transmiten a todos los clientes y tienen su versión (con suerte la misma) en el navegador. Parece que estás diciendo que, actualizar el documento en cada acción, ¿es un camino a seguir?
dev.e.loper
O al menos tenga plazos regulares de 'sincronización' donde el estado actual del documento se transmita en segundo plano para asegurarse de que todos estén en la misma página. La frecuencia dependería de la rapidez con la que las personas cambiarían el documento. De esa manera, ya tiene un método establecido para enviar a nuevas personas, así como la capacidad de asegurarse de que nunca diverja demasiado.
Ampt
1
+1. No hagas la vida difícil. Google lo hace bien sin tener que reinventar la rueda.
Neil
¿Google Realtime guarda en Google Drive? Quiero guardar en mi base de datos, no en Google Drive.
dev.e.loper
@ dev.e.loper agregó información sobre eso a la respuesta por usted.
Ampt
3

Recomiendo 1 copia persistente del documento en el servidor. Cuando un cliente se conecta al servidor, emite un UPDATEcomando (s) a ese cliente con todos los cambios.

Actualizar WorkFlow

El usuario provoca cambios desencadenantes -> El cliente envía UPDATEal servidor -> El servidor envía UPDATEa los clientes

Disparadores viables

  1. El usuario hace clic en Guardar
  2. El usuario completa una tarea específica
    • Termina de editar una celda
    • Termina de editar una oración / párrafo / línea
  3. El usuario hace clic en Deshacer
  4. El usuario presiona la tecla Retorno
  5. El usuario escribe una clave (guardar en cada cambio)

Implementación de actualización

Sugeriría poder volver a crear el documento con una serie de UPDATEcomandos para que el servidor almacene cada ACTUALIZACIÓN y cuando un nuevo cliente se conecte, el cliente puede enviar la serie de actualizaciones y él mismo puede volver a crear el documento para mostrarlo el usuario. Además, también puede tener un SAVEcomando que esté separado y que ACTUALIZAR sean cambios temporales que se pueden usar para UNDOsolicitudes y que GUARDAR realmente lo almacene para volver a abrirlo si el servidor está cerrado o todos los clientes se desconectan.

Korey Hinton
fuente
2
¿Qué pasa con la resolución de conflictos? ¿Qué sucede si dos personas editan la misma área de texto al mismo tiempo? Además, esto parece colocar una carga en la base de datos, que es algo que OP estaba buscando evitar. Sin embargo, podría ser viable para lo que necesita.
Ampt
@Ampt Hice una hoja de cálculo con este modelo, y para los conflictos, cada tarea específica que se actualizaba fue reemplazada completamente por la versión más nueva. Por lo tanto, la última persona que termine de editar una celda reemplazaría por completo la previamente actualizada sin fusión.
Korey Hinton
1
Entonces, ¿una oración sobrescribiría a otra si esto fuera, digamos, un documento de Word?
Ampt
@Ampt sí, alternativamente podría implementar una forma de bloquear lo que se está trabajando, pero tomé la ruta fácil.
Korey Hinton
3

1) Echa un vistazo a Knockout.js

Sigue un patrón MVVM y enviará automáticamente notificaciones a la Vista en función de los cambios en el Modelo. Por ejemplo, mire su matriz observable para proporcionar un poco más de información sobre cómo lo hacen.

2) Mezcle eso con SignalR y ahora debería tener la capacidad de enviar notificaciones a otros usuarios que trabajan en el documento. Desde su sitio:

SignalR también proporciona una API muy simple de alto nivel para hacer RPC de servidor a cliente (llame a las funciones de JavaScript en los navegadores de sus clientes desde el código .NET del lado del servidor) en su aplicación ASP.NET, así como también agrega enlaces útiles para la administración de la conexión , por ejemplo, eventos de conexión / desconexión, agrupación de conexiones, autorización.

Por lo tanto, deberá tener algunos ganchos en su nivel de modelo dentro de Knockout.js para hacer algunas llamadas SignalR cada vez que ocurra un cambio. Los otros clientes recibirán el aviso de SignalR y luego activarán un cambio correspondiente en su copia del Modelo, que volverá a subir a su Vista.

Es una combinación interesante de los dos marcos, y debería poder buscar y recopilar más información para manejar los detalles.

Por ejemplo, este ejemplo de proyecto de código aborda específicamente lo Co Working UIs and Continuous Clientsque parece ser exactamente lo que está tratando de hacer.

Las aplicaciones web de la nueva era pueden necesitar ofrecer experiencias de usuario de la nueva era, y deben manejar adecuadamente los escenarios de co-trabajo y clientes continuos. Esto implica asegurarse de que la interfaz de usuario se sincronice correctamente en todos los dispositivos y usuarios para garantizar que el estado de la aplicación y la interfaz de usuario se mantengan "tal como están".

Esta publicación de blog parece ser un punto de entrada a una serie de publicaciones de blog que discuten el uso de los dos paquetes y contrastan con un enfoque tradicional de ASP.NET. Puede proporcionar algunos puntos para su consideración mientras diseña su sitio.

Esta publicación de blog parece ser un poco más básica y proporciona las bases para combinar los dos paquetes.

Divulgación: no estoy afiliado a ninguno de los enlaces anteriores, ni he profundizado en su contenido para ver qué tan correcto o correcto es.


fuente
2

La solución es la transformación operativa (OT). Si no has oído hablar de él, OT es una clase de algoritmos que hacen concurrencia en tiempo real de múltiples sitios. OT es como git en tiempo real. Funciona con cualquier cantidad de retraso (de cero a un feriado extendido). Permite a los usuarios realizar ediciones simultáneas en vivo con poco ancho de banda. OT le brinda una consistencia eventual entre múltiples usuarios sin reintentos, sin errores y sin sobrescribir ningún dato.

Pero implementar OT es una tarea difícil y que requiere mucho tiempo. Por lo tanto, es posible que desee utilizar una biblioteca externa como http://sharejs.org/ .

aj_
fuente
1
Google Realtime API está haciendo OT youtu.be/hv14PTbkIs0?t=14m20s Lo hacen tanto en el cliente como en el servidor. No pude obtener una respuesta clara al leer los documentos de ShareJS, pero supongo que ShareJS hace OT tanto en el cliente como en el servidor.
dev.e.loper
1

Depende principalmente del tipo de sus documentos y de cómo colaboran sus usuarios.

Sin embargo, yo haría:

  1. permita que todos los clientes envíen cambios no guardados al servidor de vez en cuando (depende de cómo trabajen los usuarios con los documentos).
  2. el servidor almacena los deltas en la sesión del usuario (incluso para un cliente gordo necesita algo como una sesión)
  3. otros clientes que editan / ven el mismo documento obtienen esos cambios temporales o al menos una pista de que podría haberlos.

Ventajas:

  • no hay actualizaciones de base de datos a menos que alguien haga clic en "guardar"
  • copia de seguridad para el caso de que el cliente se bloquee (para el período de sesión)
  • su servidor decide cómo y qué datos reenviar a qué cliente (por ejemplo, puede iniciar la función con solo una nota y luego implementar una fusión y resaltado más sofisticados)

Desventajas

  • no 'en tiempo real', por ejemplo, envía cada 30 segundos, pero alguien escribe 3 oraciones en ese tiempo.
  • más tráfico de red: depende de sus documentos y colaboración
  • posiblemente sesiones grandes
  • posiblemente un alto esfuerzo de cómputo si muchos usuarios colaboran y hacen muchos cambios
Andy
fuente
1

Esencialmente, lo que está preguntando es cómo lidiar con el estado mutable compartido. Ahorrar es la parte fácil; pero, ¿cómo lidias con varias personas que editan la misma cosa al mismo tiempo? Desea que todos los usuarios vean el mismo documento mientras sincronizan ediciones simultáneas, todo en tiempo real.

Como probablemente haya reunido, ¡es un problema difícil! Hay algunas soluciones pragmáticas:

  1. Modifique los requisitos de su aplicación para no permitir una verdadera edición simultánea. Las ediciones se pueden combinar como con los sistemas de control de código fuente, con resultados transmitidos a cada cliente. Puede construir esto usted mismo, pero sería una experiencia de usuario más pobre.
  2. Subcontrata la sincronización de mutaciones de estado a una solución de código abierto que se integra con tu tecnología existente. ShareDB es el líder actual en este espacio. Se basa en la transformación operativa y se utiliza en al menos un sistema de producción. Esto se encargará del problema de ahorro que le preocupa, pero no ayudará con ninguna de las características adicionales de UX obligatorias para cualquier aplicación colaborativa.
  3. Use una plataforma lista para usar como Convergence (descargo de responsabilidad: soy un fundador) para manejar todas las partes difíciles para usted. También obtendrá herramientas adicionales para la colaboración en tiempo real, como el seguimiento del cursor / mouse, las selecciones y el chat para desarrollar rápidamente una experiencia de colaboración superior. Vea esta pregunta para un buen resumen de todas las herramientas existentes.
alalonde
fuente