Write migration
Writing a migration¶
To have more information about migrations in laputa, check the topic page
Disclaimer¶
Warning
Migrations can be dangerous, an error will lead to Laputa not booting up (and being stuck in a restart loop in prod). They can also fail silently if the data modified is not correct and can lead to further issues on runtime. Test your migrations carefully (both local and on a guru) and follow the checklist before merging a new Laputa migration.
How to create a new migration¶
Migrations are python files located in the laputa/app/migrations directory.
They have to respect a specific format:
Filename¶
The filename is composed of (each part is split with a _):
- migration prefix
- current date when creating the file with format yyyy_MM_dd_HH_mm_ss
- the name of migration
For example migration_2022_06_16_10_00_00_migration_name.py
API¶
The code inside the file must implement the following API:
def apply_forward(params: dict) -> None:
...
def apply_backward(params: dict) -> None:
...
The params dict given as a parameter only contains two keys: config and database_manager
Sometimes the apply_backward() method is not applicable, you must still define it but leave it empty
How to update the current configs¶
To migrate Front and ETL configs, you can use existing utils to make it easier.
apply_front_config_migration(params, transform, migration_name)
apply_etl_config_migration(params, transform, migration_name)
These functions take the params, a callback to a function to migrate the config, and the name of the migration They will call the callback function with the current config and handle the save for you with its returned value.
Example:
from laputa.app.migrations.front_config_migrations import apply_front_config_migration
def transform_forward(front_config) -> dict:
# add logic to update your front_config here
return front_config
def apply_forward(params):
apply_front_config_migration(params, transform_forward, 'Migrate my Front Config')
Migrating something else¶
You might want to migrate some other data, you can do it as you would do in Laputa
Warning
Avoid using ORMs and production models here as they validate the data and might lead to exceptions
You can use the database_manager given in the params argument, a lot of utils are already existing inside the database_manager to do these queries
Otherwise, you can retrieve the collection to query the database using PyMongo using database_manager.get_small_app_database and database_manager.get_default_database
Example
def apply_forward(params):
database_manager = params['database_manager']
# data = database_manager.get_small_app_database('demo')['styles'] <- same as below
data = database_manager.get_small_app_styles_variables('demo')
# logic to update the data
database_manager.save_small_app_styles_variables('demo', data)
Complex migrations¶
You can always use Pydantic models to validate your data and their types and simplify the migration process
You can find an example at laputa/app/migrations/migration_2021_11_16_14_00_00_highlighted_kpi.py
Do not forget¶
- Try to test every possible case scenario in your unit testing
- It might be a good idea to globally catch exceptions if the changes of the migrations are not breaking
- Make sure the Pull Requests are reviewed carefully and do not hesitate to ask for it