Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add garbage collection cleanup admin and cron job #227

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c4d2efa
Add garbage collection cleanup admin and cron job
markkelnar Jul 11, 2023
ebe21a2
Delete in smaller batch events instead of all posts
markkelnar Jul 12, 2023
dc3db02
bump some version numbers
markkelnar Jul 14, 2023
63d3716
Add tests for admin settings garbage collection options
markkelnar Jul 14, 2023
81b4885
Add garbage collection unit tests
markkelnar Jul 14, 2023
e9166b8
Merge remote-tracking branch 'origin/main' into feature/garbage-colle…
markkelnar Jul 14, 2023
456d979
Get age from settings value in utils class
markkelnar Jul 14, 2023
9ff1e21
Add admin editor ability to skip garbage collection per query
markkelnar Jul 14, 2023
378ebed
Add tax_query to gargage collection to ignore where docs opt out
markkelnar Jul 18, 2023
1334dfc
Rename garbage collection class
markkelnar Jul 18, 2023
025b7c7
Add groups collection for documents. Refactor garbage collection to i…
markkelnar Jul 20, 2023
f8e6a7a
fix code sniff white space
markkelnar Jul 20, 2023
72dd923
Update gc text in graphql settings to talk about groups
markkelnar Jul 20, 2023
0f7baaa
Add the word "delete" to text
markkelnar Jul 20, 2023
c99ab11
Merge remote-tracking branch 'origin/main' into feature/garbage-colle…
markkelnar Jul 21, 2023
614a874
Use garbage_collect instead of gc
markkelnar Jul 24, 2023
a55d6e9
text description change.
markkelnar Jul 24, 2023
037df6e
snake case function name
markkelnar Jul 24, 2023
5af7178
Merge remote-tracking branch 'me/feature/garbage-collect-aged-queries…
markkelnar Jul 24, 2023
55fc784
fix for consistent names
markkelnar Jul 24, 2023
514894a
enable admin quick-edit for document groups
markkelnar Jul 24, 2023
b65efd9
Merge remote-tracking branch 'origin/main' into feature/garbage-colle…
markkelnar Jul 25, 2023
22cf8f5
Merge commit '9a023bfd9243b02f80861c56fab9c20d04c4a79a' into feature/…
jasonbahl Jul 25, 2023
35168d9
re-add allow-plugin for codesniffer-installer
markkelnar Jul 26, 2023
294bbee
Merge remote-tracking branch 'me/feature/garbage-collect-aged-queries…
markkelnar Jul 26, 2023
19923e0
add filter for garbage collect recurrence
markkelnar Jul 26, 2023
2495e72
merge fixes
markkelnar Jul 28, 2023
3a7f141
composer update
markkelnar Jul 28, 2023
92dbc42
Merge branch 'main' into feature/garbage-collect-aged-queries
jasonbahl Aug 9, 2023
7923d53
fix phpstan suggestions
markkelnar Aug 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
jasonbahl marked this conversation as resolved.
Show resolved Hide resolved
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',
jasonbahl marked this conversation as resolved.
Show resolved Hide resolved
'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,
markkelnar marked this conversation as resolved.
Show resolved Hide resolved
'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 : '';
}
}