GOOGLE ADS

miércoles, 20 de abril de 2022

Django: ¿Cómo mantener el código y la base de datos sincronizados cuando se implementa en Heroku?

Digamos que tenemos un proyecto de Django llamado Alpha. Los desarrolladores trabajan en Alpha en su entorno de desarrollo antes de implementar el proyecto Django en Heroku. El Procfile puede parecerse a:

release: python manage.py migrate
web: python -m gunicorn wsgi:application

Cuando un desarrollador intenta implementar una nueva versión de Alpha, el proyecto se envía junto con sus archivos de migración (como se recomienda). Al final de la implementación, Heroku ejecutará la releasedeclaración python manage.py migratepara realizar todos los cambios relevantes en la base de datos. Debido a que el lanzamiento es parte del proceso de implementación general, si falla, el nuevo código no se implementará.

Sin embargo... Si bien el código volverá a ser lo que era antes de la implementación (como se esperaba), los posibles cambios en la base de datos de Heroku serán permanentes. Por ejemplo, supongamos que la nueva versión tiene tres nuevas migraciones:


  • 0011

  • 0012

  • 0013


Las dos primeras migraciones se ejecutan correctamente y la base de datos se modifica en consecuencia. También se agregan a la tabla de la base de datos django_migrations. El último, sin embargo, contiene un problema (por ejemplo, define una restricción que los datos del escenario no respetan).

En este escenario, el código de Heroku (tanto /migrations/como models.py) y la base de datos de Heroku ahora están muy desincronizados: de hecho, la base de datos refleja cambios cuyas migraciones ni siquiera están presentes en el repositorio de código. Esto puede generar todo tipo de problemas.

¿Cómo evitar encontrarse en este predicado y asegurar que el código y los datos estén siempre 100 % sincronizados tanto en el escenario como en la producción?

Después de escrito

Heroku tiene el siguiente fragmento como parte de su documentación:

Usar transacciones para migraciones de bases de datos

Al realizar una migración de base de datos, utilice siempre transacciones. Una transacción garantiza que todas las operaciones de migración se realicen correctamente antes de realizar cambios en la base de datos, lo que minimiza la posibilidad de una migración parcial fallida durante la fase de lanzamiento. Si la migración de una base de datos falla durante la fase de lanzamiento (es decir, el comando de migración finaliza con un estado distinto de cero), no se implementará el nuevo lanzamiento. Si no se usaron transacciones, esto podría dejar la base de datos en un estado parcialmente migrado. Sugerimos utilizar heroku run, en lugar de la fase de lanzamiento, para realizar correcciones de esquema/datos.


Solución del problema

Como dice la documentación que citó, hacer migraciones en una transacción es una buena idea. Es una buena idea que Django haga esto por defecto con bases de datos que lo soporten.

Pero esto solo ayuda para el alcance de una migración: si la migración 0013falla como en su ejemplo, los cambios que introduce se revertirán. Los cambios introducidos por las migraciones 0011ya 0012no serán revertidos.

Para revertir las migraciones 0011y 0012tendría que retroceder manualmente, por ejemplo

python manage.py migrate myapp 0010

Pero dado que su aplicación ejecutará la versión anterior si su implementación falla, no puede simplemente heroku runeso: Heroku no tiene los archivos de migración para 0011y 0012.

Esta es probablemente, al menos en parte, la razón por la que la documentación de Heroku dice

Sugerimos usar heroku run, en lugar de la fase de lanzamiento, para realizar correcciones de esquema/datos.

Si elimina su comando de fase de lanzamiento de migración, podría comenzar a implementar así:

git push heroku main
heroku run python manage.py migrate

Si la migración falla, simplemente revierta las últimas dos migraciones y luego vuelva a la versión anterior:

heroku run python manage.py migrate myapp 0010
heroku releases:rollback

Como precaución adicional, considere poner su aplicación en modo de mantenimiento antes de comenzar su actualización. Esto evitará que los usuarios interactúen con su sitio mientras se encuentre en un estado potencialmente incoherente, por ejemplo, después de la implementación pero antes de aplicar las migraciones.

No hay comentarios.:

Publicar un comentario

Flutter: error de rango al acceder a la respuesta JSON

Estoy accediendo a una respuesta JSON con la siguiente estructura. { "fullName": "FirstName LastName", "listings...