@@ -79,48 +79,9 @@ public function add_update( string $room, $update ): bool {
7979 return false ;
8080 }
8181
82- // Create an envelope and stamp each update to enable cursor-based filtering.
83- $ envelope = array (
84- 'timestamp ' => $ this ->get_time_marker (),
85- 'value ' => $ update ,
86- );
82+ $ meta_id = add_post_meta ( $ post_id , self ::SYNC_UPDATE_META_KEY , $ update , false );
8783
88- return (bool ) add_post_meta ( $ post_id , wp_slash ( self ::SYNC_UPDATE_META_KEY ), wp_slash ( $ envelope ), false );
89- }
90-
91- /**
92- * Retrieves all sync updates for a given room.
93- *
94- * @since 7.0.0
95- *
96- * @param string $room Room identifier.
97- * @return array<int, array{ timestamp: int, value: mixed }> Sync updates.
98- */
99- private function get_all_updates ( string $ room ): array {
100- $ this ->room_cursors [ $ room ] = $ this ->get_time_marker () - 100 ; // Small buffer to ensure consistency.
101-
102- $ post_id = $ this ->get_storage_post_id ( $ room );
103- if ( null === $ post_id ) {
104- return array ();
105- }
106-
107- $ updates = get_post_meta ( $ post_id , self ::SYNC_UPDATE_META_KEY , false );
108-
109- if ( ! is_array ( $ updates ) ) {
110- $ updates = array ();
111- }
112-
113- // Filter out any updates that don't have the expected structure.
114- $ updates = array_filter (
115- $ updates ,
116- static function ( $ update ): bool {
117- return is_array ( $ update ) && isset ( $ update ['timestamp ' ], $ update ['value ' ] ) && is_int ( $ update ['timestamp ' ] );
118- }
119- );
120-
121- $ this ->room_update_counts [ $ room ] = count ( $ updates );
122-
123- return $ updates ;
84+ return (bool ) $ meta_id ;
12485 }
12586
12687 /**
@@ -170,8 +131,7 @@ public function set_awareness_state( string $room, array $awareness ): bool {
170131 * Gets the current cursor for a given room.
171132 *
172133 * The cursor is set during get_updates_after_cursor() and represents the
173- * point in time just before the updates were retrieved, with a small buffer
174- * to ensure consistency.
134+ * highest meta_id seen for the room's sync updates.
175135 *
176136 * @since 7.0.0
177137 *
@@ -235,17 +195,6 @@ private function get_storage_post_id( string $room ): ?int {
235195 return null ;
236196 }
237197
238- /**
239- * Gets the current time in milliseconds as a comparable time marker.
240- *
241- * @since 7.0.0
242- *
243- * @return int Current time in milliseconds.
244- */
245- private function get_time_marker (): int {
246- return (int ) floor ( microtime ( true ) * 1000 );
247- }
248-
249198 /**
250199 * Gets the number of updates stored for a given room.
251200 *
@@ -259,32 +208,63 @@ public function get_update_count( string $room ): int {
259208 }
260209
261210 /**
262- * Retrieves sync updates from a room for a given client and cursor. Updates
263- * from the specified client should be excluded.
211+ * Retrieves sync updates from a room after the given cursor.
264212 *
265213 * @since 7.0.0
266214 *
267215 * @param string $room Room identifier.
268- * @param int $cursor Return updates after this cursor.
216+ * @param int $cursor Return updates after this cursor (meta_id) .
269217 * @return array<int, mixed> Sync updates.
270218 */
271219 public function get_updates_after_cursor ( string $ room , int $ cursor ): array {
272- $ all_updates = $ this ->get_all_updates ( $ room );
273- $ updates = array ();
220+ global $ wpdb ;
221+
222+ $ post_id = $ this ->get_storage_post_id ( $ room );
223+ if ( null === $ post_id ) {
224+ $ this ->room_cursors [ $ room ] = 0 ;
225+ $ this ->room_update_counts [ $ room ] = 0 ;
226+ return array ();
227+ }
274228
275- foreach ( $ all_updates as $ update ) {
276- if ( $ update ['timestamp ' ] > $ cursor ) {
277- $ updates [] = $ update ;
278- }
229+ // Capture the current room state first so the returned cursor is race-safe.
230+ $ stats = $ wpdb ->get_row (
231+ $ wpdb ->prepare (
232+ "SELECT COUNT(*) AS total_updates, COALESCE( MAX(meta_id), 0 ) AS max_meta_id FROM {$ wpdb ->postmeta } WHERE post_id = %d AND meta_key = %s " ,
233+ $ post_id ,
234+ self ::SYNC_UPDATE_META_KEY
235+ )
236+ );
237+
238+ $ total_updates = $ stats ? (int ) $ stats ->total_updates : 0 ;
239+ $ max_meta_id = $ stats ? (int ) $ stats ->max_meta_id : 0 ;
240+
241+ $ this ->room_update_counts [ $ room ] = $ total_updates ;
242+ $ this ->room_cursors [ $ room ] = $ max_meta_id ;
243+
244+ if ( $ max_meta_id <= $ cursor ) {
245+ return array ();
279246 }
280247
281- // Sort by timestamp to ensure order.
282- usort (
283- $ updates ,
284- fn ( $ a , $ b ) => $ a ['timestamp ' ] <=> $ b ['timestamp ' ]
248+ $ rows = $ wpdb ->get_results (
249+ $ wpdb ->prepare (
250+ "SELECT meta_value FROM {$ wpdb ->postmeta } WHERE post_id = %d AND meta_key = %s AND meta_id > %d AND meta_id <= %d ORDER BY meta_id ASC " ,
251+ $ post_id ,
252+ self ::SYNC_UPDATE_META_KEY ,
253+ $ cursor ,
254+ $ max_meta_id
255+ )
285256 );
286257
287- return wp_list_pluck ( $ updates , 'value ' );
258+ if ( ! $ rows ) {
259+ return array ();
260+ }
261+
262+ $ updates = array ();
263+ foreach ( $ rows as $ row ) {
264+ $ updates [] = maybe_unserialize ( $ row ->meta_value );
265+ }
266+
267+ return $ updates ;
288268 }
289269
290270 /**
@@ -293,30 +273,30 @@ public function get_updates_after_cursor( string $room, int $cursor ): array {
293273 * @since 7.0.0
294274 *
295275 * @param string $room Room identifier.
296- * @param int $cursor Remove updates with markers < this cursor.
276+ * @param int $cursor Remove updates with meta_id < this cursor.
297277 * @return bool True on success, false on failure.
298278 */
299279 public function remove_updates_before_cursor ( string $ room , int $ cursor ): bool {
280+ global $ wpdb ;
281+
300282 $ post_id = $ this ->get_storage_post_id ( $ room );
301283 if ( null === $ post_id ) {
302284 return false ;
303285 }
304286
305- $ all_updates = $ this ->get_all_updates ( $ room );
287+ $ deleted_rows = $ wpdb ->query (
288+ $ wpdb ->prepare (
289+ "DELETE FROM {$ wpdb ->postmeta } WHERE post_id = %d AND meta_key = %s AND meta_id < %d " ,
290+ $ post_id ,
291+ self ::SYNC_UPDATE_META_KEY ,
292+ $ cursor
293+ )
294+ );
306295
307- // Remove all updates for the room and re-store only those that are newer than the cursor.
308- if ( ! delete_post_meta ( $ post_id , wp_slash ( self ::SYNC_UPDATE_META_KEY ) ) ) {
296+ if ( false === $ deleted_rows ) {
309297 return false ;
310298 }
311299
312- // Re-store envelopes directly to avoid double-wrapping by add_update().
313- $ add_result = true ;
314- foreach ( $ all_updates as $ envelope ) {
315- if ( $ add_result && $ envelope ['timestamp ' ] >= $ cursor ) {
316- $ add_result = (bool ) add_post_meta ( $ post_id , self ::SYNC_UPDATE_META_KEY , $ envelope , false );
317- }
318- }
319-
320- return $ add_result ;
300+ return true ;
321301 }
322302}
0 commit comments