1. Developer Tutorials
  2. Extending API Caching for new API endpoints

Extending API Caching for new API endpoints

In this tutorial, you will learn how to add your custom API endpoints into the BuddyBoss API Caching system, for improving the performance of your app. For more information about how API Caching works, make sure to watch our API Caching tutorial. You may want to reference the BuddyBoss App API and the BuddyBoss Platform API, which are both used in the app.

This tutorial assumes you have already created your own custom API endpoint(s). Refer to our tutorial explaining how to write API endpoints for more information. Once you have registered your custom API endpoint, you can extend the BuddyBoss API Caching mechanism for your new endpoint by following the steps in this tutorial.

You can optionally skip to the “Example Plugins” section at the end of the article, for an example plugin setup that you can quickly test with.

Note: This tutorial requires BuddyBoss App Plugin v1.0.4 or higher.

Adding Endpoints into the Cache

1. Create one class file and extend ‘BuddyBoss\Performance\Integration\Integration_Abstract’

use BuddyBoss\Performance\Integration\Integration_Abstract;

class <ClassName> extends Integration_Abstract {

	public function set_up() {
		// TODO: Implement set_up() method.
	}
}

2. Register an integration for extending functionality.

$this->register( '<integration_name>' );

3. Register an option for the API Caching settings. The option will appear at BuddyBoss App > Settings > API Caching.

Slug 	 		: Slug for setting field
label 	 		: Label for setting field
label_checkbox 	 	: Text  for setting field
default_enabled 	: endpoint cache, if it should be enabled by default or not
public function register_setting( $settings ) {
	$settings[] = array(
		'slug'            => 'book',
		'label'           => __( 'Books', 'buddyboss-app' ),
		'label_checkbox'  => __( 'Cache Books', 'buddyboss-app' ),
		'default_enabled' => true,
	);

	return $settings;
}

add_filter( 'bbapp_admin_performance_custom_setting', array( $this, 'register_setting' ) );

4. Check if the ‘API Performance’ component is enabled or not before adding the endpoint to the cache.

$is_component_active = BuddyBoss\Performance\Helper::instance()->get_app_settings( 'cache_component', 'buddyboss-app' );

5. If an option was registered in Step 3, check the endpoint’s option before adding the endpoint to the cache.

$settings = Helper::instance()->get_app_settings( 'cache_<slug>', 'buddyboss-app' );

6. Once the integration has been registered, add the endpoint to the cache.

Endpoint 	: Endpoint URL like 'wp/v2/books'
Expire 		: Time in seconds to specify when cache will auto expire
Args		: Other arguments
Deep_cache 	: If result of the endpoint should be cached individually or cached as one entity. This option will be explained in detail below.
$this->cache_endpoint( $endpoint, $expire, $args = array(), $deep_cache = false );

For a single endpoint, you can add $endpoint in a format similar to this:

buddyboss-app/learndash/v1/courses/<id>

Then the Cache will create a cache key like <integration_name>_<id>. This Cache key will be used later to purge the cache.

Example:

// Endpoint-1: wp-json/buddyboss-app/learndash/v1/courses.
$this->cache_endpoint(
	'buddyboss-app/learndash/v1/courses',
	Cache::instance()->month_in_seconds * 60,
	array(),
	false
);

// Endpoint-2: wp-json/buddyboss-app/learndash/v1/courses/<id>.
$this->cache_endpoint(
	'buddyboss-app/learndash/v1/courses/<id>',
	Cache::instance()->month_in_seconds * 60,
	array(),
	false
);

Purging Cache for Endpoint

Now that the cache has been created, the most important part is to purge it, otherwise, it will provide incorrect/expired data to users.

7. To purge the cache, hook the below function with every action on which the endpoint response will be updated.

  • To remove list endpoint cache, use this method:
BuddyBoss\Performance\Cache::instance()->purge_by_group( $integration_name );
  • To remove a single endpoint cache event, use this method:
BuddyBoss\Performance\Cache::instance()->purge_by_group( $integration_name . '_' . $item_id   );

Note that $integration_name is the value we registered in Step 2.

  • To remove all cache related to the integration, use this method:
BuddyBoss\Performance\Cache::instance()->purge_by_component( $integration_name );

Deep Cache Integration

Before implementing everything, it will be very helpful for you to know how to take advantage of our “Deep Cache” functionality. Deep Cache is primarily used for directory page endpoints, where we are storing a separate cache for each item listed in a directory page (Activity, Forums, etc). When data changes for a single item in the list of items on the page, we can purge just the single item instead of purging all items on the page.

There are two types of endpoints:

  • List endpoint  -> return list of items. Example : /forum
  • Single endpoint  -> return single item. Example: /forums/<forum_id>

For List endpoints, we are storing two types of cache details for each endpoint request:

  • We are extracting item IDs from the response and storing them as a cache with the group name ‘Integration_name’
  • We are storing each item of the response as a separate cache with ‘integration_name’ and item ID as the group name.

With this type of mechanism, we are not required to purge the cache entry of all items of the ‘list endpoint’ response just because a single item’s response changed. This allows us to reduce database entries and processing. 

While fetching data, we are preparing hybrid responses. We fetch new data only for updated items, and for the rest of the items, we use data from the cache. By doing this, data fetching will be fast since the process only needs to load a single updated item. 

To enable deep cache for an endpoint, pass the following arguments upon adding the endpoint to the cache in Step 3 earlier.

  • Pass Deep_cache as true
  • Pass the following argument as Args:
Unique_id	: This should be the key value of the unique field in the endpoint response. Default value is 'id'.
Include_param	: Include parameter name to fetch single item. Default value is 'include'.

Note: Unique_id will be used as a suffix for the integration name, to store the single item cache. We added this param because a different endpoint might have a different unique key to store the cache, so with this dynamic solution, we can use one argument for it.

To fetch a single updated item, use the same endpoint, passing item ID as the ‘include’ parameter. If you want to use another parameter instead of ‘include’, then you can pass that value with the argument ‘include_param’ in Args.

Example:

$this->cache_endpoint(
	'buddyboss-app/learndash/v1/courses',
	Cache::instance()->month_in_seconds * 60,
	array(
		'unique_id'         => 'id',
	),
	true
);

Note: With Deep Cache, there is no need to purge the cache for list endpoints on every event. You should only purge the cache on those events with response items that need to update the list. Examples include adding or deleting items, changing the order of items, etc.

To delete a single item endpoint cache, use integration item as <integration_name>_<id>

Load Performance Class at MU Level

For performance, we recommend loading your plugin from the WordPress must-use plugins directory.

MU plugins are part of the first hook of WordPress, loading before all other WordPress plugins. This allows the API Caching code to load before the rest of WordPress.

With this method, we can achieve extremely fast responses when pulling data from the cache. This means that any custom code related to performance should be loaded first at the MU level. Otherwise, you will need to wait for all WordPress plugins to initialize before receiving a response from the cache, which could take multiple seconds.

You can choose to store all of your caching code in your MU plugin, or you can just use the MU plugin as a loader file, which then references another file from your main plugin that contains most of the caching logic (this is how BuddyBoss App plugin works). The advantage to the second option is that you can auto-update a normal WordPress plugin whenever your caching logic changes, whereas an MU plugin needs to be updated manually.

To load the class you created in Step 1 earlier at the MU level, use the template file provided below. The plugin information must be updated. After doing so, upload this plugin file into the ‘mu-plugins’ directory on your WordPress site.

<?php
/**
 * Plugin Name: {add your own}
 * Description: {add your own}
 * Version: 1.0.0
 * Author: {add your own}
 * Author URI: {add your own}
 */

if ( ! defined( 'ABSPATH' ) ) {
	die();
}

if ( ! function_exists( 'bbapp_custom_performance_load' ) ) {

	/**
	 * Load the mu level code.
	 */
	function bbapp_custom_performance_load() {
		// Load and initialise your performance classes here.
	}

	add_action( 'rest_cache_loaded', 'bbapp_custom_performance_load', 40 );
}

Example Plugins

You can upload both of the PHP template files below, the first as an MU plugin and the second as a regular plugin, to add the “Books” custom post type into the API Cache, which can be seen at BuddyBoss App > Settings > API Caching. Make sure to use both plugins!

Note: For this to actually work in your app, we are assuming you have also already registered a “book” custom post type in WordPress. Alternatively, you can adjust this code to use your own custom post type.

Must Use Plugin File

buddyboss-custom-api-caching-mu.php

Make sure to upload this plugin into the must-use plugins directory of your WordPress site. If the name or location of the regular plugin file changes, make sure to update its reference in this file.

<?php
/**
 * Plugin Name: BuddyBoss Custom API Caching Must-Use
 * Description: Must-Use plugin for BuddyBoss App to extend API Caching for custom code
 * Version: 1.0.0
 * Author: {add your own}
 * Author URI: {add your own}
 *
 * @package BuddyBoss\Performance
 */
 
if ( ! defined( 'ABSPATH' ) ) {
    die();
}
 
if ( ! function_exists( 'bbapp_custom_performance_load' ) ) {
 
    /**
     * Load the mu level code.
     */
    function bbapp_custom_performance_load() {
        if ( file_exists( WP_PLUGIN_DIR . '/buddyboss-custom-performance-cache.php' ) ) {
            require_once WP_PLUGIN_DIR . '/buddyboss-custom-performance-cache.php';
 
            \BuddyBossApp\Custom\Performance\Book::instance();
        }
    }
 
    add_action( 'rest_cache_loaded', 'bbapp_custom_performance_load', 40 );
}

Regular Plugin File

buddyboss-custom-performance-cache.php

Upload this file into the plugins directory in your WordPress site. This file contains all of the caching logic and is referenced from the MU plugin. If you change the name of this file, make sure to update the reference to this file in the MU plugin.

If you have a larger plugin containing the rest of your custom code, you could put this file into that plugin somewhere, and then update the reference in the MU plugin to point to the new location of this file. If doing this, delete the plugin header information from this file (lines 1-11).

<?php
/**
 * Plugin Name: BuddyBoss Custom API Performance Cache
 * Description: {add your own}
 * Version: 1.0.0
 * Author: {add your own}
 * Author URI:  {add your own}
 * 
 * @package BuddyBoss\Performance
 */

/**
 * Class file to extend performance for book endpoint.
 */

namespace BuddyBossApp\Custom\Performance;

use BuddyBoss\Performance\Cache;
use BuddyBoss\Performance\Integration\Integration_Abstract;
use BuddyBoss\Performance\Helper;

/**
 * Class Book
 * @package BuddyBossApp\Custom\Performance
 */
class Book extends Integration_Abstract {

	public function set_up() {

		$this->register( 'book' );

		add_filter( 'bbapp_admin_performance_custom_setting', array( $this, 'register_setting' ) );

		// NOTE : Getting admin settings to toggle api cache.
		$is_component_active     = Helper::instance()->get_app_settings( 'cache_component', 'buddyboss-app' );
		$settings                = Helper::instance()->get_app_settings( 'cache_book', 'buddyboss-app' );
		$cache_support_book = isset( $is_component_active ) && isset( $settings ) ? ( $is_component_active && $settings ) : true;

		if ( $cache_support_book ) {

			// Endpoint-1: wp-json/wp/v2/book.
			$this->cache_endpoint(
				'wp/v2/book',
				Cache::instance()->month_in_seconds * 60,
				array(
					'unique_id' => 'id',
				),
				true
			);

			// Endpoint-2: wp-json/wp/v2/book/<id>.
			$this->cache_endpoint(
				'wp/v2/book/<id>',
				Cache::instance()->month_in_seconds * 60,
				array(),
				false
			);
		}

		add_action( 'save_post_book', array( $this, 'event_purge_cache' ) );
		add_action( 'edit_post_book', array( $this, 'event_purge_cache' ) );
		add_action( 'trashed_post', array( $this, 'event_purge_cache' ) );
		add_action( 'untrashed_post', array( $this, 'event_purge_cache' ) );
		add_action( 'deleted_post', array( $this, 'event_purge_cache' ) );

		add_action( 'book_bookmarked', array( $this, 'event_book_bookmarked' ) );
	}

	public function register_setting( $settings ) {
		$settings[] = array(
			'slug'            => 'book',
			'label'           => __( 'Books', 'buddyboss-app' ),
			'label_checkbox'  => __( 'Cache Books', 'buddyboss-app' ),
			'default_enabled' => true,
		);

		return $settings;
	}

	public function event_purge_cache( $book_id ) {
		Cache::instance()->purge_by_group( 'book' );
		Cache::instance()->purge_by_group( 'book_' . $book_id );
	}

	public function event_book_bookmarked( $book_id ) {
		/**
		 * I enabled deep cache and when user bookmarked any book my book list is not updating
		 * So here I don't need to purge list endpoint cache.
		 */
		Cache::instance()->purge_by_group( 'book_' . $book_id );
	}
}

Questions?

We're always happy to help with questions you might have! Search our documentation, contact support, or connect with our sales team.