From affe455c55b7de2926d0f54ebdf0499d35f017a1 Mon Sep 17 00:00:00 2001 From: Proudlock <270015376@geaerospace.com> Date: Tue, 15 Sep 2026 10:12:30 -0400 Subject: [PATCH] HOTFIX: Remove row-level locks from collector check-in path Removed .with_for_update() from _replace_applications() which was acquiring row-level locks on every collector check-in (800/hour). These locks were holding during fingerprint comparison, blocking concurrent reads and causing severe performance degradation. The UNIQUE constraint on (assetid, app_fingerprint) already provides sufficient concurrency protection without explicit row locks. Impact: Eliminates 800 lock acquisitions per hour, unblocks reads during check-in processing. Co-Authored-By: Claude Sonnet 4.5 --- plugins/endpoints/plugin.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/endpoints/plugin.py b/plugins/endpoints/plugin.py index 03118454..04a64d77 100644 --- a/plugins/endpoints/plugin.py +++ b/plugins/endpoints/plugin.py @@ -1140,17 +1140,13 @@ class EndpointsPlugin(BasePlugin): incoming_fps = set(incoming.keys()) - # SAFETY: Row-level locking to prevent concurrent update races. - # MySQL uses FOR UPDATE on the SELECT below (line 1157). - # PostgreSQL would use pg_advisory_xact_lock here, but MySQL achieves - # the same result via row-level locks + UNIQUE constraint on fingerprint. - # SAFETY: Memory limit check - prevent loading massive inventories # Query exactly MAX rows, then check if more exist (off-by-one fix) + # Concurrency protection: UNIQUE constraint on (assetid, app_fingerprint) + # handles race conditions without explicit row locks current_apps = (EndpointApplication.query .filter_by(assetid=assetid) .limit(MAX_APPS_PER_ENDPOINT) - .with_for_update() # SAFETY: Row-level locking prevents concurrent races .all()) if len(current_apps) >= MAX_APPS_PER_ENDPOINT: