Background worker: keeps the first policy row it reads until it restarts, so Server settings changes never reach it #473
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#473
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, following where the memoised policy row is cleared.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atcore/memo.py:25-54(the two memos,forget_currentwith its docstring, andforget_decisions, moved there by #248 and still handed out bycore/site.pyandplugins/policy.py),core/site.py:110-121(current) andplugins/policy.py:146-155(_answers). The callers offorget_currentare nowcore/middleware.py:118,core/models.py:1082andnotifications/management/commands/send_due_reminders.py:184, and the readers named below are atjobs/pages.py:155-156andplugins/fetching.py:110.site.current()memoises theSiteSettingsrow in an asgirefLocal, andplugins.policymemoises its plugin decisions the same way. Both are cleared at the start of each request, when the row is saved in the same process, and at the top of each scheduler pass. Themanage.py workprocess added by #247 is a fourth long-lived process and clears neither, so the first errand that reads the policy fixes it for every later errand the worker runs, until the container restarts.core/site.py:117-144(current,forget_current, whose docstring names three places the row can change and misses the worker);core/errands.py:116-151(perform);core/management/commands/work.py:60-81(the loop arounddjango_tasks_db'sWorker, which runs every task in the same thread);plugins/policy.py:141-153(_memo,forget_decisions). The only callers offorget_currentarecore/middleware.py:118,core/models.py:1081andnotifications/management/commands/send_due_reminders.py:182.POSTULO_BACKGROUND_WORK=trueand the worker running, an administrator switches off keeping the source or rendering of captured pages, switches off ignoringrobots.txt, or changes plugin availability. Captures fetched by the worker keep reading the old answers fromsite.capture_keep_source()/capture_keep_rendering()(jobs/pages.py:150-155) andsite.capture_ignore_robots()(plugins/fetching.py:154), and notification delivery keeps the old plugin decisions. The row the web container saved is a different process's memo; nothing in the worker drops its own.jobs/pages.py), yet after an administrator says no the worker goes on storing copies of other people's pages, and goes on ignoringrobots.txt, for as long as it runs. The same instance without a worker obeys at once, so the behaviour depends on how it was deployed.site.forget_current()andpolicy.forget_decisions()at the top oferrands.perform(), which covers the worker and the inline path alike; add the worker toforget_current's docstring.Done when
tests/test_errands.pyruns twoerrands.perform()calls outside a request, withSiteSettings.objects.filter(pk=1).update(capture_keep_source=False)between them, and asserts that a handler readingsite.capture_keep_source()sees the new value in the second.