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 release
declaración python manage.py migrate
para 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 0013
falla como en su ejemplo, los cambios que introduce se revertirán. Los cambios introducidos por las migraciones 0011
ya 0012
no serán revertidos.
Para revertir las migraciones 0011
y 0012
tendrí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 run
eso: Heroku no tiene los archivos de migración para 0011
y 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