mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-11-06 06:49:23 +00:00
Fix: make the global media lock reentrant within a thread
Every caller built its own FileLock on media.lock, so code already holding it could not call into code that takes it again without blocking itself. That made it impossible to take media.lock before opening a transaction in paths that also attach files or move files inside that transaction. media_lock() hands out one FileLock instance per path with per-thread hold counts, so a thread re-enters while other threads and processes stay excluded. All media.lock call sites now use it.
This commit is contained in:
1 parent
08748baf54
commit
3591c39c5f
10 files changed
+252
-15
No files matched your search
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
Document file moves, coalesced to once per unit of work.
|
||||
|
||||
Every save that can change a document's generated filename asks for a file
|
||||
move through request_file_move(). Inside a scope opened by defer_file_moves()
|
||||
(a request, a Celery task, the consumer, or a per-item command step) the
|
||||
request is only recorded, and the outermost scope moves each recorded document
|
||||
once, after its own writes have committed. Outside any scope the move happens
|
||||
immediately.
|
||||
|
||||
The mover always takes media.lock first and then reads the document fresh, so
|
||||
it starts from the latest committed state and never waits on media.lock while
|
||||
its own transaction holds document rows.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
|
||||
def in_user_transaction() -> bool:
|
||||
"""
|
||||
True when the default connection is inside an atomic block that was not
|
||||
created by Django's test case machinery.
|
||||
|
||||
Django marks the atomic blocks TestCase (and pytest-django) wrap around
|
||||
each test with _from_testcase, the same flag it uses for durable checks.
|
||||
Ignoring them keeps tests on the same path as production.
|
||||
"""
|
||||
connection = transaction.get_connection()
|
||||
return any(not block._from_testcase for block in connection.atomic_blocks)
|
||||
Reference in new issue
Block a user