Skip to content

Commit

Permalink
feat: use redis to store cache
Browse files Browse the repository at this point in the history
  • Loading branch information
HitkoDev committed Nov 11, 2021
1 parent f3fe3d7 commit 8a98f8f
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 114 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ jobs:
run: |
mkdir -p breeze
rsync -a --exclude=breeze --exclude="\.*" --exclude=composer.lock --exclude=composer.json . breeze
zip -r breeze.zip breeze
zip -r breeze-redis.zip breeze
- name: Release
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
prerelease: false
files: |
breeze.zip
breeze-redis.zip
1 change: 1 addition & 0 deletions breeze.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
require_once BREEZE_PLUGIN_DIR . 'inc/functions.php';

//action to purge cache
require_once BREEZE_PLUGIN_DIR . 'inc/cache/redis-client.php';
require_once BREEZE_PLUGIN_DIR . 'inc/cache/purge-varnish.php';
require_once BREEZE_PLUGIN_DIR . 'inc/cache/purge-cache.php';
require_once BREEZE_PLUGIN_DIR . 'inc/cache/purge-per-time.php';
Expand Down
6 changes: 2 additions & 4 deletions inc/breeze-configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public function afterLoadConfigPage() {

$basic = [
'breeze-active' => (isset($_POST['cache-system']) ? '1' : '0'),
'breeze-redis-uri' => (isset($_POST['cache-redis-uri']) ? $_POST['cache-redis-uri'] : 'redis://127.0.0.1/0'),
'breeze-cross-origin' => (isset($_POST['safe-cross-origin']) ? '1' : '0'),
'breeze-ttl' => (int) $_POST['cache-ttl'],
'breeze-minify-html' => (isset($_POST['minification-html']) ? '1' : '0'),
Expand Down Expand Up @@ -759,10 +760,7 @@ public static function breeze_clean_cache() {
// Check whether we're clearing the cache for one subsite on the network.
$is_subsite = is_multisite() && !is_network_admin();

// analysis size cache
$cachepath = untrailingslashit(breeze_get_cache_base_path(is_network_admin()));

$size_cache = breeze_get_directory_size($cachepath);
$size_cache = 0;

// Analyze minification directory sizes.
$files_path = rtrim(WP_CONTENT_DIR, '/') . '/cache/breeze-minification';
Expand Down
2 changes: 1 addition & 1 deletion inc/cache/config-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ public function clean_up() {

$folder = untrailingslashit(breeze_get_cache_base_path());

if (!$wp_filesystem->delete($folder, true)) {
if (!@RedisClient::factory()->delete($folder . '/*')) {
$ret = false;
}

Expand Down
71 changes: 34 additions & 37 deletions inc/cache/execute-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

// Load helper functions.
require_once dirname(__DIR__) . '/functions.php';
require_once __DIR__ . '/redis-client.php';

if (isset($GLOBALS['breeze_config'], $GLOBALS['breeze_config']['disable_per_adminuser'])) {
$wp_cookies = ['wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_'];
Expand Down Expand Up @@ -211,11 +212,6 @@ function breeze_cache($buffer, $flags) {
if (is_404() || is_search() || post_password_required()) {
return $buffer;
}
global $wp_filesystem;
if (empty($wp_filesystem)) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}

$path = $GLOBALS['breeze_filename'];
$X1 = $GLOBALS['breeze_x1'];
Expand Down Expand Up @@ -341,8 +337,11 @@ function breeze_cache($buffer, $flags) {
]
);

$wp_filesystem->put_contents($path, $data);
$wp_filesystem->touch($path, $modified_time);
$ttl = (isset($GLOBALS['breeze_config']['cache_options']['breeze-ttl']) ? (int) $GLOBALS['breeze_config']['cache_options']['breeze-ttl'] : 0) * 60;
if ($ttl <= 0) {
$ttl = 86400;
}
RedisClient::factory()->set($path, $data, $ttl);

//set cache provider header if not exists cache file
header('Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'C');
Expand Down Expand Up @@ -406,9 +405,9 @@ function breeze_serve_cache($filename, $url_path, $X1, $opts) {
}

if (function_exists('gzencode') && !empty($GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'])) {
$file_name = md5($filename . '/index.gzip.html') . '.php';
$file_name = md5($filename . '/index.gzip.html');
} else {
$file_name = md5($filename . '/index.html') . '.php';
$file_name = md5($filename . '/index.html');
}

$blog_id_requested = isset($GLOBALS['breeze_config']['blog_id']) ? $GLOBALS['breeze_config']['blog_id'] : 0;
Expand All @@ -417,39 +416,37 @@ function breeze_serve_cache($filename, $url_path, $X1, $opts) {
$GLOBALS['breeze_filename'] = $path;
$GLOBALS['breeze_x1'] = $X1;

if (@file_exists($path)) {
$cacheFile = file_get_contents($path);
$cacheFile = @RedisClient::factory()->get($path);

if ($cacheFile != false) {
$datas = unserialize($cacheFile);
foreach ($datas['headers'] as $data) {
header($data['name'] . ': ' . $data['value']);
}
//set cache provider header
header('Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'E');
if ($cacheFile) {
$datas = unserialize($cacheFile);
foreach ($datas['headers'] as $data) {
header($data['name'] . ': ' . $data['value']);
}
//set cache provider header
header('Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'E');

$client_support_gzip = true;
$client_support_gzip = true;

//check gzip request from client
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') === false)) {
$client_support_gzip = false;
}

if ($client_support_gzip && function_exists('gzdecode') && !empty($GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'])) {
//if file is zip
//check gzip request from client
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false || strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') === false)) {
$client_support_gzip = false;
}

$content = gzencode($datas['body'], 9);
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($content));
header('Vary: Accept-Encoding');
echo $content;
} else {
header('Content-Length: ' . strlen($datas['body']));
//render page cache
echo $datas['body'];
}
exit;
if ($client_support_gzip && function_exists('gzdecode') && !empty($GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'])) {
//if file is zip

$content = gzencode($datas['body'], 9);
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($content));
header('Vary: Accept-Encoding');
echo $content;
} else {
header('Content-Length: ' . strlen($datas['body']));
//render page cache
echo $datas['body'];
}
exit;
}
}

Expand Down
14 changes: 4 additions & 10 deletions inc/cache/purge-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,7 @@ public function purge_post_on_new_comment($comment_ID, $approved, $commentdata)
}

$url_path = get_permalink($post_id);
if ($wp_filesystem->exists(breeze_get_cache_base_path() . md5($url_path))) {
$wp_filesystem->rmdir(breeze_get_cache_base_path() . md5($url_path), true);
}
RedisClient::factory()->delete(breeze_get_cache_base_path() . md5($url_path) . '/*');
}
}

Expand All @@ -106,9 +104,7 @@ public function purge_post_on_comment_status_change($comment_ID, $comment_status

$url_path = get_permalink($post_id);

if ($wp_filesystem->exists(breeze_get_cache_base_path() . md5($url_path))) {
$wp_filesystem->rmdir(breeze_get_cache_base_path() . md5($url_path), true);
}
RedisClient::factory()->delete(breeze_get_cache_base_path() . md5($url_path) . '/*');
}
}
}
Expand All @@ -122,7 +118,7 @@ public static function breeze_cache_flush() {
WP_Filesystem();

$cache_path = breeze_get_cache_base_path(is_network_admin());
$wp_filesystem->rmdir(untrailingslashit($cache_path), true);
RedisClient::factory()->delete($cache_path . '*');

if (function_exists('wp_cache_flush')) {
wp_cache_flush();
Expand All @@ -141,9 +137,7 @@ public function clean_up() {
$ret = false;
}

$folder = untrailingslashit(breeze_get_cache_base_path());

if (!$wp_filesystem->delete($folder, true)) {
if (!@RedisClient::factory()->delete(breeze_get_cache_base_path() . '*')) {
$ret = false;
}

Expand Down
1 change: 0 additions & 1 deletion inc/cache/purge-per-time.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ public function schedule_varnish() {

// Purge normal cache
if ($this->normalcache) {
Breeze_PurgeCache::breeze_cache_flush();
Breeze_MinificationCache::clear_minification();
}
}
Expand Down
97 changes: 97 additions & 0 deletions inc/cache/redis-client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php
/**
* @copyright 2017 Cloudways https://www.cloudways.com
*
* Original development of this plugin by JoomUnited https://www.joomunited.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
if (!defined('ABSPATH')) {
exit;
}

class RedisClient {
/**
* @var Redis
*/
private $redis;

public function __construct($uri) {
$this->redis = new Redis();
$url = parse_url($uri);
$scheme = 'tcp';

switch ($url['scheme']) {
case 'unix':
$this->redis->connect($url['path']);
break;

case 'rediss':
$scheme = 'tls';
// no break
default:
$db = strlen($url['path']) > 1 ? (int) filter_var(substr($url['path'], 1), FILTER_VALIDATE_INT) : 0;
$db = $db ? $db : 0;
$host = ($scheme ? $scheme . '://' : '') . $url['host'];
$port = isset($url['port']) ? $url['port'] : 6379;
$this->redis->connect($host, $port);
$this->redis->select($db);
break;
}
}

public function delete($key) {
try {
return $this->redis->eval("local keys = redis.call('keys', ARGV[1]) for i=1,#keys,5000 do redis.call('del', unpack(keys, i, math.min(i+4999, #keys))) end return #keys", [$key], 0);
} catch (exception $e) {
throw $this->redis->getLastError();
}
}

public function set($key, $data, $ttl = 0) {
try {
if ($ttl) {
return $this->redis->setEx($key, $ttl, $data);
}
return $this->redis->set($key, $data);
} catch (exception $e) {
throw $this->redis->getLastError();
}
}

public function get($key) {
try {
return $this->redis->get($key);
} catch (exception $e) {
throw $this->redis->getLastError();
}
}

/**
* Singleton instance.
*
* @return RedisClient
*/
public static function factory() {
static $instance;

if (!$instance) {
$config = isset($GLOBALS['breeze_config']['cache_options']['breeze-redis-uri']) ? $GLOBALS['breeze_config']['cache_options']['breeze-redis-uri'] : breeze_get_option('basic_settings')['breeze-redis-uri'];
$instance = new self($config);
}

return $instance;
}
}
32 changes: 27 additions & 5 deletions inc/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@
define('BREEZE_PLUGIN_FULL_PATH', dirname(__DIR__) . '/');
require_once BREEZE_PLUGIN_FULL_PATH . 'inc/class-breeze-query-strings-rules.php';

/**
* Generate UUIDv4.
*
* @return string
*/
function guidv4() {
$data = random_bytes(16);

$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10

return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

/**
* Get base path for the page cache directory.
*
Expand All @@ -30,23 +44,31 @@
* @return string
*/
function breeze_get_cache_base_path($is_network = false, $blog_id_requested = 0) {
$guild_path = rtrim(WP_CONTENT_DIR, '/\\') . '/breeze-guid.txt';
$guid = file_get_contents($guild_path);
if (empty($guid)) {
$guid = guidv4();
file_put_contents($guild_path, $guid);
}
$guid = rtrim($guid, '/\\') . '/';

if (empty($blog_id_requested)) {
$blog_id_requested = isset($GLOBALS['breeze_config']['blog_id']) ? $GLOBALS['breeze_config']['blog_id'] : 0;
}

if (!$is_network && is_multisite()) {
if (empty($blog_id_requested)) {
global $blog_id;
$path = rtrim(WP_CONTENT_DIR, '/\\') . '/cache/breeze/';
$path = $guid;
if (!empty($blog_id)) {
$path .= abs(intval($blog_id)) . DIRECTORY_SEPARATOR;
$path .= abs(intval($blog_id)) . '/';
}
} else {
$path = rtrim(WP_CONTENT_DIR, '/\\') . '/cache/breeze/';
$path .= abs(intval($blog_id_requested)) . DIRECTORY_SEPARATOR;
$path = $guid;
$path .= abs(intval($blog_id_requested)) . '/';
}
} else {
$path = rtrim(WP_CONTENT_DIR, '/\\') . '/cache/breeze/';
$path = $guid;
}

return $path;
Expand Down
4 changes: 2 additions & 2 deletions inc/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -631,8 +631,8 @@ function breeze_varnish_purge_cache($url = '', $purge_varnish = false, $check_va
}

// Clear the local cache using the product URL.
if (!empty($url) && $wp_filesystem->exists(breeze_get_cache_base_path() . md5($url))) {
$wp_filesystem->rmdir(breeze_get_cache_base_path() . md5($url), true);
if (!empty($url)) {
RedisClient::factory()->delete(breeze_get_cache_base_path() . md5($url) . '/*');
}

if ($purge_varnish === false && $check_varnish === true) {
Expand Down
Loading

0 comments on commit 8a98f8f

Please sign in to comment.