Skip to content

Commit

Permalink
fix: Avoid a long table lock for the first_name migration
Browse files Browse the repository at this point in the history
  • Loading branch information
khvn26 committed Nov 6, 2024
1 parent fd5c532 commit 78b666a
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 19 deletions.
53 changes: 53 additions & 0 deletions api/tests/unit/users/test_migrations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import pytest
from django.conf import settings
from django_test_migrations.migrator import Migrator

pytestmark = pytest.mark.skipif(
settings.SKIP_MIGRATION_TESTS is True,
reason="Skip migration tests to speed up tests where necessary",
)


def test_0039_ffadminuser_first_name_v2__values_expected(migrator: Migrator) -> None:
# Given
old_state = migrator.apply_initial_migration(
("users", "0038_create_hubspot_tracker")
)
OldFFAdminUser = old_state.apps.get_model("users", "FFAdminUser")

user = OldFFAdminUser.objects.create(first_name="Testfirstname")

# When
new_state = migrator.apply_tested_migration(
("users", "0039_ffadminuser_first_name_v2")
)
NewFFAdminUser = new_state.apps.get_model("users", "FFAdminUser")

# Then
assert NewFFAdminUser.objects.get(id=user.id).first_name == user.first_name


def test_0039_ffadminuser_first_name_v2__reverse__values_expected(
migrator: Migrator,
) -> None:
# Given
old_state = migrator.apply_initial_migration(
("users", "0039_ffadminuser_first_name_v2")
)
NewFFAdminUser = old_state.apps.get_model("users", "FFAdminUser")

user = NewFFAdminUser.objects.create(
first_name="TestfirstnameTestfirstnameTestfirstnameTestfirstname"
)

# When
new_state = migrator.apply_tested_migration(
("users", "0038_create_hubspot_tracker")
)
OldFFAdminUser = new_state.apps.get_model("users", "FFAdminUser")

# Then
assert (
OldFFAdminUser.objects.get(id=user.id).first_name
== "TestfirstnameTestfirstnameTest"
)
18 changes: 0 additions & 18 deletions api/users/migrations/0039_alter_ffadminuser_first_name.py

This file was deleted.

55 changes: 55 additions & 0 deletions api/users/migrations/0039_ffadminuser_first_name_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Generated by Django 4.2.16 on 2024-11-05 10:49

from pathlib import Path
from django.db import migrations, models


def _get_ffadminuser_table_name() -> str:
from users.models import FFAdminUser

return FFAdminUser._meta.db_table


_ffadminuser_table_name = _get_ffadminuser_table_name()


parent_dir = Path(__file__).parent.resolve()

with open(parent_dir / "sql/0039_ffadminuser_first_name_v2.sql") as f:
sql_forwards = f.read().format(ffadminuser_table_name=_ffadminuser_table_name)

with open(parent_dir / "sql/0039_ffadminuser_first_name_v2_reverse.sql") as f:
sql_reverse = f.read().format(ffadminuser_table_name=_ffadminuser_table_name)


class Migration(migrations.Migration):

dependencies = [
("users", "0038_create_hubspot_tracker"),
]

operations = [
migrations.SeparateDatabaseAndState(
state_operations=[
migrations.RemoveField(
model_name="ffadminuser",
name="first_name",
),
migrations.AddField(
model_name="ffadminuser",
name="first_name",
field=models.CharField(
db_column="first_name_v2",
max_length=150,
verbose_name="first name",
),
),
],
database_operations=[
migrations.RunSQL(
sql=sql_forwards,
reverse_sql=sql_reverse,
)
],
)
]
8 changes: 8 additions & 0 deletions api/users/migrations/sql/0039_ffadminuser_first_name_v2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ALTER TABLE {ffadminuser_table_name}
ADD COLUMN first_name_v2 varchar(150) NULL;
UPDATE {ffadminuser_table_name}
SET first_name_v2 = {ffadminuser_table_name}.first_name;
ALTER TABLE {ffadminuser_table_name}
ALTER COLUMN first_name_v2 SET NOT NULL;
ALTER TABLE {ffadminuser_table_name}
DROP COLUMN first_name;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ALTER TABLE {ffadminuser_table_name}
ADD COLUMN first_name varchar(30) NULL;
UPDATE {ffadminuser_table_name}
SET first_name = left({ffadminuser_table_name}.first_name_v2, 30);
ALTER TABLE {ffadminuser_table_name}
ALTER COLUMN first_name SET NOT NULL;
ALTER TABLE {ffadminuser_table_name}
DROP COLUMN first_name_v2;
6 changes: 5 additions & 1 deletion api/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ class FFAdminUser(LifecycleModel, AbstractUser):
email = models.EmailField(unique=True, null=False)
objects = UserManager()
username = models.CharField(unique=True, max_length=150, null=True, blank=True)
first_name = models.CharField("first name", max_length=150)
first_name = models.CharField(
"first name",
max_length=150,
db_column="first_name_v2",
)
last_name = models.CharField("last name", max_length=150)
google_user_id = models.CharField(max_length=50, null=True, blank=True)
github_user_id = models.CharField(max_length=50, null=True, blank=True)
Expand Down

0 comments on commit 78b666a

Please sign in to comment.