From 063dbf8242eeb667e25b82eaa493d7eedfc4e39f Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Tue, 24 Feb 2026 16:19:28 +0000 Subject: [PATCH 1/7] Add new clear queue endpoint --- .../sync/src/class-rest-endpoints.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/projects/packages/sync/src/class-rest-endpoints.php b/projects/packages/sync/src/class-rest-endpoints.php index 1bc84b08240b..c2bf7482195b 100644 --- a/projects/packages/sync/src/class-rest-endpoints.php +++ b/projects/packages/sync/src/class-rest-endpoints.php @@ -332,6 +332,24 @@ public static function initialize_rest_api() { 'permission_callback' => __CLASS__ . '::verify_default_permissions', ) ); + + // Clear Sync queue. + register_rest_route( + 'jetpack/v4', + '/sync/clear-queue', + array( + 'methods' => WP_REST_Server::EDITABLE, + 'callback' => __CLASS__ . '::clear_queue', + 'permission_callback' => __CLASS__ . '::verify_default_permissions', + 'args' => array( + 'queue' => array( + 'description' => __( 'Name of Sync queue to clear.', 'jetpack-sync' ), + 'type' => 'string', + 'required' => true, + ), + ), + ) + ); } /** @@ -810,6 +828,39 @@ public static function reset_locks() { ); } + /** + * Clear a Sync queue. + * + * @since $$next-version$$ + * + * @param \WP_REST_Request $request The request sent to the WP REST API. + * + * @return \WP_REST_Response|WP_Error + */ + public static function clear_queue( $request ) { + $queue_name = $request->get_param( 'queue' ); + + if ( ! in_array( $queue_name, array( 'sync', 'full_sync' ), true ) ) { + return new WP_Error( 'invalid_queue', 'Queue name should be sync or full_sync', array( 'status' => 400 ) ); + } + + $queue = new Queue( $queue_name ); + $queue->reset(); + + // If the incremental sync queue was cleared, re-enable sending in case + // it was temporarily disabled during a pull. + if ( 'sync' === $queue_name ) { + delete_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME ); + } + + return rest_ensure_response( + array( + 'success' => true, + 'queue' => $queue_name, + ) + ); + } + /** * Verify that request has default permissions to perform sync actions. * From 67da7bdc78cf817ea76520b9e97bdaf2f4e3f9e3 Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Tue, 24 Feb 2026 16:19:59 +0000 Subject: [PATCH 2/7] Add tests for new endpoint --- .../sync/tests/php/REST_Endpoints_Test.php | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/projects/packages/sync/tests/php/REST_Endpoints_Test.php b/projects/packages/sync/tests/php/REST_Endpoints_Test.php index 0624087224c1..6ab4868a79d2 100644 --- a/projects/packages/sync/tests/php/REST_Endpoints_Test.php +++ b/projects/packages/sync/tests/php/REST_Endpoints_Test.php @@ -262,6 +262,63 @@ public function test_sync_reset_locks() { $this->assertEquals( 200, $response->get_status() ); } + /** + * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint clears the specified queue. + */ + public function test_sync_clear_queue() { + $user = wp_get_current_user(); + $user->add_cap( 'manage_options' ); + + $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); + $request->set_header( 'Content-Type', 'application/json' ); + $request->set_body( '{ "queue": "sync" }' ); + + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); + + $user->remove_cap( 'manage_options' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertTrue( $data['success'] ); + $this->assertEquals( 'sync', $data['queue'] ); + } + + /** + * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint rejects queue names other than sync and full_sync. + * + * @param string $queue_name Queue name to test. + * @dataProvider clear_queue_invalid_queue_provider + */ + #[DataProvider( 'clear_queue_invalid_queue_provider' )] + public function test_sync_clear_queue_invalid_queue( $queue_name ) { + $user = wp_get_current_user(); + $user->add_cap( 'manage_options' ); + + $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); + $request->set_header( 'Content-Type', 'application/json' ); + $request->set_body( '{ "queue": "' . $queue_name . '" }' ); + + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); + + $user->remove_cap( 'manage_options' ); + + $this->assertEquals( 400, $response->get_status() ); + $this->assertEquals( 'invalid_queue', $data['code'] ); + } + + /** + * Queue names that should be rejected by the clear-queue endpoint. + * + * @return array + */ + public static function clear_queue_invalid_queue_provider() { + return array( + array( 'immediate' ), + array( 'invalid_queue' ), + ); + } + /** * Array of Sync Endpoints and method. * @@ -283,6 +340,7 @@ public static function endpoint_provider() { array( 'sync/data-check', 'GET', null ), array( 'sync/data-histogram', 'POST', null ), array( 'sync/locks', 'DELETE', null ), + array( 'sync/clear-queue', 'POST', '{ "queue": "sync" }' ), ); } From 85b4be4e7ac92b50dea984ce68e7d6f7e36621bd Mon Sep 17 00:00:00 2001 From: Changelog Bot Date: Tue, 24 Feb 2026 18:21:22 +0000 Subject: [PATCH 3/7] Add changelog entries. --- projects/packages/sync/changelog/pr-47303 | 4 ++++ projects/plugins/jetpack/changelog/pr-47303 | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 projects/packages/sync/changelog/pr-47303 create mode 100644 projects/plugins/jetpack/changelog/pr-47303 diff --git a/projects/packages/sync/changelog/pr-47303 b/projects/packages/sync/changelog/pr-47303 new file mode 100644 index 000000000000..bbf768b4aff0 --- /dev/null +++ b/projects/packages/sync/changelog/pr-47303 @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +REST_Endpoints: Add clear-queue endpoint to allow clearing a Sync queue via REST API. diff --git a/projects/plugins/jetpack/changelog/pr-47303 b/projects/plugins/jetpack/changelog/pr-47303 new file mode 100644 index 000000000000..ebfae8c170f2 --- /dev/null +++ b/projects/plugins/jetpack/changelog/pr-47303 @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Sync: Add clear-queue REST endpoint to allow clearing a Sync queue. From d6ec87e4ac0c7727e4269671d9ce56e9efb8b7ea Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Wed, 25 Feb 2026 09:58:12 +0000 Subject: [PATCH 4/7] Remove full-sync as a queue option --- projects/packages/sync/src/class-rest-endpoints.php | 2 +- projects/packages/sync/tests/php/REST_Endpoints_Test.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/packages/sync/src/class-rest-endpoints.php b/projects/packages/sync/src/class-rest-endpoints.php index c2bf7482195b..61b9cab0c83e 100644 --- a/projects/packages/sync/src/class-rest-endpoints.php +++ b/projects/packages/sync/src/class-rest-endpoints.php @@ -840,7 +840,7 @@ public static function reset_locks() { public static function clear_queue( $request ) { $queue_name = $request->get_param( 'queue' ); - if ( ! in_array( $queue_name, array( 'sync', 'full_sync' ), true ) ) { + if ( ! in_array( $queue_name, array( 'sync' ), true ) ) { return new WP_Error( 'invalid_queue', 'Queue name should be sync or full_sync', array( 'status' => 400 ) ); } diff --git a/projects/packages/sync/tests/php/REST_Endpoints_Test.php b/projects/packages/sync/tests/php/REST_Endpoints_Test.php index 6ab4868a79d2..fcbd802b4efa 100644 --- a/projects/packages/sync/tests/php/REST_Endpoints_Test.php +++ b/projects/packages/sync/tests/php/REST_Endpoints_Test.php @@ -284,7 +284,7 @@ public function test_sync_clear_queue() { } /** - * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint rejects queue names other than sync and full_sync. + * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint rejects queue names other than sync. * * @param string $queue_name Queue name to test. * @dataProvider clear_queue_invalid_queue_provider @@ -314,6 +314,7 @@ public function test_sync_clear_queue_invalid_queue( $queue_name ) { */ public static function clear_queue_invalid_queue_provider() { return array( + array( 'full_sync' ), array( 'immediate' ), array( 'invalid_queue' ), ); From d0a5c49ceda7fa0b6aac40356572a0a27ea47039 Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Wed, 25 Feb 2026 11:28:15 +0000 Subject: [PATCH 5/7] Update the endpoint and clear_queue function since we can assume the only queue is sync now --- .../sync/src/class-rest-endpoints.php | 32 +++----------- .../sync/tests/php/REST_Endpoints_Test.php | 44 +------------------ 2 files changed, 9 insertions(+), 67 deletions(-) diff --git a/projects/packages/sync/src/class-rest-endpoints.php b/projects/packages/sync/src/class-rest-endpoints.php index 61b9cab0c83e..521dc7cf00e8 100644 --- a/projects/packages/sync/src/class-rest-endpoints.php +++ b/projects/packages/sync/src/class-rest-endpoints.php @@ -341,13 +341,6 @@ public static function initialize_rest_api() { 'methods' => WP_REST_Server::EDITABLE, 'callback' => __CLASS__ . '::clear_queue', 'permission_callback' => __CLASS__ . '::verify_default_permissions', - 'args' => array( - 'queue' => array( - 'description' => __( 'Name of Sync queue to clear.', 'jetpack-sync' ), - 'type' => 'string', - 'required' => true, - ), - ), ) ); } @@ -829,34 +822,23 @@ public static function reset_locks() { } /** - * Clear a Sync queue. + * Clear the Sync queue. * * @since $$next-version$$ * - * @param \WP_REST_Request $request The request sent to the WP REST API. - * - * @return \WP_REST_Response|WP_Error + * @return \WP_REST_Response */ - public static function clear_queue( $request ) { - $queue_name = $request->get_param( 'queue' ); - - if ( ! in_array( $queue_name, array( 'sync' ), true ) ) { - return new WP_Error( 'invalid_queue', 'Queue name should be sync or full_sync', array( 'status' => 400 ) ); - } - - $queue = new Queue( $queue_name ); + public static function clear_queue() { + $queue = new Queue( 'sync' ); $queue->reset(); - // If the incremental sync queue was cleared, re-enable sending in case - // it was temporarily disabled during a pull. - if ( 'sync' === $queue_name ) { - delete_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME ); - } + // Re-enable sending in case it was temporarily disabled during a pull. + delete_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME ); return rest_ensure_response( array( 'success' => true, - 'queue' => $queue_name, + 'queue' => 'sync', ) ); } diff --git a/projects/packages/sync/tests/php/REST_Endpoints_Test.php b/projects/packages/sync/tests/php/REST_Endpoints_Test.php index fcbd802b4efa..0671b691d196 100644 --- a/projects/packages/sync/tests/php/REST_Endpoints_Test.php +++ b/projects/packages/sync/tests/php/REST_Endpoints_Test.php @@ -263,16 +263,13 @@ public function test_sync_reset_locks() { } /** - * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint clears the specified queue. + * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint clears the sync queue. */ public function test_sync_clear_queue() { $user = wp_get_current_user(); $user->add_cap( 'manage_options' ); - $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); - $request->set_header( 'Content-Type', 'application/json' ); - $request->set_body( '{ "queue": "sync" }' ); - + $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); $response = $this->server->dispatch( $request ); $data = $response->get_data(); @@ -283,43 +280,6 @@ public function test_sync_clear_queue() { $this->assertEquals( 'sync', $data['queue'] ); } - /** - * Testing the `POST /jetpack/v4/sync/clear-queue` endpoint rejects queue names other than sync. - * - * @param string $queue_name Queue name to test. - * @dataProvider clear_queue_invalid_queue_provider - */ - #[DataProvider( 'clear_queue_invalid_queue_provider' )] - public function test_sync_clear_queue_invalid_queue( $queue_name ) { - $user = wp_get_current_user(); - $user->add_cap( 'manage_options' ); - - $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); - $request->set_header( 'Content-Type', 'application/json' ); - $request->set_body( '{ "queue": "' . $queue_name . '" }' ); - - $response = $this->server->dispatch( $request ); - $data = $response->get_data(); - - $user->remove_cap( 'manage_options' ); - - $this->assertEquals( 400, $response->get_status() ); - $this->assertEquals( 'invalid_queue', $data['code'] ); - } - - /** - * Queue names that should be rejected by the clear-queue endpoint. - * - * @return array - */ - public static function clear_queue_invalid_queue_provider() { - return array( - array( 'full_sync' ), - array( 'immediate' ), - array( 'invalid_queue' ), - ); - } - /** * Array of Sync Endpoints and method. * From eb0ba4629cabed680bfe2bb6b8c6b693aa3d961c Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Wed, 25 Feb 2026 12:14:35 +0000 Subject: [PATCH 6/7] Update test to conside that sync is now the default queue --- projects/packages/sync/tests/php/REST_Endpoints_Test.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/projects/packages/sync/tests/php/REST_Endpoints_Test.php b/projects/packages/sync/tests/php/REST_Endpoints_Test.php index 0671b691d196..7efcc39a7962 100644 --- a/projects/packages/sync/tests/php/REST_Endpoints_Test.php +++ b/projects/packages/sync/tests/php/REST_Endpoints_Test.php @@ -269,7 +269,10 @@ public function test_sync_clear_queue() { $user = wp_get_current_user(); $user->add_cap( 'manage_options' ); - $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); + set_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME, time() ); + + $request = new WP_REST_Request( 'POST', '/jetpack/v4/sync/clear-queue' ); + $request->set_header( 'Content-Type', 'application/json' ); $response = $this->server->dispatch( $request ); $data = $response->get_data(); @@ -278,6 +281,7 @@ public function test_sync_clear_queue() { $this->assertEquals( 200, $response->get_status() ); $this->assertTrue( $data['success'] ); $this->assertEquals( 'sync', $data['queue'] ); + $this->assertFalse( get_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME ) ); } /** @@ -301,7 +305,7 @@ public static function endpoint_provider() { array( 'sync/data-check', 'GET', null ), array( 'sync/data-histogram', 'POST', null ), array( 'sync/locks', 'DELETE', null ), - array( 'sync/clear-queue', 'POST', '{ "queue": "sync" }' ), + array( 'sync/clear-queue', 'POST', null ), ); } From 94595cd728f53f61e641ac7930ea049fe915cefe Mon Sep 17 00:00:00 2001 From: Karen Attfield Date: Wed, 25 Feb 2026 12:22:17 +0000 Subject: [PATCH 7/7] Simplify endpoint response now that the queue is known --- projects/packages/sync/src/class-rest-endpoints.php | 1 - projects/packages/sync/tests/php/REST_Endpoints_Test.php | 1 - 2 files changed, 2 deletions(-) diff --git a/projects/packages/sync/src/class-rest-endpoints.php b/projects/packages/sync/src/class-rest-endpoints.php index 521dc7cf00e8..10ca265f9e87 100644 --- a/projects/packages/sync/src/class-rest-endpoints.php +++ b/projects/packages/sync/src/class-rest-endpoints.php @@ -838,7 +838,6 @@ public static function clear_queue() { return rest_ensure_response( array( 'success' => true, - 'queue' => 'sync', ) ); } diff --git a/projects/packages/sync/tests/php/REST_Endpoints_Test.php b/projects/packages/sync/tests/php/REST_Endpoints_Test.php index 7efcc39a7962..079f82b594fb 100644 --- a/projects/packages/sync/tests/php/REST_Endpoints_Test.php +++ b/projects/packages/sync/tests/php/REST_Endpoints_Test.php @@ -280,7 +280,6 @@ public function test_sync_clear_queue() { $this->assertEquals( 200, $response->get_status() ); $this->assertTrue( $data['success'] ); - $this->assertEquals( 'sync', $data['queue'] ); $this->assertFalse( get_transient( Sender::TEMP_SYNC_DISABLE_TRANSIENT_NAME ) ); }