A scheduled sync runs in the instance's language and time zone, not its owner's #335

Closed
opened 2026-10-01 06:31:29 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-30, reading src/postulo/plugins/syncing.py at 0a5cad587 and following what postulo-dav writes during a run.

sync_connection runs a sync plugin with nothing activated. A sync started by the scheduler therefore runs in settings.LANGUAGE_CODE and settings.TIME_ZONE, while the same sync started by Sync now runs inside the person's request, in their language and zone. What the run writes depends on who started it.

  • Where:
    • plugins/syncing.py:70-96 (sync_connection): plugin.sync(connection, connection.full_config) with no language and no time zone set for connection.owner. run_syncs (:110-137) calls it from the scheduler pass (src/postulo/notifications/management/commands/send_due_reminders.py:198).
    • plugins/views.py:453-456: Sync now calls the same function inside a request, where the middleware has activated the person's zone (src/postulo/core/middleware.py:129) and language.
    • For comparison, notifications do it properly: src/postulo/notifications/service.py:18-50 wraps the sending in translation.override(language_for(user)), because "a reminder announced by the scheduler has no request at all" (#223).
  • What happens on a scheduled run:
    1. Wrong hour in stored text. When a calendar sync moves an interview, reschedule_interview words the "moved from … to …" timeline entry and the reminder's summary with timezone.localtime and the active formats (src/postulo/applications/services.py:354-372). With nothing active that is the server's zone, so a person in another zone gets a reminder naming the wrong hour, sent word for word as the notification's title.
    2. Text in the instance's language. Everything the plugin words with its own catalogue (notes, conflict lines, timeline entries) and everything it asks the core to word for the other side (event_lines' SUMMARY and its "With:" line, pushed to the person's calendar) comes out in the instance's language, not the owner's.
    3. The report kept in Connection.last_summary is worded in whichever language the run happened in, and shown later inside a sentence in the reader's.
  • Who meets it: anybody whose language or time zone differs from the instance's and who has a sync connection, on every scheduled run. On an instance with one language and one zone nothing shows.
  • Fix: sync_connection runs the plugin as its owner: inside translation.override(language_for(connection.owner)) and the owner's time zone, restored afterwards, whoever started the run. One helper for "as this person", shared with the notification service, so the next piece of work done outside a request has it to use.

Related: #223 (closed), which did this for documents and notifications.

Done when

  • A test runs a sync from the scheduler's path for an owner whose language and zone differ from the instance's, with a plugin that moves an interview and words a note: the reminder's summary names the hour in the owner's zone, and the note is in the owner's language.
  • The same run started by Sync now gives the same text.
  • Writing a plugin says a sync runs in its owner's language and zone.

Found while filing the extension and DAV plugin improvements of 2026-09-30.

Found on 2026-09-30, reading `src/postulo/plugins/syncing.py` at `0a5cad587` and following what postulo-dav writes during a run. `sync_connection` runs a sync plugin with nothing activated. A sync started by the scheduler therefore runs in `settings.LANGUAGE_CODE` and `settings.TIME_ZONE`, while the same sync started by *Sync now* runs inside the person's request, in their language and zone. What the run writes depends on who started it. - **Where:** - `plugins/syncing.py:70-96` (`sync_connection`): `plugin.sync(connection, connection.full_config)` with no language and no time zone set for `connection.owner`. `run_syncs` (`:110-137`) calls it from the scheduler pass (`src/postulo/notifications/management/commands/send_due_reminders.py:198`). - `plugins/views.py:453-456`: *Sync now* calls the same function inside a request, where the middleware has activated the person's zone (`src/postulo/core/middleware.py:129`) and language. - For comparison, notifications do it properly: `src/postulo/notifications/service.py:18-50` wraps the sending in `translation.override(language_for(user))`, because "a reminder announced by the scheduler has no request at all" (#223). - **What happens on a scheduled run:** 1. **Wrong hour in stored text.** When a calendar sync moves an interview, `reschedule_interview` words the "moved from … to …" timeline entry and the reminder's summary with `timezone.localtime` and the active formats (`src/postulo/applications/services.py:354-372`). With nothing active that is the server's zone, so a person in another zone gets a reminder naming the wrong hour, sent word for word as the notification's title. 2. **Text in the instance's language.** Everything the plugin words with its own catalogue (notes, conflict lines, timeline entries) and everything it asks the core to word for the other side (`event_lines`' `SUMMARY` and its "With:" line, pushed to the person's calendar) comes out in the instance's language, not the owner's. 3. **The report** kept in `Connection.last_summary` is worded in whichever language the run happened in, and shown later inside a sentence in the reader's. - **Who meets it:** anybody whose language or time zone differs from the instance's and who has a sync connection, on every scheduled run. On an instance with one language and one zone nothing shows. - **Fix:** `sync_connection` runs the plugin as its owner: inside `translation.override(language_for(connection.owner))` and the owner's time zone, restored afterwards, whoever started the run. One helper for "as this person", shared with the notification service, so the next piece of work done outside a request has it to use. Related: #223 (closed), which did this for documents and notifications. ## Done when - A test runs a sync from the scheduler's path for an owner whose language and zone differ from the instance's, with a plugin that moves an interview and words a note: the reminder's summary names the hour in the owner's zone, and the note is in the owner's language. - The same run started by *Sync now* gives the same text. - *Writing a plugin* says a sync runs in its owner's language and zone. Found while filing the extension and DAV plugin improvements of 2026-09-30.
tiagoagueda added this to the 0.5.0 milestone 2026-10-01 06:31:29 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#335
No description provided.