Skip to content

Commit 26a5031

Browse files
authored
Mastodon | Time zone calculation stabilized
2 parents c1e3c60 + b40b399 commit 26a5031

7 files changed

Lines changed: 1105 additions & 1015 deletions

File tree

fp-plugins/mastodon/developer-docs/01-Process-Map.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ flowchart TD
4747

4848
| ID | Process | Trigger | Core behavior | Primary state | Regression focus |
4949
| --- | ----------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
50-
| P1 | Scheduled content sync | Frontend `init` hook via `plugin_mastodon_maybe_sync()` | Reads compact scheduler-state first; may call `plugin_mastodon_run_sync(false)`. | scheduler-state.json, sync.guard.json, sync.lock, state.json | Simulation scheduler, cooldown, compact-state and large-state tests. |
50+
| P1 | Scheduled content sync | Frontend `init` hook via `plugin_mastodon_maybe_sync()` | Reads compact scheduler-state first; UTC-normalized due checks decide whether to call `plugin_mastodon_run_sync(false)`. | scheduler-state.json, sync.guard.json, sync.lock, state.json | Scheduler, timezone, cooldown, compact-state and large-state tests. |
5151
| P2 | Manual content sync | Admin actions in `plugin_mastodon_admin_assign()` | Calls `plugin_mastodon_run_sync(true, ...)` and bypasses due window; still respects lock and budgets. | state.json, sync.lock, rate-limit-windows.json | Manual normal/full synchronization tests. |
5252
| P3 | Remote top-level status import | Content sync when `update_local_from_remote` is enabled | Verifies account, pages statuses, filters, converts HTML/media/tags, saves FlatPress entries. | entries, entries_remote, last_remote_status_id, content_stats | Remote import and content-window tests. |
5353
| P4 | Remote reply import | Remote context pass for known imported/exported threads | Fetches context descendants, resolves parent comments, queues rechecks or tombstones. | comments, comments_remote, comment_tombstones, pending_comment_remote_rechecks | Reply tree, self-reply, quote, comment-as-entry tests. |
@@ -67,6 +67,7 @@ flowchart TD
6767
flowchart TD
6868
Start[Request or admin action]
6969
Config{Instance URL and token available?}
70+
TimeBasis[Stored UTC sync_time and UTC state timestamps]
7071
Due{Due or forced?}
7172
Cooldown{Scheduled cooldown active?}
7273
Lock{sync.lock acquired?}
@@ -78,7 +79,7 @@ flowchart TD
7879
7980
Start --> Config
8081
Config -- no --> Write
81-
Config -- yes --> Due
82+
Config -- yes --> TimeBasis --> Due
8283
Due -- no --> Stop
8384
Due -- yes --> Cooldown
8485
Cooldown -- yes and not forced --> Stop
@@ -91,7 +92,7 @@ flowchart TD
9192
Write --> Stop
9293
```
9394

94-
Manual sync bypasses the daily due check and can request a full window, but it still uses `sync.lock`, request budgets, media/delete windows and state writes. This matters on shared hosting: manual repair must not become unbounded.
95+
Manual sync bypasses the daily due check and can request a full window, but it still uses `sync.lock`, request budgets, media/delete windows and UTC state writes. The automatic due check treats stored `sync_time`, `last_run`, `last_deletion_run` and `deletions_not_before` as UTC so host or plugin changes to PHP's default timezone do not shift the daily 03:00-style FlatPress-local schedule. This matters on shared hosting: manual repair must not become unbounded.
9596

9697
## P3/P4 — Remote import
9798

@@ -174,6 +175,7 @@ flowchart TD
174175
Start[Scheduled follow-up or admin deletion sync]
175176
Enabled{delete_sync_enabled?}
176177
Pending{pending or forced?}
178+
UtcCooldown[Parse deletions_not_before as UTC]
177179
Due{due?}
178180
Lock{sync.lock acquired?}
179181
Entries[Find missing local mapped entries]
@@ -185,13 +187,13 @@ flowchart TD
185187
Retry{Legacy error 400 405 422 or delete_media message?}
186188
RetryOld[Retry DELETE without delete_media]
187189
Tombstone[Write tombstone or queue descendants recheck]
188-
State[Update cursors pending stats last_deletion_run]
190+
State[Update cursors pending stats last_deletion_run UTC]
189191
190192
Start --> Enabled
191193
Enabled -- no --> State
192194
Enabled -- yes --> Pending
193195
Pending -- no and not forced --> State
194-
Pending --> Due
196+
Pending --> UtcCooldown --> Due
195197
Due -- no --> State
196198
Due -- yes --> Lock
197199
Lock -- yes --> Entries --> Version

fp-plugins/mastodon/developer-docs/02-State-Model.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ and does not load comment shards.
4848
| Field | Type | Meaning | Usually written by | Usually read by |
4949
| ------------------------------- | --------------------------------------- | ----------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------- |
5050
| version | integer | State schema version, currently 5. | default_state; normalization on read. | state read/write, migrations, diagnostics. |
51-
| last_run | UTC datetime string | Last completed content sync timestamp. | run_sync. | scheduler-state summary, admin diagnostics, due checks. |
52-
| last_deletion_run | UTC datetime string | Last completed deletion sync timestamp. | run_deletion_sync. | scheduler-state summary, admin diagnostics. |
51+
| last_run | UTC datetime string | Last completed content sync timestamp. | run_sync via `gmdate()`. | scheduler-state summary and UTC due check. |
52+
| last_deletion_run | UTC datetime string | Last completed deletion sync timestamp. | run_deletion_sync via `gmdate()`. | scheduler-state summary and admin display. |
5353
| deletions_pending | 0/1 | Whether follow-up deletion sync work exists. | delete hooks, state_set_deletions_pending. | maybe_sync, run_deletion_sync. |
5454
| deletions_pending_scope | full\|entries\|comments | Limits what deletion work is currently needed. | state_set_deletions_pending. | deletion sync candidate selection. |
55-
| deletions_not_before | UTC datetime string | Earliest follow-up deletion run time. | state_set_deletions_pending. | deletion_sync_due. |
55+
| deletions_not_before | UTC datetime string | Earliest follow-up deletion run time. | state_set_deletions_pending. | UTC deletion_sync_due cooldown. |
5656
| last_error | string | Last operational error or rate-limit reason. | sync and deletion paths. | admin diagnostics, scheduler summary. |
5757
| last_remote_status_id | string | Newest seen imported remote top-level status. | remote-to-local sync. | next remote import since_id/max logic. |
5858
| last_remote_notification_id | string | Newest processed mention notification hint. | notification hint pass. | next notifications since_id logic. |
@@ -190,7 +190,9 @@ flowchart TD
190190

191191
## Completed Split-State Guardrails
192192

193-
The split-state implementation now uses five additional guardrails:
193+
The split-state implementation now uses six additional guardrails:
194+
195+
UTC timestamp guardrail: scheduler and deletion due checks parse stored state datetimes as UTC, write new technical state timestamps with `gmdate()`, and only apply the FlatPress `locale.timeoffset` when formatting admin-local values or building FlatPress-local date keys.
194196

195197
- A short-lived `state-write.lock` serializes every `state.json` and comment-shard mutation, including FlatPress dirty hooks that run outside the long content/deletion sync lock.
196198
- Partial states carry internal loaded-shard markers. `plugin_mastodon_state_write()` updates only loaded comment shards and preserves unloaded shards.

0 commit comments

Comments
 (0)