Skip to content

Commit 66dbef9

Browse files
authored
Purge Outbox Items on Schedule (#1288)
* WIP: Purge Outbox Items on Schedule * Keep at least 20 posts Also adds unit tests * Changelog
1 parent 7c26b4b commit 66dbef9

File tree

5 files changed

+98
-0
lines changed

5 files changed

+98
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
* Batch Outbox-Processing.
1313
* Outbox processed events get logged in Stream and show any errors returned from inboxes.
14+
* Outbox items older than 6 months will be purged to avoid performance issues.
1415
* REST API endpoints for likes and shares.
1516

1617
### Changed

includes/class-migration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ public static function maybe_migrate() {
179179
\wp_schedule_single_event( \time() + 15, 'activitypub_upgrade', array( 'create_comment_outbox_items' ) );
180180
add_action( 'init', 'flush_rewrite_rules', 20 );
181181
}
182+
if ( \version_compare( $version_from_db, 'unreleased', '<' ) ) {
183+
Scheduler::register_schedules();
184+
}
182185

183186
/*
184187
* Add new update routines above this comment. ^

includes/class-scheduler.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static function init() {
3333

3434
\add_action( 'activitypub_async_batch', array( self::class, 'async_batch' ), 10, 99 );
3535
\add_action( 'activitypub_reprocess_outbox', array( self::class, 'reprocess_outbox' ) );
36+
\add_action( 'activitypub_outbox_purge', array( self::class, 'purge_outbox' ) );
3637

3738
\add_action( 'post_activitypub_add_to_outbox', array( self::class, 'schedule_outbox_activity_for_federation' ) );
3839
\add_action( 'post_activitypub_add_to_outbox', array( self::class, 'schedule_announce_activity' ), 10, 4 );
@@ -69,6 +70,10 @@ public static function register_schedules() {
6970
if ( ! \wp_next_scheduled( 'activitypub_reprocess_outbox' ) ) {
7071
\wp_schedule_event( time(), 'hourly', 'activitypub_reprocess_outbox' );
7172
}
73+
74+
if ( ! wp_next_scheduled( 'activitypub_outbox_purge' ) ) {
75+
wp_schedule_event( time(), 'daily', 'activitypub_outbox_purge' );
76+
}
7277
}
7378

7479
/**
@@ -80,6 +85,7 @@ public static function deregister_schedules() {
8085
wp_unschedule_hook( 'activitypub_update_followers' );
8186
wp_unschedule_hook( 'activitypub_cleanup_followers' );
8287
wp_unschedule_hook( 'activitypub_reprocess_outbox' );
88+
wp_unschedule_hook( 'activitypub_outbox_purge' );
8389
}
8490

8591
/**
@@ -199,6 +205,39 @@ public static function reprocess_outbox() {
199205
}
200206
}
201207

208+
/**
209+
* Purge outbox items based on a schedule.
210+
*/
211+
public static function purge_outbox() {
212+
$total_posts = (int) wp_count_posts( Outbox::POST_TYPE )->publish;
213+
if ( $total_posts <= 20 ) {
214+
return;
215+
}
216+
217+
$days = 180; // TODO: Replace with a setting.
218+
$timezone = new \DateTimeZone( 'UTC' );
219+
$date = new \DateTime( 'now', $timezone );
220+
221+
$date->sub( \DateInterval::createFromDateString( "$days days" ) );
222+
223+
$post_ids = get_posts(
224+
array(
225+
'post_type' => Outbox::POST_TYPE,
226+
'post_status' => 'any',
227+
'fields' => 'ids',
228+
'date_query' => array(
229+
array(
230+
'before' => $date->format( 'Y-m-d' ),
231+
),
232+
),
233+
)
234+
);
235+
236+
foreach ( $post_ids as $post_id ) {
237+
\wp_delete_post( $post_id, true );
238+
}
239+
}
240+
202241
/**
203242
* Asynchronously runs batch processing routines.
204243
*

readme.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ For reasons of data protection, it is not possible to see the followers of other
133133

134134
* Added: Batch Outbox-Processing.
135135
* Added: Outbox processed events get logged in Stream and show any errors returned from inboxes.
136+
* Added: Outbox items older than 6 months will be purged to avoid performance issues.
136137
* Added: REST API endpoints for likes and shares.
137138
* Changed: Increased probability of Outbox items being processed with the correct author.
138139
* Changed: Enabled querying of Outbox posts through the REST API to improve troubleshooting and debugging.

tests/includes/class-test-scheduler.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,58 @@ function ( $event ) use ( &$scheduled_time ) {
194194
wp_delete_post( $pending_id, true );
195195
remove_all_filters( 'schedule_event' );
196196
}
197+
198+
/**
199+
* Test purge_outbox method with more than 20 posts.
200+
*
201+
* @covers ::purge_outbox
202+
*/
203+
public function test_purge_outbox_more_than_20_posts() {
204+
// Create 25 posts, 5 older than 6 months.
205+
self::factory()->post->create_many(
206+
25,
207+
array(
208+
'post_type' => Outbox::POST_TYPE,
209+
'post_status' => 'publish',
210+
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '-1 month' ) ),
211+
)
212+
);
213+
self::factory()->post->create_many(
214+
5,
215+
array(
216+
'post_type' => Outbox::POST_TYPE,
217+
'post_status' => 'publish',
218+
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '-7 months' ) ),
219+
)
220+
);
221+
222+
Scheduler::purge_outbox();
223+
wp_cache_delete( _count_posts_cache_key( Outbox::POST_TYPE ), 'counts' );
224+
225+
// Assert that 5 posts were deleted, leaving 25.
226+
$this->assertEquals( 25, wp_count_posts( Outbox::POST_TYPE )->publish );
227+
}
228+
229+
/**
230+
* Test purge_outbox method with 20 or fewer posts.
231+
*
232+
* @covers ::purge_outbox
233+
*/
234+
public function test_purge_outbox_20_or_fewer_posts() {
235+
// Create 20 posts, all older than 6 months.
236+
self::factory()->post->create_many(
237+
20,
238+
array(
239+
'post_type' => Outbox::POST_TYPE,
240+
'post_status' => 'publish',
241+
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '-7 months' ) ),
242+
)
243+
);
244+
245+
Scheduler::purge_outbox();
246+
wp_cache_delete( _count_posts_cache_key( Outbox::POST_TYPE ), 'counts' );
247+
248+
// Assert that no posts were deleted.
249+
$this->assertEquals( 20, wp_count_posts( Outbox::POST_TYPE )->publish );
250+
}
197251
}

0 commit comments

Comments
 (0)