You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On a site with a persistent object cache, every Heartbeat tick from an open editor makes every cached post query on the site stale.
flowchart LR
A[Post open in editor] -->|every Heartbeat tick| B[Lock rewritten in post meta]
B --> C[Posts last_changed bumped]
C --> D[Every cached post query stale]
Loading
A post lock already is presence: who holds this post, refreshed every tick, stale 150 seconds after the last one. The same editor's presence row already records which block they are in, through gutenberg-sync-engines' block awareness. Keeping the lock in that row puts both facts in one place, and it stops the cache flush as a side effect. Writing the lock through $wpdb, as r62099 did for sync storage, would fix the cache and leave the two apart.
Today
With the lock in presence
Where the lock lives
Post meta
The editor's presence row
Cached post queries on each tick
Go stale
Stay valid
Locking for the person editing
Works
Works the same
Core touches _edit_lock only through get_post_meta(), update_post_meta() and delete_post_meta(), so their three short-circuit filters move it without changing a caller. The Customizer changeset lock is _edit_lock on a post too, so the same filters cover it.
Write _edit_lock to the lock holder's presence row from update_post_metadata, and clear it from delete_post_metadata
Read it back from get_post_metadata, so wp_check_post_lock() and every caller of it work unchanged
Test: refreshing a lock leaves wp_cache_get_last_changed( 'posts' ) unchanged, and a second user still sees the post as locked
The test asserts the cache key itself because that is the defect; a test on the filters alone would still pass if something else wrote the meta.
Where this happens in core
wp_set_post_lock() writes _edit_lock with update_post_meta(), and the value is a fresh timestamp each time
On a site with a persistent object cache, every Heartbeat tick from an open editor makes every cached post query on the site stale.
A post lock already is presence: who holds this post, refreshed every tick, stale 150 seconds after the last one. The same editor's presence row already records which block they are in, through gutenberg-sync-engines' block awareness. Keeping the lock in that row puts both facts in one place, and it stops the cache flush as a side effect. Writing the lock through
$wpdb, as r62099 did for sync storage, would fix the cache and leave the two apart.Core touches
_edit_lockonly throughget_post_meta(),update_post_meta()anddelete_post_meta(), so their three short-circuit filters move it without changing a caller. The Customizer changeset lock is_edit_lockon a post too, so the same filters cover it._edit_lockto the lock holder's presence row fromupdate_post_metadata, and clear it fromdelete_post_metadataget_post_metadata, sowp_check_post_lock()and every caller of it work unchangedwp_cache_get_last_changed( 'posts' )unchanged, and a second user still sees the post as lockedThe test asserts the cache key itself because that is the defect; a test on the filters alone would still pass if something else wrote the meta.
Where this happens in core
wp_set_post_lock()writes_edit_lockwithupdate_post_meta(), and the value is a fresh timestamp each timedefault-filters.php#L126hooksupdated_post_metatowp_cache_set_posts_last_changed()WP_Customize_Manager::refresh_changeset_lock()writes the same key on the changeset post_edit_lockin SQL would miss the lock