-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve change logs aka history (#294)
Improve data model of change logs for objects. Prior to this commit, we had 3 tables, one for objects created, one for objects deleted and another one for changes to objects. This caused complexity inside the ORM layer and inefficient queries at times. The idea of this change is to include all kind of changes in just a single table to reduce said complexity and perform optimizations across all 3 levels.
- Loading branch information
Showing
17 changed files
with
790 additions
and
555 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
serveradmin/serverdb/migrations/0011_create_change_table.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Generated by Django 3.2.16 on 2022-10-24 13:37 | ||
|
||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
|
||
import serveradmin | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('serverdb', '0010_delete_change'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='Change', | ||
fields=[ | ||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
('object_id', models.IntegerField(db_index=True)), | ||
('change_type', models.CharField(choices=[('create', 'create'), ('change', 'change'), ('delete', 'delete')], max_length=6)), | ||
('change_json', models.JSONField(encoder=serveradmin.serverdb.models.Change.ChangeJSONEncoder)), | ||
('commit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='serverdb.changecommit')), | ||
], | ||
), | ||
] |
112 changes: 112 additions & 0 deletions
112
serveradmin/serverdb/migrations/0012_migrate_change_tables.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# Generated by Django 3.2.16 on 2022-10-24 13:39 | ||
|
||
import math | ||
|
||
from django.db import migrations, transaction, connection | ||
from rich.progress import Progress | ||
|
||
BATCH_SIZE = 100000 | ||
|
||
|
||
def migrate_change_add(apps, schema_editor): | ||
change_add = apps.get_model('serverdb', 'ChangeAdd') | ||
total = change_add.objects.count() | ||
batches = math.ceil(total / BATCH_SIZE) | ||
|
||
with Progress() as progress: | ||
migration = progress.add_task("\t[green]Migrating ChangeAdd data...", total=batches) | ||
|
||
with connection.cursor() as cursor: | ||
while not progress.finished: | ||
with transaction.atomic(): | ||
cursor.execute(""" | ||
WITH moved AS ( | ||
DELETE FROM serverdb_changeadd | ||
WHERE id IN (SELECT id FROM serverdb_changeadd ORDER BY id DESC LIMIT %s FOR UPDATE) | ||
RETURNING | ||
server_id as object_id, | ||
'create' as change_type, | ||
attributes_json::jsonb as change_json, | ||
commit_id | ||
) | ||
INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) | ||
SELECT * FROM moved; | ||
""", [BATCH_SIZE]) | ||
|
||
progress.update(migration, advance=1) | ||
|
||
|
||
def migrate_change_delete(apps, schema_editor): | ||
change_delete = apps.get_model('serverdb', 'ChangeDelete') | ||
total = change_delete.objects.count() | ||
batches = math.ceil(total / BATCH_SIZE) | ||
|
||
with Progress() as progress: | ||
migration = progress.add_task("\t[green]Migrating ChangeDelete data...", total=batches) | ||
|
||
with connection.cursor() as cursor: | ||
while not progress.finished: | ||
with transaction.atomic(): | ||
cursor.execute(""" | ||
WITH moved AS ( | ||
DELETE FROM serverdb_changedelete | ||
WHERE id IN (SELECT id FROM serverdb_changedelete ORDER BY id DESC LIMIT %s FOR UPDATE) | ||
RETURNING | ||
server_id as object_id, | ||
'delete' as change_type, | ||
attributes_json::jsonb as change_json, | ||
commit_id | ||
) | ||
INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) | ||
SELECT * FROM moved; | ||
""", [BATCH_SIZE]) | ||
|
||
progress.update(migration, advance=1) | ||
|
||
|
||
def migrate_change_update(apps, schema_editor): | ||
change_update = apps.get_model('serverdb', 'ChangeUpdate') | ||
total = change_update.objects.count() | ||
batches = math.ceil(total / BATCH_SIZE) | ||
|
||
with Progress() as progress: | ||
migration = progress.add_task("\t[green]Migrating ChangeUpdate data...", total=batches) | ||
|
||
with connection.cursor() as cursor: | ||
while not progress.finished: | ||
with transaction.atomic(): | ||
cursor.execute(""" | ||
WITH moved AS ( | ||
DELETE FROM serverdb_changeupdate | ||
WHERE id IN (SELECT id FROM serverdb_changeupdate ORDER BY id DESC LIMIT %s FOR UPDATE) | ||
RETURNING | ||
server_id as object_id, | ||
'change' as change_type, | ||
updates_json::jsonb as change_json, | ||
commit_id | ||
) | ||
INSERT INTO serverdb_change (object_id, change_type, change_json, commit_id) | ||
SELECT * FROM moved; | ||
""", [BATCH_SIZE]) | ||
|
||
progress.update(migration, advance=1) | ||
|
||
|
||
class Migration(migrations.Migration): | ||
atomic = False | ||
|
||
dependencies = [ | ||
('serverdb', '0011_create_change_table'), | ||
] | ||
|
||
# The migration of the old table is in a dedicated migration to avoid | ||
# running them together with the DDL statements which cause a full table | ||
# lock. | ||
# | ||
# This migration can safely be aborted by pressing <CTRL>-<C> at any time. | ||
# It can be continued any time by starting it again. | ||
operations = [ | ||
migrations.RunPython(migrate_change_add), | ||
migrations.RunPython(migrate_change_delete), | ||
migrations.RunPython(migrate_change_update), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Generated by Django 3.2.16 on 2022-11-03 16:12 | ||
|
||
from django.db import migrations | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('serverdb', '0012_migrate_change_tables'), | ||
] | ||
|
||
operations = [ | ||
# Apparently Django doesn't support creating indexes on jsonb keys yet | ||
migrations.RunSQL( | ||
""" | ||
CREATE INDEX IF NOT EXISTS | ||
serverdb_change_change_json_hostname | ||
ON | ||
serverdb_change ((change_json->'hostname')) | ||
WHERE | ||
change_type in ('create', 'delete'); | ||
""" | ||
), | ||
] |
38 changes: 38 additions & 0 deletions
38
serveradmin/serverdb/migrations/0014_delete_deprecated_change_models.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Generated by Django 3.2.18 on 2023-03-15 13:11 | ||
|
||
from django.db import migrations | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('serverdb', '0013_change_index'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterUniqueTogether( | ||
name='changedelete', | ||
unique_together=None, | ||
), | ||
migrations.RemoveField( | ||
model_name='changedelete', | ||
name='commit', | ||
), | ||
migrations.AlterUniqueTogether( | ||
name='changeupdate', | ||
unique_together=None, | ||
), | ||
migrations.RemoveField( | ||
model_name='changeupdate', | ||
name='commit', | ||
), | ||
migrations.DeleteModel( | ||
name='ChangeAdd', | ||
), | ||
migrations.DeleteModel( | ||
name='ChangeDelete', | ||
), | ||
migrations.DeleteModel( | ||
name='ChangeUpdate', | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.