wp-graphql / wp-graphql-smart-cache

Smart Caching & Cache Invalidation for WPGraphQL
60 stars 15 forks source link

Invalidate caches when settings (options) change #158

Open jasonbahl opened 2 years ago

jasonbahl commented 2 years ago

Currently, WPGraphQL Smart Cache does not invalidate any caches when settings/options are changed (meaning values stored in the wp_options table).

Refactor WPGraphQL core to treat options as models/nodes

This will allow WPGraphQL Smart Cache to properly map the setting groups to the cache map in the same way other nodes (posts, terms, etc) are mapped.

Direct Queries for Options should be be evicted when values change

The goal here is to ensure queries for direct option values are invalidated when said values are updated.

For example, a query such as:

{
  generalSettings {
    url
  }
}

should be evicted when the general settings url option is updated.

Queries for options should be mapped in the cache map. Currently this isn't happening because Options aren't using the DataLoader/Model/Node pattern (see above issue).

Once Options are refactored to use that pattern, this should probably be resolved already?

"Side-effect" evictions should be triggered when option values change

When options in WordPress are changed, they often have "side effects" that aren't always straight forward or centrally defined anywhere in WordPress core.

For example, changing rewrite rules affects anything with a URI, and we should probably call purge_all in response to said change.

Or changing the page_on_front value would affect both the new and old page, and we should call purge on any queries that queried for the old or new page node. We probably don't need to purge all when this option changes, because we usually know the impact of this change.

Since each option is treated differently, I believe we should identify a filterable list of options to track in response to the updated_option hook, and what callback should happen in response to said action.

Something to the tune of (pseudo code):

$tracked_options = [
  'blogdescription' => [
    // this callback would run when `update_option` is called, and the 
    // option name matches the name above, in this case 'blogdescription'
    'callback' => function( $option, $old_value, $value ) { 
       // purge queries that asked for this setting?
    },
  ],
  'permalink_structure' => [
     'callback' => function( $option, $old_value, $value ) { 
       // purge all
    },
  ],
  'stylesheet' => [
    'callback' => function( $option, $old_value, $value ) { 
       // purge all (when themes change)
    },
  ],
  'page_on_front' => [ 
     'callback' => function( $option, $old_value, $value ) { 
       // purge queries that included the node associated with the `$old_value` ID and the node associated with the `$value` ID
       // ex: a query for `{ pages { nodes { id, isFrontPage } } }` should have been evicted when this setting was changed 
    },
  ]
];

// filter the tracked options so plugin/theme authors can hook in and add to the list or modify things in the list
$filtered_tracked_options = apply_filters( 'graphql_smart_cache_tracked_options', $tracked_options );

The above are examples of some settings that should purge different caches when the values are changed. I think we need to do some case-by-case analysis of what should happen for each setting that WordPress core has built-in, and set a pattern for how 3rd party plugin/theme developers can hook in and tie their options to these evictions.

Future Idea I don't want to get lost

In the same way WPGraphQL respects additional fields on the register_post_type and register_taxonomy calls (such as show_in_graphql, graphql_single_name, graphql_plural_name) it would be nice if WPGraphQL could look for fields on the register_setting calls and then use that to determine which settings should be added to the filtered list above.

For example, if I were do do something like so (pseudo code):

register_setting( 'myGroupName', 'mySettingName', [
  'type' => 'string',
  ...
  'graphql_cache_invalidation' => [
     'callback' => function( $option, $old_value, $value ) { // do something when graphql smart cache is looking at this options callback }
  ]
] );
eliyadzz commented 2 years ago

Any news on this?

jasonbahl commented 2 years ago

@eliyadzz not yet. Would you be interested in contributing to make this happen?

marco910 commented 4 months ago

We would really appreciate it if this feature could get integrated into the plugin. We're working a lot with option page (also those created with the acf_add_options_page () ACF function) in headless WordPress, so this would be very handy