Explorar o código

#21355: Refactor trigger migrations

Jeremy Stretch hai 2 días
pai
achega
e7ed80ed8b

+ 22 - 2
netbox/circuits/migrations/0058_denormalization_triggers.py

@@ -4,7 +4,7 @@ of the Python `post_save` handler formerly registered in netbox.denormalized.
 """
 from django.db import migrations
 
-from utilities.migration import cached_scope_triggers
+from utilities.migration import InstallDenormalizationTrigger
 
 
 class Migration(migrations.Migration):
@@ -15,4 +15,24 @@ class Migration(migrations.Migration):
         ('dcim', '0238_ltree_paths'),
     ]
 
-    operations = cached_scope_triggers('circuits_circuittermination')
+    operations = [
+        InstallDenormalizationTrigger(
+            dependent_table='circuits_circuittermination',
+            source_table='dcim_site',
+            fk_column='_site_id',
+            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
+        ),
+        InstallDenormalizationTrigger(
+            dependent_table='circuits_circuittermination',
+            source_table='dcim_location',
+            fk_column='_location_id',
+            mappings={'_site_id': 'site_id'},
+            related_mappings=(
+                {
+                    'table': 'dcim_site',
+                    'source_fk': 'site_id',
+                    'mappings': {'_region_id': 'region_id', '_site_group_id': 'group_id'},
+                },
+            ),
+        ),
+    ]

+ 2 - 5
netbox/dcim/signals.py

@@ -34,9 +34,7 @@ from .utils import create_cablepaths, rebuild_paths
 def handle_location_site_change(instance, created, **kwargs):
     """
     Cascade a Location's Site assignment down to the Racks, Devices, and PowerPanels it contains
-    (and to descendant Locations). The denormalized cache columns on cable terminations and device
-    components are maintained by PostgreSQL triggers, which fire on these Site/Location/Rack/Device
-    column writes.
+    (and to descendant Locations).
     """
     if not created:
         instance.get_descendants().update(site=instance.site)
@@ -49,8 +47,7 @@ def handle_location_site_change(instance, created, **kwargs):
 @receiver(post_save, sender=Rack)
 def handle_rack_site_change(instance, created, **kwargs):
     """
-    Cascade a Rack's Site/Location assignment down to the Devices it contains. The denormalized cache
-    columns on those devices' components are maintained by PostgreSQL triggers.
+    Cascade a Rack's Site/Location assignment down to the Devices it contains.
     """
     if not created:
         Device.objects.filter(rack=instance).update(site=instance.site, location=instance.location)

+ 22 - 2
netbox/ipam/migrations/0093_denormalization_triggers.py

@@ -4,7 +4,7 @@ Python `post_save` handler formerly registered in netbox.denormalized (and dcim.
 """
 from django.db import migrations
 
-from utilities.migration import cached_scope_triggers
+from utilities.migration import InstallDenormalizationTrigger
 
 
 class Migration(migrations.Migration):
@@ -15,4 +15,24 @@ class Migration(migrations.Migration):
         ('dcim', '0238_ltree_paths'),
     ]
 
-    operations = cached_scope_triggers('ipam_prefix')
+    operations = [
+        InstallDenormalizationTrigger(
+            dependent_table='ipam_prefix',
+            source_table='dcim_site',
+            fk_column='_site_id',
+            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
+        ),
+        InstallDenormalizationTrigger(
+            dependent_table='ipam_prefix',
+            source_table='dcim_location',
+            fk_column='_location_id',
+            mappings={'_site_id': 'site_id'},
+            related_mappings=(
+                {
+                    'table': 'dcim_site',
+                    'source_fk': 'site_id',
+                    'mappings': {'_region_id': 'region_id', '_site_group_id': 'group_id'},
+                },
+            ),
+        ),
+    ]

+ 9 - 39
netbox/utilities/migration.py

@@ -4,7 +4,6 @@ from netbox.config import ConfigItem
 
 __all__ = (
     'InstallDenormalizationTrigger',
-    'cached_scope_triggers',
     'custom_deconstruct',
 )
 
@@ -68,6 +67,15 @@ class InstallDenormalizationTrigger(migrations.operations.base.Operation):
     newly created source row has no dependents yet) and it does not recurse: the dependent tables carry no
     triggers of their own.
 
+    Example: refresh a CircuitTermination's cached region/sitegroup when its Site's region or group changes::
+
+        InstallDenormalizationTrigger(
+            dependent_table='circuits_circuittermination',
+            source_table='dcim_site',
+            fk_column='_site_id',
+            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
+        )
+
     Note: this is a row-level trigger, so a bulk source update of N rows fires it N times. A statement-level
     trigger with transition tables would batch this, but PostgreSQL forbids transition tables on a trigger
     with an `UPDATE OF <columns>` list, and dropping that column list would fire the trigger on every source
@@ -139,41 +147,3 @@ class InstallDenormalizationTrigger(migrations.operations.base.Operation):
 
     def describe(self):
         return f'Install denormalization trigger on {self.source_table} updating {self.dependent_table}'
-
-
-# Site/region/site-group lookup shared by every CachedScopeMixin-style dependent (see cached_scope_triggers).
-SITE_SCOPE_RELATED_MAPPINGS = (
-    {
-        'table': 'dcim_site',
-        'source_fk': 'site_id',
-        'mappings': {'_region_id': 'region_id', '_site_group_id': 'group_id'},
-    },
-)
-
-
-def cached_scope_triggers(dependent_table):
-    """
-    Return the Site + Location `InstallDenormalizationTrigger` pair for a dependent table carrying the
-    standard cached-scope columns (_site/_location/_region/_site_group) — i.e. any CachedScopeMixin model
-    (Prefix, Cluster, WirelessLAN) plus CircuitTermination, which share the same denormalization shape.
-
-    Region- and SiteGroup-scoped rows need no trigger: their cached FK is the scoped object itself and
-    never changes underneath them. So two triggers fully cover the cache:
-      - dcim_site: region/group changed  -> refresh _region/_site_group on rows scoped to that site
-      - dcim_location: site changed       -> refresh _site (and the new site's region/group)
-    """
-    return [
-        InstallDenormalizationTrigger(
-            dependent_table=dependent_table,
-            source_table='dcim_site',
-            fk_column='_site_id',
-            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
-        ),
-        InstallDenormalizationTrigger(
-            dependent_table=dependent_table,
-            source_table='dcim_location',
-            fk_column='_location_id',
-            mappings={'_site_id': 'site_id'},
-            related_mappings=SITE_SCOPE_RELATED_MAPPINGS,
-        ),
-    ]

+ 22 - 2
netbox/virtualization/migrations/0057_denormalization_triggers.py

@@ -4,7 +4,7 @@ via PostgreSQL triggers instead of the Python `dcim.signals.sync_cached_scope_fi
 """
 from django.db import migrations
 
-from utilities.migration import cached_scope_triggers
+from utilities.migration import InstallDenormalizationTrigger
 
 
 class Migration(migrations.Migration):
@@ -15,4 +15,24 @@ class Migration(migrations.Migration):
         ('dcim', '0238_ltree_paths'),
     ]
 
-    operations = cached_scope_triggers('virtualization_cluster')
+    operations = [
+        InstallDenormalizationTrigger(
+            dependent_table='virtualization_cluster',
+            source_table='dcim_site',
+            fk_column='_site_id',
+            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
+        ),
+        InstallDenormalizationTrigger(
+            dependent_table='virtualization_cluster',
+            source_table='dcim_location',
+            fk_column='_location_id',
+            mappings={'_site_id': 'site_id'},
+            related_mappings=(
+                {
+                    'table': 'dcim_site',
+                    'source_fk': 'site_id',
+                    'mappings': {'_region_id': 'region_id', '_site_group_id': 'group_id'},
+                },
+            ),
+        ),
+    ]

+ 22 - 2
netbox/wireless/migrations/0021_denormalization_triggers.py

@@ -5,7 +5,7 @@ handler.
 """
 from django.db import migrations
 
-from utilities.migration import cached_scope_triggers
+from utilities.migration import InstallDenormalizationTrigger
 
 
 class Migration(migrations.Migration):
@@ -16,4 +16,24 @@ class Migration(migrations.Migration):
         ('dcim', '0238_ltree_paths'),
     ]
 
-    operations = cached_scope_triggers('wireless_wirelesslan')
+    operations = [
+        InstallDenormalizationTrigger(
+            dependent_table='wireless_wirelesslan',
+            source_table='dcim_site',
+            fk_column='_site_id',
+            mappings={'_region_id': 'region_id', '_site_group_id': 'group_id'},
+        ),
+        InstallDenormalizationTrigger(
+            dependent_table='wireless_wirelesslan',
+            source_table='dcim_location',
+            fk_column='_location_id',
+            mappings={'_site_id': 'site_id'},
+            related_mappings=(
+                {
+                    'table': 'dcim_site',
+                    'source_fk': 'site_id',
+                    'mappings': {'_region_id': 'region_id', '_site_group_id': 'group_id'},
+                },
+            ),
+        ),
+    ]