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 <noreply@anthropic.com>
This commit is contained in:
Proudlock
2026-09-15 10:12:30 -04:00
parent 5cd5332397
commit affe455c55

View File

@@ -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: