Fix: place consumed files before running the post-consume script

The consumer's storage phase opens its own file move scope, which nests under the consume task's scope. Moves requested while storing the document therefore stayed pending until the task ended, and the post-consume script could be handed a path from before the move.

The consumer now flushes the pending file moves once after the storage block, outside the media lock and the transaction, and before the post-consume script runs.
This commit is contained in:
stumpylog committed 2026-11-03 15:09:30 -08:00
1 parent 57c6fb5cfa
commit ee7a000304
2 files changed
+37

No files matched your search

+5
View File
@@ -27,6 +27,7 @@ from documents.file_handling import generate_filename
from documents.file_handling import generate_unique_filename
from documents.file_handling import validate_path_in_root
from documents.file_moves import defer_file_moves
from documents.file_moves import flush_pending_file_moves
from documents.loggers import LoggingMixin
from documents.media_lock import media_lock
from documents.models import Correspondent
@@ -810,6 +811,10 @@ class ConsumerPlugin(
exception=e,
)
# The storage scope above nests under the consume task's scope, so its
# moves are still pending; place the file before the script reads its path.
flush_pending_file_moves()
self.run_post_consume_script(document)
self.log.info(f"Document {document} consumption finished")
+32
View File
@@ -250,6 +250,38 @@ class TestConsumer(
assert document is not None
self.assertIsFile(document.source_path)
@mock.patch("documents.consumer.load_classifier")
def test_consume_places_file_before_post_consume_script(self, m) -> None:
"""
GIVEN:
- A new document to consume
WHEN:
- It is consumed
THEN:
- Pending file moves are flushed before the post-consume script runs
"""
m.return_value = MagicMock()
order = MagicMock()
with (
mock.patch(
"documents.consumer.flush_pending_file_moves",
order.flush,
),
mock.patch.object(
ConsumerPlugin,
"run_post_consume_script",
order.script,
),
):
with self.get_consumer(self.get_test_file()) as consumer:
consumer.run()
self.assertEqual(
[c[0] for c in order.mock_calls],
["flush", "script"],
)
@mock.patch("documents.consumer.load_classifier")
def test_consume_version_takes_media_lock_outside_transaction(self, m) -> None:
"""