Skip to content

Commit

Permalink
Switch to triggering invalidation of page cache via scheduled event
Browse files Browse the repository at this point in the history
  • Loading branch information
westonruter committed Nov 14, 2024
1 parent 41a1526 commit eee4761
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 65 deletions.
1 change: 0 additions & 1 deletion plugins/embed-optimizer/tests/test-hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public function test_embed_optimizer_add_hooks(): void {
$this->assertSame( 10, has_action( 'od_init', 'embed_optimizer_init_optimization_detective' ) );
$this->assertSame( 10, has_action( 'wp_head', 'embed_optimizer_render_generator' ) );
$this->assertSame( 10, has_action( 'wp_loaded', 'embed_optimizer_add_non_optimization_detective_hooks' ) );
$this->assertSame( 10, has_action( 'od_url_metric_stored', 'od_clean_queried_object_cache_for_stored_url_metric' ) );
}

/**
Expand Down
1 change: 0 additions & 1 deletion plugins/optimization-detective/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@
OD_URL_Metrics_Post_Type::add_hooks();
add_action( 'wp', 'od_maybe_add_template_output_buffer_filter' );
add_action( 'wp_head', 'od_render_generator_meta_tag' );
add_action( 'od_url_metric_stored', 'od_clean_queried_object_cache_for_stored_url_metric' );
33 changes: 15 additions & 18 deletions plugins/optimization-detective/storage/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ function od_handle_rest_request( WP_REST_Request $request ) {
}
$post_id = $result;

// Schedule an event in 10 minutes to trigger an invalidation of the page cache (hopefully).
$cache_purge_post_id = $request->get_param( 'cache_purge_post_id' );
if ( is_int( $cache_purge_post_id ) && false === wp_next_scheduled( 'od_trigger_page_cache_invalidation', array( $cache_purge_post_id ) ) ) {
wp_schedule_single_event(
time() + 10 * MINUTE_IN_SECONDS,
'od_trigger_page_cache_invalidation',
array( $cache_purge_post_id )
);
}

/**
* Fires whenever a URL Metric was successfully stored.
*
Expand Down Expand Up @@ -235,30 +245,17 @@ function od_handle_rest_request( WP_REST_Request $request ) {
}

/**
* Cleans the cache for the queried object when it has a new URL Metric stored.
* Triggers actions for page caches to invalidate their caches related to the supplied cache purge post ID.
*
* This is intended to flush any page cache for the URL after the new URL Metric was submitted so that the optimizations
* which depend on that URL Metric can start to take effect. Furthermore, when a submitted URL Metric results in a full
* sample of URL Metric groups, then flushing the page cache will allow the next request to omit the detection script
* module altogether. When a page cache holds onto a cached page for a long time (e.g. a week), this will result in
* the stored URL Metrics being stale if they have the default freshness TTL of 1 day. Nevertheless, if no changes have
* been applied to a cached page then those stale URL Metrics should continue to result in an optimized page.
*
* This assumes that a page caching plugin flushes the page cache for a queried object via `clean_post_cache`,
* `clean_term_cache`, and `clean_user_cache` actions. Other actions may make sense to trigger as well as can be seen in
* {@link https://github.com/pantheon-systems/pantheon-advanced-page-cache/blob/e3b5552/README.md?plain=1#L314-L356}.
* which depend on that URL Metric can start to take effect.
*
* @since n.e.x.t
* @access private
*
* @param OD_URL_Metric_Store_Request_Context $context Context.
* @param int $cache_purge_post_id Cache purge post ID.
*/
function od_clean_queried_object_cache_for_stored_url_metric( OD_URL_Metric_Store_Request_Context $context ): void {

$cache_purge_post_id = $context->request->get_param( 'cache_purge_post_id' );
if ( ! is_int( $cache_purge_post_id ) ) {
return;
}

function od_trigger_page_cache_invalidation( int $cache_purge_post_id ): void {
$post = get_post( $cache_purge_post_id );
if ( ! ( $post instanceof WP_Post ) ) {
return;
Expand Down
110 changes: 65 additions & 45 deletions plugins/optimization-detective/tests/storage/test-rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static function ( array $properties ): array {
*
* @covers ::od_register_endpoint
* @covers ::od_handle_rest_request
* @covers ::od_clean_queried_object_cache_for_stored_url_metric
* @covers ::od_trigger_page_cache_invalidation
*/
public function test_rest_request_good_params( Closure $set_up ): void {
$stored_context = null;
Expand All @@ -89,15 +89,9 @@ function ( OD_URL_Metric_Store_Request_Context $context ) use ( &$stored_context

$valid_params = $set_up();

$all_hook_callback_args = array();
add_action(
'all',
static function ( string $hook, ...$args ) use ( &$all_hook_callback_args ): void {
$all_hook_callback_args[ $hook ][] = $args;
},
10,
PHP_INT_MAX
);
if ( isset( $valid_params['cache_purge_post_id'] ) ) {
$this->assertFalse( wp_next_scheduled( 'od_trigger_page_cache_invalidation', array( $valid_params['cache_purge_post_id'] ) ) );
}

$this->assertCount( 0, get_posts( array( 'post_type' => OD_URL_Metrics_Post_Type::SLUG ) ) );
$request = $this->create_request( $valid_params );
Expand Down Expand Up @@ -126,43 +120,14 @@ static function ( string $hook, ...$args ) use ( &$all_hook_callback_args ): voi

$this->assertInstanceOf( OD_URL_Metric_Store_Request_Context::class, $stored_context );

// Now check that od_clean_queried_object_cache_for_stored_url_metric() cleaned caches as expected.
// Now check that od_trigger_page_cache_invalidation() cleaned caches as expected.
$this->assertSame( $url_metrics[0]->jsonSerialize(), $stored_context->url_metric->jsonSerialize() );
$cache_purge_post_id = $stored_context->request->get_param( 'cache_purge_post_id' );
if ( null !== $cache_purge_post_id ) {
$this->assertArrayHasKey( 'clean_post_cache', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['clean_post_cache'] as $args ) {
if ( $args[0] === $cache_purge_post_id ) {
$this->assertInstanceOf( WP_Post::class, $args[1] );
$this->assertSame( $cache_purge_post_id, $args[1]->ID );
$found = true;
}
}
$this->assertTrue( $found, 'Expected clean_post_cache to have been fired for the post queried object.' );

$this->assertArrayHasKey( 'transition_post_status', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['transition_post_status'] as $args ) {
$this->assertInstanceOf( WP_Post::class, $args[2] );
if ( $args[2]->ID === $cache_purge_post_id ) {
$this->assertSame( $args[2]->post_status, $args[0] );
$this->assertSame( $args[2]->post_status, $args[1] );
$found = true;
}
}
$this->assertTrue( $found, 'Expected transition_post_status to have been fired for the post queried object.' );

$this->assertArrayHasKey( 'save_post', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['save_post'] as $args ) {
if ( $args[0] === $cache_purge_post_id ) {
$this->assertInstanceOf( WP_Post::class, $args[1] );
$this->assertSame( $cache_purge_post_id, $args[1]->ID );
$found = true;
}
}
$this->assertTrue( $found, 'Expected save_post to have been fired for the post queried object.' );

if ( isset( $valid_params['cache_purge_post_id'] ) ) {
$scheduled = wp_next_scheduled( 'od_trigger_page_cache_invalidation', array( $valid_params['cache_purge_post_id'] ) );
$this->assertIsInt( $scheduled );
$this->assertGreaterThan( time(), $scheduled );
}
}

Expand Down Expand Up @@ -618,6 +583,61 @@ static function () use ( $breakpoint_width ): array {
$this->assertSame( 403, $response->get_status(), 'Response: ' . wp_json_encode( $response->get_data() ) );
}

/**
* Test od_trigger_page_cache_invalidation().
*
* @covers ::od_trigger_page_cache_invalidation
*/
public function test_od_trigger_page_cache_invalidation(): void {
$cache_purge_post_id = self::factory()->post->create();

$all_hook_callback_args = array();
add_action(
'all',
static function ( string $hook, ...$args ) use ( &$all_hook_callback_args ): void {
$all_hook_callback_args[ $hook ][] = $args;
},
10,
PHP_INT_MAX
);

od_trigger_page_cache_invalidation( $cache_purge_post_id );

$this->assertArrayHasKey( 'clean_post_cache', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['clean_post_cache'] as $args ) {
if ( $args[0] === $cache_purge_post_id ) {
$this->assertInstanceOf( WP_Post::class, $args[1] );
$this->assertSame( $cache_purge_post_id, $args[1]->ID );
$found = true;
}
}
$this->assertTrue( $found, 'Expected clean_post_cache to have been fired for the post queried object.' );

$this->assertArrayHasKey( 'transition_post_status', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['transition_post_status'] as $args ) {
$this->assertInstanceOf( WP_Post::class, $args[2] );
if ( $args[2]->ID === $cache_purge_post_id ) {
$this->assertSame( $args[2]->post_status, $args[0] );
$this->assertSame( $args[2]->post_status, $args[1] );
$found = true;
}
}
$this->assertTrue( $found, 'Expected transition_post_status to have been fired for the post queried object.' );

$this->assertArrayHasKey( 'save_post', $all_hook_callback_args );
$found = false;
foreach ( $all_hook_callback_args['save_post'] as $args ) {
if ( $args[0] === $cache_purge_post_id ) {
$this->assertInstanceOf( WP_Post::class, $args[1] );
$this->assertSame( $cache_purge_post_id, $args[1]->ID );
$found = true;
}
}
$this->assertTrue( $found, 'Expected save_post to have been fired for the post queried object.' );
}

/**
* Populate URL Metrics.
*
Expand Down

0 comments on commit eee4761

Please sign in to comment.