From b0e2986730a339342bce25801874d74d4ea7d9ee Mon Sep 17 00:00:00 2001 From: Norman Hooper Date: Tue, 3 Aug 2021 19:39:55 +0100 Subject: [PATCH] --wip-- architect and migration --- corehq/motech/migrations/0009_partition.py | 109 +++++++++++++++++++++ corehq/motech/models.py | 10 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 corehq/motech/migrations/0009_partition.py diff --git a/corehq/motech/migrations/0009_partition.py b/corehq/motech/migrations/0009_partition.py new file mode 100644 index 000000000000..c55aac16a6ac --- /dev/null +++ b/corehq/motech/migrations/0009_partition.py @@ -0,0 +1,109 @@ +from django.db import migrations +from django.db.migrations.operations.models import ModelOperation + +from architect.commands import partition + + +def get_sql(): + next_month = '2021-09-01 00:00:00 Z' # TODO: Calculate this + return f""" + CREATE TABLE motech_requestlog ( + id integer NOT NULL, + domain character varying(126) NOT NULL, + "timestamp" timestamp with time zone NOT NULL, + request_method character varying(12) NOT NULL, + request_url character varying(255) NOT NULL, + request_headers text NOT NULL, + request_params text NOT NULL, + request_body text, + request_error text, + response_status integer, + response_body text, + log_level integer, + payload_id character varying(126), + response_headers text + ); + + CREATE SEQUENCE motech_requestlog_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + ALTER SEQUENCE motech_requestlog_id_seq + OWNED BY motech_requestlog.id; + + ALTER TABLE dhis2_jsonapilog + ADD CONSTRAINT before_next_month + CHECK ("timestamp" < TIMESTAMP '{next_month}'); + + ALTER TABLE dhis2_jsonapilog + INHERIT motech_requestlog; + """ + + +reverse_sql = """ + ALTER TABLE dhis2_jsonapilog + NO INHERIT motech_requestlog; + + ALTER TABLE dhis2_jsonapilog + DROP CONSTRAINT before_next_month; + + DROP SEQUENCE motech_requestlog_id_seq; + + DROP TABLE motech_requestlog; + +""" + + +class PointModelAtTable(ModelOperation): + """ + Point a model to a different table. + + The new table must already be set up as an exact replica of the + current table. This class is therefore a state operation, and + intentionally does not implement ``database_forwards()`` and + ``database_backwards()``. + """ + + def __init__(self, name, table): + self.table = table + super().__init__(name) + + def deconstruct(self): + kwargs = { + 'name': self.name, + 'table': self.table, + } + return self.__class__.__qualname__, [], kwargs + + def state_forwards(self, app_label, state): + state.models[app_label, self.name_lower].options["db_table"] = self.table + state.reload_model(app_label, self.name_lower, delay=True) + + def describe(self): + return f"Point model {self.name} at table {self.table}" + + +def add_partitions(apps, schema_editor): + partition.run({'module': 'corehq.motech.models'}) + + +class Migration(migrations.Migration): + + dependencies = [ + ('motech', '0008_requestlog_response_headers'), + ] + + operations = [ + migrations.RunSQL( + get_sql(), + reverse_sql=reverse_sql, + state_operations=[PointModelAtTable( + name='requestlog', + table='motech_requestlog', + )], + ), + migrations.RunPython(add_partitions), + ] diff --git a/corehq/motech/models.py b/corehq/motech/models.py index a5e20563a9bb..ff9f8828cb2f 100644 --- a/corehq/motech/models.py +++ b/corehq/motech/models.py @@ -6,6 +6,7 @@ from django.utils.functional import cached_property from django.utils.translation import gettext as _ +import architect import attr import jsonfield @@ -224,6 +225,13 @@ def used_by(self): return kinds +@architect.install( + 'partition', + type='range', + subtype='date', + constraint='month', + column='timestamp', +) class RequestLog(models.Model): """ Store API requests and responses to analyse errors and keep an audit trail @@ -248,7 +256,7 @@ class RequestLog(models.Model): response_body = models.TextField(blank=True, null=True) class Meta: - db_table = 'dhis2_jsonapilog' + db_table = 'motech_requestlog' @staticmethod def log(level: int, log_entry: RequestLogEntry):