¿Cómo eliminar correctamente un módulo en un entorno por etapas?

17

Algunos módulos tienen rutinas de desinstalación. Que normalmente eliminan las tablas de base de datos para ese módulo, las variables de la tabla de variables y las configuraciones regionales introducidas por ese módulo. Estas rutinas viven en el .installde ese módulo.

Por lo tanto, no se pueden ejecutar sin ese módulo presente. Así que aquí están nuestros pasos actuales. Mi pregunta es: ¿se puede hacer esto de manera más simple y efectiva? Digamos que elimino el módulo foo_bar.

  1. En el RCS, prepare una nueva versión, donde:
    • Se eliminan todas las sustituciones de css y de temas que usan o se crean sobre foo_bar.
    • Se eliminan todas las sustituciones de css y temas para los módulos que dependen de foo_bar.
  2. Empuje ese lanzamiento a la aceptación. Pruebe la desinstalación (desde admin / modules) con una copia muy reciente de la base de datos de producción.
  3. Si todo va bien, implemente la nueva base de código en producción y desinstale foo_bar y sus dependencias allí. Esto invocará la desinstalación en los distintos módulos, limpiando la base de datos.
  4. En el RCS (git), prepare una nueva versión donde el código se elimine realmente.
  5. Implemente eso en la aceptación donde probamos si nada dependía accidentalmente de esto (algunos módulos feos o funciones temáticas incluyen archivos directamente de otros módulos. En particular CSS, JS o archivos de imagen).
  6. Si se acepta, implemente una nueva versión en producción. La producción ahora tiene una base de datos limpia y una base de código limpia .

El problema que no puedo ver cómo resolver es que esto siempre necesita dos versiones. Dado que en Drupal una versión requiere que el sitio esté fuera de línea, esto significa dos veces el tiempo de inactividad solo para eliminar un módulo. También requiere dos procedimientos de lanzamiento, que, en entornos de alojamiento profesional, pueden ser muy costosos, lentos o frustrantes.

Si eliminamos el módulo de la base de código en la primera iteración, no podemos ejecutar los ganchos de desinstalación, manteniendo muchas pelusas en la base de datos; no solo unas pocas tablas, sino principalmente variables y configuraciones regionales. Si no eliminamos el módulo de la base de código, eso significa que la base de código crecerá con código obsoleto y no utilizado; esto no genera una sobrecarga de rendimiento, pero hace que el mantenimiento del código sea cada vez más difícil.

Como tratas con esto?

[editar: nota agregada sobre la implementación como un procedimiento difícil, a menudo]

Berkes
fuente
2
Si primero realiza los pasos del 1 al 6 en un servidor provisional, ¿no podría actualizar el sitio en vivo a HEAD ^, realizar las desinstalaciones y luego actualizar a HEAD (todo de una vez)?
Andy
Si todos mis proyectos se implementaron con git, entonces sí. Pero algunos necesitan que se envíen tarballs por correo, mientras que otros usan (¡solo!) Ftp, etc. Pero mirar git y algunos scripts de git-hook es ciertamente una idea muy interesante.
Berkes
¿Por qué exactamente se requiere eliminar el sitio?
Letharion
@Letharion: 1) Eliminar el sitio prohíbe las escrituras no deseadas en su base de datos durante el proceso de alterar esa base de datos; Drupal no utiliza transacciones. 2) La implementación de un nuevo código que depende de cierto estado de la base de datos (un tema que requiere un cierto campo cck, por ejemplo) romperá su sitio en el tiempo entre la implementación del código y la actualización de la base de datos.
Berkes

Respuestas:

7

Tenga mucho cuidado al mantener su base de datos y código sincronizados; Como usted menciona en su pregunta, los módulos que se desinstalarán deben permanecer en la base del código hasta que sus enlaces de desinstalación se ejecuten en la base de datos en vivo. Esta es una limitación de Drupal que un flujo de trabajo de git pull solo no va a resolver.

Recomendaría que en lugar de intentar ajustar su proceso, busque formas de reducir el tiempo de inactividad requerido para procesar sus actualizaciones. Recomendaría configurar un entorno de preparación multisitio ying / yang para resolver este problema. nb No he usado los scripts contenidos en el enlace anterior; es posible que desee configurar las cosas de manera diferente, siguiendo la misma idea de que puede intercambiar sus sitios en vivo y en escena durante la implementación.

Continúe siguiendo el mismo procedimiento que describió en su pregunta con los siguientes ajustes:

a. Sincronice de dev a stage (yang) como siempre. Pruebe haciendo una desinstalación de los módulos que se eliminarán, seguido de la eliminación del código, etc. Notas sobre el flujo de trabajo de Git: cree una etiqueta o anote el hash de los diferentes estados de su código: todos los módulos en su lugar antes de la desinstalación, los módulos de código eliminados, su anulaciones y c. eliminado, etc. según sea necesario. Quizás solo se necesitan dos referencias.

si. Cuando la prueba esté completa y aceptada, restaure el código en el escenario (yang) al estado de vida (ying).

C. Prepare el sitio en vivo (ying) para la actualización deshabilitando la capacidad de cualquier usuario para cambiar el contenido del sistema. Una actualización de SQL a la tabla de permisos generalmente lo hará aquí. En este punto, los usuarios aún podrán leer contenido en el sitio en vivo, pero recibirán un error de permiso denegado si intentan actualizar el contenido. (Si es genial, quizás podría cambiar el controlador de permiso denegado para imprimir un aviso apropiado de que la función no está disponible temporalmente).

re. Ahora empuje la base de datos en vivo (ying) de regreso a la base de datos en etapa (yang), excluyendo la tabla de permisos de la actualización.

mi. Repita el paso a. de nuevo. Si tiene sus hashtags a mano, debería ser fácil restaurar el estado en el que están los módulos que se eliminarán, ejecutar los ganchos de desinstalación en la base de datos y luego volver al estado del código donde se fusionaron sus elementos del paso 1 de nuevo en.

F. Ahora estás listo para intercambiar ying y yang. Haga esto ajustando sus directivas de configuración de Apache. Tenga en cuenta que si hace una /etc/init.d/apache restart, algunas conexiones pueden cortarse, pero /etc/init.d/apache reloadpermitirán un intercambio limpio.

sol. Live es ahora 'yang'; la tabla de permisos no se modifica aquí, por lo que los usuarios pueden crear contenido. Si automatiza los pasos e. y f., el tiempo no disponible debe ser muy bajo.

h. Empuje en vivo (yang) de vuelta al escenario (ying), tanto el código como la base de datos, o empuje desde dev, según sea necesario. Ahora tiene un entorno limpio listo para su próxima iteración.

greg_1_anderson
fuente
Ying-yang falla horriblemente en el paso c. Solo funcionarán sitios muy específicos, como editorial-driven-anon-access-only. Esto se debe principalmente a que no solo los comentarios, los nodos y demás deben deshabilitarse, sino que la tabla de sesión, el perro guardián, los contadores, etc. se actualizarán y se escribirán en ellos. El tiempo de inactividad parece un efecto secundario desafortunado pero inevitable. Aunque, de hecho, para ciertos sitios, ying-yang es un concepto muy interesante para usar cuando se implementa.
Berkes
Por supuesto, estás en lo correcto; sin embargo, si escribe el paso final, la ventana de tiempo de inactividad o información perdida será baja. Si pierde una entrada de la tabla de sesión, el usuario deberá iniciar sesión nuevamente. Un contador puede estar apagado un poco. Puede perder una o dos notificaciones en el perro guardián. Si esto es peor que un corto período de "este sitio está fuera de servicio por mantenimiento", entonces utilice la solución más simple. Si realmente quisiera, podría intentar recuperar los mensajes de contador y vigilancia después del intercambio. Esto podría ser más complicado de lo que valía, a menos que información + tiempo de actividad MUY valioso.
greg_1_anderson
Puede considerar realizar un seguimiento de las transacciones en el sitio de transición utilizando el registro binario mysql. Ver dev.mysql.com/doc/refman/5.0/en/point-in-time-recovery.html . Sería reacio a fusionar las cosas, pero podría realizar un seguimiento de los mensajes adicionales de contador / vigilancia fuera de banda. La forma más fácil de lidiar con la tabla de sesión sería deshabilitar también los inicios de sesión durante la transición.
greg_1_anderson
Su comentario me llevó a una posible otra solución: agregar todos los hook_uninstall para un módulo como hook_update_n () s de un módulo especial para propósito: uninstall.module. De esa forma, puedo eliminar la base de código en la primera iteración / y / obtener una instalación más rápida en la versión real. Podría ser un script drush que raspe esta información.
Berkes
1
Una cosa más que ayudará un poco. Cambie todo su código php personalizado de modo que se incluya cualquier referencia al módulo a eliminar if (module_exists('removeme')) { ... }. Implemente ese código. Si prueba y confirma que quitar el módulo ya no rompe su código personalizado, eso simplificará su implementación. Todavía es recomendable realizar el paso de desactivación en un sitio que no está activo, pero tal vez esto reducirá ligeramente su ventana. No creo que su enlace de actualización personalizado haga que sea más seguro desactivar un módulo en vivo.
greg_1_anderson