Skip to content

Commit

Permalink
Merge pull request #227 from markkelnar/feature/garbage-collect-aged-…
Browse files Browse the repository at this point in the history
…queries

feat: Add garbage collection cleanup admin and cron job
  • Loading branch information
markkelnar authored Aug 9, 2023
2 parents d832372 + 7923d53 commit 61c4d7c
Show file tree
Hide file tree
Showing 13 changed files with 494 additions and 111 deletions.
4 changes: 2 additions & 2 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ MYSQL_USER=${DB_USER}
MYSQL_PASSWORD=${DB_PASSWORD}

# docker container env vars
WP_VERSION=5.9
PHP_VERSION=8.0
WP_VERSION=6.1
PHP_VERSION=8.1
WPGRAPHQL_VERSION=latest
DATA_DUMP_DIR=/var/www/html/wp-content/plugins/wp-graphql-smart-cache/tests/_data
4 changes: 2 additions & 2 deletions .env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ MYSQL_USER=${DB_USER}
MYSQL_PASSWORD=${DB_PASSWORD}

# docker container env vars
WP_VERSION=5.9
PHP_VERSION=8.0
WP_VERSION=6.1
PHP_VERSION=8.1
WPGRAPHQL_VERSION=latest
DATA_DUMP_DIR=/var/www/html/wp-content/plugins/wp-graphql-smart-cache/tests/_data
16 changes: 9 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
"wp-graphql/wp-graphql-testcase": "*",
"squizlabs/php_codesniffer": "^3.6",
"phpcompatibility/phpcompatibility-wp": "*",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
"wp-coding-standards/wpcs": "^2.3",
"lucatume/wp-browser": "^3.0",
"codeception/module-asserts": "^1.3",
"codeception/module-asserts": "^1.3.1",
"codeception/module-phpbrowser": "^1.0",
"codeception/module-webdriver": "^1.2",
"codeception/module-db": "^1.1",
Expand Down Expand Up @@ -75,9 +74,12 @@
]
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
}
}
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"phpstan/extension-installer": true
}
},
"require": {
"appsero/client": "^1.2"
}
}
97 changes: 49 additions & 48 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ services:
local:

app_db:
image: mariadb:10.2
image: mariadb:10.11
env_file:
- .env.dist
ports:
Expand All @@ -46,7 +46,7 @@ services:
local:

testing_db:
image: mariadb:10.2
image: mariadb:10.11
env_file:
- .env.testing
ports:
Expand Down
44 changes: 44 additions & 0 deletions src/Admin/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,50 @@ function () {
]
);

register_graphql_settings_field(
'graphql_persisted_queries_section',
[
'name' => 'query_garbage_collect',
'label' => __( 'Delete Old Queries', 'wp-graphql-smart-cache' ),
'desc' => __( 'Toggle on to enable garbage collection (delete) of saved queries older than number of days specified below. Queries that are tagged in a "Group" will be excluded from garbage collection.', 'wp-graphql-smart-cache' ),
'type' => 'checkbox',
'default' => 'off',
'sanitize_callback' => function ( $value ) {
/**
* When enable garbage collection,
* schedule the garbage collection action/event to run once daily.
* Otherwise remove it.
*/
if ( 'on' === $value ) {
if ( ! wp_next_scheduled( 'wpgraphql_smart_cache_query_garbage_collect' ) ) {
// Add scheduled job to run
$event_recurrence = apply_filters( 'wpgraphql_smart_cache_query_garbage_collect_recurrence', 'daily' );
wp_schedule_event( time() + 60, $event_recurrence, 'wpgraphql_smart_cache_query_garbage_collect' );
}
} else {
wp_clear_scheduled_hook( 'wpgraphql_smart_cache_query_garbage_collect' );
}
return $value;
},
]
);

register_graphql_settings_field(
'graphql_persisted_queries_section',
[
'name' => 'query_garbage_collect_age',
'desc' => __( 'Age, in number of days, of saved query when it will be removed', 'wp-graphql-smart-cache' ),
'type' => 'number',
'default' => '30',
'sanitize_callback' => function ( $value ) {
if ( 1 > $value || ! is_numeric( $value ) ) {
return function_exists( 'get_graphql_setting' ) ? \get_graphql_setting( 'query_garbage_collect_age', false, 'graphql_persisted_queries_section' ) : null;
}
return (int) $value;
},
]
);

// Add a tab section to the graphql admin settings page
register_graphql_settings_section(
'graphql_cache_section',
Expand Down
1 change: 0 additions & 1 deletion src/Cache/Invalidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use WPGraphQL\Model\Menu;
use WPGraphQL\SmartCache\Admin\Settings;


/**
* This class handles the invalidation of the WPGraphQL Caches
*/
Expand Down
61 changes: 61 additions & 0 deletions src/Document/GarbageCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php
/**
* Content
*
* @package Wp_Graphql_Smart_Cache
*/

namespace WPGraphQL\SmartCache\Document;

use WPGraphQL\SmartCache\Admin\Settings;
use WPGraphQL\SmartCache\Document;
use WPGraphQL\SmartCache\Document\Group;
use GraphQL\Server\RequestError;

class GarbageCollection {

/**
* @param integer $number_of_posts Number of post ids matching criteria.
*
* @return int[] Array of post ids
*/
public static function get_documents_by_age( $number_of_posts = 100 ) {
// $days_ago Posts older than this many days ago
$days_ago = get_graphql_setting( 'query_garbage_collect_age', null, 'graphql_persisted_queries_section' );
if ( 1 > $days_ago || ! is_numeric( $days_ago ) ) {
return [];
}

// Query for saved query documents that are older than age and not skipping garbage collection.
// Get documents where no group taxonmy term is set.
$wp_query = new \WP_Query(
[
'post_type' => Document::TYPE_NAME,
'post_status' => 'publish',
'posts_per_page' => $number_of_posts,
'fields' => 'ids',
'date_query' => [
[
'column' => 'post_modified_gmt',
'before' => $days_ago . ' days ago',
],
],
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
'tax_query' => [
[
'taxonomy' => Group::TAXONOMY_NAME,
'field' => 'name',
'operator' => 'NOT EXISTS',
],
],
]
);

/**
* Because 'fields' returns 'ids', this returns array of post ints. Satisfy phpstan.
*
* @var int[]
*/
return $wp_query->get_posts();
}
}
54 changes: 54 additions & 0 deletions src/Document/Group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Content
*
* @package Wp_Graphql_Smart_Cache
*/

namespace WPGraphQL\SmartCache\Document;

use WPGraphQL\SmartCache\Admin\Settings;
use WPGraphQL\SmartCache\Document;

class Group {

const TAXONOMY_NAME = 'graphql_document_group';

/**
* @return void
*/
public function init() {
register_taxonomy(
self::TAXONOMY_NAME,
Document::TYPE_NAME,
[
'description' => __( 'Tag the saved query document with other queries as a "group".', 'wp-graphql-smart-cache' ),
'labels' => [
'name' => __( 'Groups', 'wp-graphql-smart-cache' ),
'singular_name' => __( 'Group', 'wp-graphql-smart-cache' ),
],
'hierarchical' => false,
'public' => false,
'publicly_queryable' => false,
'show_admin_column' => true,
'show_in_menu' => Settings::show_in_admin(),
'show_ui' => Settings::show_in_admin(),
'show_in_quick_edit' => true,
'show_in_graphql' => true,
'graphql_single_name' => 'graphqlDocumentGroup',
'graphql_plural_name' => 'graphqlDocumentGroups',
]
);
}

/**
* Look up the first group for a post
*
* @param int $post_id The post id
* @return string
*/
public static function get( $post_id ) {
$item = get_the_terms( $post_id, self::TAXONOMY_NAME );
return ! is_wp_error( $item ) && isset( $item[0] ) && property_exists( $item[0], 'name' ) ? $item[0]->name : '';
}
}
Loading

0 comments on commit 61c4d7c

Please sign in to comment.