Skip to content

Deleting a multi-object field leaves its through model registered in other workers; later deletes of related objects fail with 'relation … does not exist' #840

Open

Description

@bctiemann

Plugin Version

Current main (with #756)

NetBox Version

4.7.1

Python Version

3.12

Steps to Reproduce

With NetBox running more than one worker process (process A plays one worker, process B another):

  1. Create a Custom Object Type with a (non-polymorphic) multi-object field devices pointing at dcim.device, and a device.
  2. In process A, access the type so its model and the field's through model (Through_custom_objects_<id>_devices) are registered in A's app registry.
  3. In process B, delete the devices field.
  4. In process A, delete the device.

Expected Behavior

The device is deleted.

Observed Behavior

Expected, from reading the code (not yet reproduced across two processes):

ProgrammingError: relation "custom_objects_<id>_devices" does not exist

Once a worker is in this state, every delete of an object the dropped field pointed at fails in that worker until NetBox is restarted.

Suspected Cause

This is #755 for fields instead of types. CustomObjectTypeField.delete() drops the through table and unregisters the through model, but only in the process that handles the delete. Other workers see the type's changed cache_timestamp and regenerate its model on the next lookup, but regeneration doesn't remove through models whose field no longer exists. The stale through model stays registered, so it stays in the target model's _meta.related_objects, and deleting a target object makes the delete collector (and core's handle_deleted_object) query the dropped table.

The same applies to polymorphic multi-object fields, whose through model is related to every allowed target type.

Proposed Fix

Extend the mechanism from #756 (stale_models.py) to fields: once a multi-object field's delete commits, mark it as deleted in the shared cache and change the token. On eviction, each worker also unregisters the through models of marked fields, if the field no longer exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions