Skip to content

Commit

Permalink
Major refactoring, renaming and simplification.
Browse files Browse the repository at this point in the history
  • Loading branch information
kepol committed Jul 6, 2024
1 parent 5d5b59c commit 1b957b4
Show file tree
Hide file tree
Showing 16 changed files with 484 additions and 461 deletions.
1 change: 1 addition & 0 deletions modules/quant_api/src/Client/QuantClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ public function search() {
* {@inheritdoc}
*/
public function purgePath(string $path) : array {

$response = $this->client->post($this->endpoint . '/purge', [
RequestOptions::JSON => [],
'headers' => [
Expand Down
30 changes: 27 additions & 3 deletions modules/quant_purger/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
# Quant cache tag purger
# Quant Purger

Adds a cache tag plugin which listens to Drupal invalidation events in order to
queue Quant updates for related content.
The Quant Purger helps you keep content fresh on your static Quant site
after content updates within Drupal.

## Purge Plugins

This module is built on top of the [Purge module suite](https://www.drupal.org/project/purge).

### Purger Plugin

Processes cache invalidations based on type: 'everything', 'path' and 'tag'.
The Quant cache will be purged based on these invalidations.

- *Everything:* A site-wide cache purge, e.g. `/*`.
- *Path:* Purges the given path.
- *Tag:* Purges the given tag.

### Queuer Plugin

Adds a cache tag queuer plugin which listens to Drupal invalidation events in
order to queue Quant updates for related content.

For example, this allows node edits to trigger the main (`/node`) page to update
along with any other pages associated with the node through cache tags (e.g.
Expand All @@ -14,6 +32,12 @@ To ensure that queued content is processed in a timely manner, you can set up a
Quant cron process that is separate from the core cron which just processes the
Quant queue. This Quant cron can be run more regularly than the core cron.

### TagsHeader Plugin

Sets and formats the default response header with hashed cache tags.

## Documentation

See [Quant Purger documentation](https://docs.quantcdn.io/docs/integrations/drupal/purger)
for additional information.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
quant_purge_header:
quant_purger_header:
type: mapping
label: 'Quant Header'
label: 'Quant Purger Header'
mapping:
field:
type: string
Expand Down
32 changes: 24 additions & 8 deletions modules/quant_purger/config/schema/quant_purger.schema.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
# Schema for the configuration files of the purge_queuer_url module.
quant_purger.settings:
type: config_object
label: 'Quant purger settings.'
label: 'Quant Purger Queuer Settings'
mapping:
tag_blacklist:
label: 'A list of string tags that will not trigger a queue.'
tag_blocklist:
label: 'A list of tags that will not get queued.'
type: sequence
translatable: false
sequence:
type: string
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.'
tag_allowlist:
label: 'A list of tags that can get queued.'
type: sequence
translatable: false
sequence:
type: string
label: 'String that can be present in the cache tag.'
translatable: false
path_blocklist:
label: 'A list of paths that will not get queued.'
type: sequence
translatable: false
sequence:
type: string
label: 'String that cannot be present in a fully qualified URL.'
translatable: false
path_allowlist:
label: 'A list of paths that can not get queued.'
type: sequence
translatable: false
sequence:
type: string
label: 'String that can be present in a fully qualified URL.'
translatable: false

// @todo Why is this under the queuer settings?
quant_purger.settings.*:
type: config_entity
label: 'Section Purger'
label: 'Quant Purger Settings'
mapping:

#
Expand All @@ -34,7 +50,7 @@ quant_purger.settings.*:
name:
type: string
translatable: false
invalidationtype:
invalidation_type:
type: string
translatable: false

Expand Down
2 changes: 1 addition & 1 deletion modules/quant_purger/quant_purger.info.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Quant Purger
description: Cache tag purger for Quant.
description: Purge content in Quant based on paths and cache tags.
package: Quant

type: module
Expand Down
2 changes: 1 addition & 1 deletion modules/quant_purger/quant_purger.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
tags:
- { name: http_middleware, priority: 250 }
quant_purger.queuer:
class: Drupal\quant_purger\Plugin\Purge\Queuer\QuantPurger
class: Drupal\quant_purger\Plugin\Purge\Queuer\QuantPurgerQueuerInvalidator
tags:
- { name: cache_tags_invalidator }
calls:
Expand Down
8 changes: 4 additions & 4 deletions modules/quant_purger/src/Entity/QuantPurgerSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
* Defines the QuantPurgerSettings entity.
*
* @ConfigEntityType(
* id = "quantpurgersettings",
* label = @Translation("QuantCDN"),
* id = "quant_purger_settings",
* label = @Translation("Quant Purger Settings"),
* config_prefix = "settings",
* static_cache = TRUE,
* entity_keys = {"id" = "id"},
Expand All @@ -19,7 +19,7 @@
* "label",
* "description",
* "name",
* "invalidationtype",
* "invalidation_type",
* "runtime_measurement",
* "timeout",
* "connect_timeout",
Expand Down Expand Up @@ -47,7 +47,7 @@ class QuantPurgerSettings extends PurgerSettingsBase implements PurgerSettingsIn
*
* @var string
*/
public $invalidationtype = 'tag';
public $invalidation_type = 'tag';

/**
* Runtime measurement.
Expand Down
211 changes: 208 additions & 3 deletions modules/quant_purger/src/Form/QuantPurgerConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,223 @@

namespace Drupal\quant_purger\Form;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\purge\Plugin\Purge\Invalidation\InvalidationsServiceInterface;
use Drupal\purge_ui\Form\PurgerConfigFormBase;
use Drupal\quant_purger\Entity\QuantPurgerSettings;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Configuration form for the Quant Purger.
* Form for Quant Purger configuration.
*/
class QuantPurgerConfigForm extends QuantPurgerConfigFormBase {
class QuantPurgerConfigForm extends PurgerConfigFormBase {

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

/**
* The service that generates invalidation objects on-demand.
*
* @var \Drupal\purge\Plugin\Purge\Invalidation\InvalidationsServiceInterface
*/
protected $purgeInvalidationFactory;

/**
* Constructs a base Quant Purger configuration form.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\purge\Plugin\Purge\Invalidation\InvalidationsServiceInterface $purge_invalidation_factory
* The invalidation objects factory service.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entityTypeManager.
*/
public function __construct(ConfigFactoryInterface $config_factory, InvalidationsServiceInterface $purge_invalidation_factory, EntityTypeManagerInterface $entity_type_manager) {
$this->setConfigFactory($config_factory);
$this->purgeInvalidationFactory = $purge_invalidation_factory;
$this->entityTypeManager = $entity_type_manager;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('purge.invalidation.factory'),
$container->get('entity_type.manager')
);
}

/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [];
}

/**
* {@inheritdoc}
*/
public function getFormId() {
return 'quant_purger.configuration_form';
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$settings = QuantPurgerSettings::load($this->getId($form_state));
$form['tabs'] = ['#type' => 'vertical_tabs', '#weight' => 10];
$this->buildFormMetadata($form, $form_state, $settings);
$this->buildFormPerformance($form, $form_state, $settings);
return parent::buildForm($form, $form_state);
}

/**
* Build the 'metadata' section of the form.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param \Drupal\quant_purger\Entity\QuantPurgerSettings $settings
* Configuration entity for the purger being configured.
*/
public function buildFormMetadata(array &$form, FormStateInterface $form_state, QuantPurgerSettings $settings) {
$form['name'] = [
'#title' => $this->t('Name'),
'#type' => 'textfield',
'#description' => $this->t('Purger to purge QuantCDN content.'),
'#default_value' => $settings->name,
'#required' => TRUE,
];
$types = [];
foreach ($this->purgeInvalidationFactory->getPlugins() as $type => $definition) {
$types[$type] = (string) $definition['label'];
}
}

/**
* Build the 'performance' section of the form.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param \Drupal\quant_purger\Entity\QuantPurgerSettings $settings
* Configuration entity for the purger being configured.
*/
public function buildFormPerformance(array &$form, FormStateInterface $form_state, QuantPurgerSettings $settings) {
$form['performance'] = [
'#type' => 'details',
'#group' => 'tabs',
'#title' => $this->t('Performance'),
];
$form['performance']['cooldown_time'] = [
'#type' => 'number',
'#step' => 0.1,
'#min' => 0.0,
'#max' => 3.0,
'#title' => $this->t('Cooldown time'),
'#default_value' => $settings->cooldown_time,
'#required' => TRUE,
'#description' => $this->t('Number of seconds to wait after a group of HTTP requests so that other purgers get fresh content.'),
];
$form['performance']['max_requests'] = [
'#type' => 'number',
'#step' => 1,
'#min' => 1,
'#max' => 500,
'#title' => $this->t('Maximum requests'),
'#default_value' => $settings->max_requests,
'#required' => TRUE,
'#description' => $this->t("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."),
];
$form['performance']['runtime_measurement'] = [
'#title' => $this->t('Runtime measurement'),
'#type' => 'checkbox',
'#default_value' => $settings->runtime_measurement,
];
$form['performance']['runtime_measurement_help'] = [
'#type' => 'item',
'#states' => [
'visible' => [
':input[name="runtime_measurement"]' => ['checked' => FALSE],
],
],
'#description' => $this->t('When you uncheck this setting, capacity will be based on the sum of both timeouts. By default, capacity will automatically adjust (up and down) based on measured time data.'),
];
$form['performance']['timeout'] = [
'#type' => 'number',
'#step' => 0.1,
'#min' => 0.1,
'#max' => 8.0,
'#title' => $this->t('Timeout'),
'#default_value' => $settings->timeout,
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name="runtime_measurement"]' => ['checked' => FALSE],
],
],
'#description' => $this->t('The timeout of the request in seconds.'),
];
$form['performance']['connect_timeout'] = [
'#type' => 'number',
'#step' => 0.1,
'#min' => 0.1,
'#max' => 4.0,
'#title' => $this->t('Connection timeout'),
'#default_value' => $settings->connect_timeout,
'#required' => TRUE,
'#states' => [
'visible' => [
':input[name="runtime_measurement"]' => ['checked' => FALSE],
],
],
'#description' => $this->t('The number of seconds to wait while trying to connect to a server.'),
];
}

/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {

// Validate that our timeouts stay between the boundaries purge demands.
$timeout = $form_state->getValue('connect_timeout') + $form_state->getValue('timeout');
if ($timeout > 10) {
$form_state->setErrorByName('connect_timeout');
$form_state->setErrorByName('timeout', $this->t('The sum of both timeouts cannot be higher than 10.00 as this would affect performance too negatively.'));
}
elseif ($timeout < 0.4) {
$form_state->setErrorByName('connect_timeout');
$form_state->setErrorByName('timeout', $this->t('The sum of both timeouts cannot be lower as 0.4 as this can lead to too many failures under real usage conditions.'));
}
}

/**
* {@inheritdoc}
*/
public function submitFormSuccess(array &$form, FormStateInterface $form_state) {
$settings = QuantPurgerSettings::load($this->getId($form_state));

// Iterate the config object and overwrite values found in the form state.
foreach ($settings as $key => $default_value) {
if (!is_null($value = $form_state->getValue($key))) {
$settings->$key = $value;
}
}
$settings->save();
}

}
Loading

0 comments on commit 1b957b4

Please sign in to comment.