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

Added support for automatic purging via cache tags #238

Open
wants to merge 16 commits into
base: 8.x-1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions modules/quant_api/src/Client/QuantClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,44 @@ public function search() {
return FALSE;
}

/**
* {@inheritdoc}
*/
public function purgePath(string $path) : array {
$response = $this->client->post($this->endpoint . '/purge', [
RequestOptions::JSON => [],
'headers' => [
'Quant-Customer' => $this->username,
'Quant-Project' => $this->project,
'Quant-Token' => $this->token,
'Quant-Url' => $path,
],
'verify' => $this->tlsDisabled ? FALSE : TRUE,
]);

return json_decode($response->getBody(), TRUE);
}

/**
* {@inheritdoc}
*/
public function purgeTags(array $tags) : array {

$response = $this->client->post($this->endpoint . '/purge', [
RequestOptions::JSON => [],
'headers' => [
'Quant-Customer' => $this->username,
'Quant-Project' => $this->project,
'Quant-Token' => $this->token,
'Cache-Keys' => implode(' ', $tags),
],
'verify' => $this->tlsDisabled ? FALSE : TRUE,
]);

return json_decode($response->getBody(), TRUE);

}

/**
* {@inheritdoc}
*/
Expand Down
28 changes: 28 additions & 0 deletions modules/quant_api/src/Client/QuantClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,34 @@ public function search();
*/
public function send(array $data) : array;

/**
* Sends a purge payload (path based) to the API.
*
* @param string $path
* The path to purge.
*
* @return array
* Return array of response data.
*
* @throws \Drupal\quant_api\Exception\InvalidPayload
* @throws \Drupal\quant_api\Exception\InvalidResposne
kepol marked this conversation as resolved.
Show resolved Hide resolved
*/
public function purgePath(string $path) : array;

/**
* Sends a purge payload (tags based) to the API.
*
* @param array $tags
* The array of tags to purge.
*
* @return array
* Return array of response data.
*
* @throws \Drupal\quant_api\Exception\InvalidPayload
* @throws \Drupal\quant_api\Exception\InvalidResposne
kepol marked this conversation as resolved.
Show resolved Hide resolved
*/
public function purgeTags(array $tags) : array;

/**
* Send a file to the API.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
quant_purge_header:
kepol marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not clear what this is being used for

type: mapping
label: 'Quant Header'
mapping:
field:
type: string
translatable: false
value:
type: string
translatable: false
46 changes: 45 additions & 1 deletion modules/quant_purger/config/schema/quant_purger.schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ quant_purger.settings:
translatable: false
sequence:
type: string
label: 'String that cannot be present in the ccache tag.'
label: 'String that cannot be present in the cache tag.'
translatable: false
path_blacklist:
label: 'A list of string patterns that will not get queued.'
Expand All @@ -19,3 +19,47 @@ quant_purger.settings:
type: string
label: 'String that cannot be present in a fully qualified URL.'
translatable: false

quant_purger.settings.*:
type: config_entity
label: 'Section Purger'
kepol marked this conversation as resolved.
Show resolved Hide resolved
mapping:

#
# Instance metadata:
#
id:
type: string
translatable: false
name:
type: string
translatable: false
invalidationtype:
type: string
translatable: false

#
# Performance settings:
#
runtime_measurement:
type: boolean
translatable: false
timeout:
type: float
translatable: false
connect_timeout:
type: float
translatable: false
cooldown_time:
type: float
translatable: false
max_requests:
type: integer
translatable: false

#
# Success resolution:
#
http_errors:
type: boolean
translatable: false
70 changes: 70 additions & 0 deletions modules/quant_purger/src/Entity/Hash.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace Drupal\quant_purger\Entity;

/**
* Helper class that centralizes string hashing for security and maintenance.
*/
class Hash {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this make sense as a general utility instead of just in quant_purger?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or not because it's dealing with cache tags?


/**
* Create a hash with the given input and length.
*
* @param string $input
* The input string to be hashed.
* @param int $length
* The length of the hash.
*
* @return string
* Cryptographic hash with the given length.
*/
protected static function hashInput($input, $length) {
// MD5 is the fastest algorithm beyond CRC32 (which is 30% faster, but high
// collision risk), so this is the best bet for now. If collisions are going
// to be a major problem in the future, we might have to consider a hash DB.
$hex = md5($input);
// The produced HEX can be converted to BASE32 number to take less space.
// For example 5 characters HEX can be stored in 4 characters BASE32.
$hash = base_convert(substr($hex, 0, ceil($length * 1.25)), 16, 32);
// Return a hash with consistent length, padding zeroes if needed.
return strtolower(str_pad(substr($hash, 0, $length), $length, '0', STR_PAD_LEFT));
}

/**
* Create unique hashes/IDs for a list of cache tag strings.
*
* @param string[] $tags
* Non-associative array cache tags.
*
* @return string[]
* Non-associative array with hashed copies of the given cache tags.
*/
public static function cacheTags(array $tags) {
$hashes = [];
foreach ($tags as $tag) {
if (strlen($tag) > 4) {
$hashes[] = self::hashInput($tag, 4);
}
else {
$hashes[] = $tag;
}
}
return $hashes;
}

/**
* Create a unique hash that identifies this site.
*
* @param string $site_name
* The identifier of the site on Acquia Cloud.
* @param string $site_path
* The path of the site, e.g. 'site/default' or 'site/database_a'.
*
* @return string
* Cryptographic hash that's long enough to be unique.
*/
public static function siteIdentifier($site_name, $site_path) {
return self::hashInput($site_name . $site_path, 16);
}

}
115 changes: 115 additions & 0 deletions modules/quant_purger/src/Entity/QuantPurgeSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

namespace Drupal\quant_purger\Entity;

use Drupal\purge\Plugin\Purge\Purger\PurgerSettingsBase;
use Drupal\purge\Plugin\Purge\Purger\PurgerSettingsInterface;

/**
* Defines the QuantCDN purger settings entity.
kepol marked this conversation as resolved.
Show resolved Hide resolved
*
* @ConfigEntityType(
* id = "quantpurgersettings",
kepol marked this conversation as resolved.
Show resolved Hide resolved
* label = @Translation("QuantCDN"),
* config_prefix = "settings",
* static_cache = TRUE,
* entity_keys = {"id" = "id"},
* config_export = {
* "id",
* "label",
* "description",
* "name",
* "invalidationtype",
* "runtime_measurement",
* "timeout",
* "connect_timeout",
* "cooldown_time",
* "max_requests",
* "http_errors"
* },
* )
*/
class QuantPurgeSettings extends PurgerSettingsBase implements PurgerSettingsInterface {
kepol marked this conversation as resolved.
Show resolved Hide resolved

/**
* Instance metadata.
*/

/**
* The readable name of this purger.
*
* @var string
*/
public $name = '';

/**
* The invalidation plugin ID that this purger invalidates.
*
* @var string
*/
public $invalidationtype = 'tag';

/**
* Runtime measurement.
*
* When FALSE, dynamic capacity calculation will be disabled and based upon
* the connect_timeout and timeout settings.
*
* @var bool
*/
// @phpcs:ignore
public $runtime_measurement = TRUE;

/**
* The timeout of the request in seconds.
*
* @var float
*/
public $timeout = 1.0;

/**
* The number of seconds to wait while trying to connect to a server.
*
* @var float
*/
// @phpcs:ignore
public $connect_timeout = 1.0;

/**
* Cooldown time.
*
* Number of seconds to wait after one or more invalidations took place (so
* that other purgers get fresh content).'
kepol marked this conversation as resolved.
Show resolved Hide resolved
*
* @var float
*/
// @phpcs:ignore
public $cooldown_time = 0.0;

/**
* Maximum requests.
*
* Maximum number of HTTP requests that can be made during Drupal's execution
* lifetime. Usually PHP resource restraints lower this value dynamically, but
* can be met at the CLI.
*
* @var int
*/
// @phpcs:ignore
public $max_requests = 250;

/**
* Success resolution.
*/

/**
* Whether 4xx and 5xx responses need to be treated as failures or not.
*
* @var bool
*
* @see http://docs.guzzlephp.org/en/latest/request-options.html#http-errors
*/
// @phpcs:ignore
public $http_errors = TRUE;

}
19 changes: 19 additions & 0 deletions modules/quant_purger/src/Form/QuantPurgeForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Drupal\quant_purger\Form;

/**
* Configuration form for the HTTP Bundled Purger.
*/
class QuantPurgeForm extends QuantPurgeFormBase {
kepol marked this conversation as resolved.
Show resolved Hide resolved

/**
* The token group names this purger supports replacing tokens for.
*
* @var string[]
*
* @see purge_tokens_token_info()
*/
protected $tokenGroups = ['invalidation'];

}
Loading
Loading