Skip to content

Commit

Permalink
Create an 'on-all-events' invalidation strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
antonioribeiro committed Sep 10, 2024
1 parent 681f92e commit 60987d7
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 12 deletions.
19 changes: 19 additions & 0 deletions config/invalidations.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,25 @@
*/
'default' => 'invalidate-dependents',
],

'on-all-events' => [
/**
* On all events, also invalidate those
*/
'default' => 'invalidate-none',

'when-models' => [
[
'models' => ['*'],

'strategy' => 'invalidate-urls',

'urls' => [
'%sitemap.xml%',
]
],
],
],
],
],
];
5 changes: 5 additions & 0 deletions src/Listeners/EloquentObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public function invalidate(Model $model, string $event, array $relation = []): v
return;
}

if ($event !== 'on-all-events') {
// Always dispatch an 'on-all-events' event
$this->invalidate($model, 'on-all-events', $relation);
}

$entity = new Entity($model, $event);

$entity->setRelation($relation);
Expand Down
15 changes: 14 additions & 1 deletion src/Services/Invalidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ public function setPaths(Collection $paths): self
return $this;
}

public function itemsList(string|null $type = null): Collection
{
return $this->items($type);
}

public function queryItemsList(string|null $type = null): string
{
return $this->items($type)
Expand Down Expand Up @@ -355,7 +360,15 @@ public function urlNames(): Collection
return $this->urlNames;
}

return $this->urlNames = $this->urls()->map->url;
$urls = $this->urls()->map(function (Url|string $url) {

Check failure on line 363 in src/Services/Invalidation.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(A17\EdgeFlush\Models\Url|string): string given.

Check failure on line 363 in src/Services/Invalidation.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(A17\EdgeFlush\Models\Url|string): string given.

Check failure on line 363 in src/Services/Invalidation.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(A17\EdgeFlush\Models\Url|string): string given.
if ($url instanceof Url) {
return $url->url;
}

return $url;
});

return $this->urlNames = $urls;
}

public function urlHashes(): Collection
Expand Down
25 changes: 25 additions & 0 deletions src/Services/Strategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace A17\EdgeFlush\Services;

class Strategy
{
public string $name;

public array $urls = [];

public array $models = [];

public array $onChange = [];

public function __construct(array $strategy)
{
$this->name = $strategy['strategy'];

$this->urls = $strategy['urls'] ?? [];

$this->models = $strategy['models'] ?? [];

$this->onChange = $strategy['onChange'] ?? [];
}
}
108 changes: 97 additions & 11 deletions src/Services/Tags.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace A17\EdgeFlush\Services;

use PHPUnit\TextUI\Help;
use Illuminate\Support\Str;
use A17\EdgeFlush\EdgeFlush;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -228,13 +229,13 @@ protected function dispatchInvalidationsForCrud(Entity $entity): void

$strategy = $this->getCrudStrategy($entity);

if ($strategy === Constants::INVALIDATION_STRATEGY_NONE) {
if ($strategy->name === Constants::INVALIDATION_STRATEGY_NONE) {
Helpers::debug('NO INVALIDATION needed for model ' . $entity->modelName);

return;
}

if ($strategy === Constants::INVALIDATION_STRATEGY_ALL) {
if ($strategy->name === Constants::INVALIDATION_STRATEGY_ALL) {
Helpers::debug('INVALIDATING ALL tags');

$this->markAsDispatched($entity);
Expand All @@ -244,7 +245,7 @@ protected function dispatchInvalidationsForCrud(Entity $entity): void
return;
}

if ($strategy === Constants::INVALIDATION_STRATEGY_DEPENDENTS) {
if ($strategy->name === Constants::INVALIDATION_STRATEGY_DEPENDENTS) {
Helpers::debug('INVALIDATING tags for model ' . $entity->modelName);

$invalidation = new Invalidation();
Expand All @@ -258,32 +259,64 @@ protected function dispatchInvalidationsForCrud(Entity $entity): void
return;
}

throw new \Exception("Strategy '{$strategy}' Not implemented");
if ($strategy->name === Constants::INVALIDATION_STRATEGY_URLS) {
Helpers::debug('Invalidate URLs ' . json_encode($strategy->urls));

$invalidation = new Invalidation();

$invalidation->setUrls($strategy->urls);

$this->invalidateTags($invalidation);

return;
}

throw new \Exception("Strategy '{$strategy->name}' Not implemented");
}

public function getCrudStrategy(Entity $entity): string
public function getCrudStrategy(Entity $entity): Strategy
{
if (!$entity->isDirty()) {
return Constants::INVALIDATION_STRATEGY_NONE;

Check failure on line 280 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Method A17\EdgeFlush\Services\Tags::getCrudStrategy() should return A17\EdgeFlush\Services\Strategy but returns string.

Check failure on line 280 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Method A17\EdgeFlush\Services\Tags::getCrudStrategy() should return A17\EdgeFlush\Services\Strategy but returns string.

Check failure on line 280 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Method A17\EdgeFlush\Services\Tags::getCrudStrategy() should return A17\EdgeFlush\Services\Strategy but returns string.
}

$strategy = Helpers::configArray("edge-flush.invalidations.crud-strategy.{$entity->event}");

$defaultStrategy = $strategy['default'] ?? Constants::INVALIDATION_STRATEGY_DEPENDENTS;
$defaultStrategy = new Strategy(['strategy' => $strategy['default'] ?? Constants::INVALIDATION_STRATEGY_DEPENDENTS]);

if (blank($strategy)) {
return $defaultStrategy;
}

foreach ($strategy['when-models'] ?? [] as $modelStrategy) {
// Model is not in the list of models
if (!in_array($entity->modelClass, $modelStrategy['models'])) {
// Loop through each model or pattern in the models list
$matchesPattern = false;

foreach ($modelStrategy['models'] as $model) {
// Check if it's a full class name match
if ($entity->modelClass === $model) {
$matchesPattern = true;

break;
}

// Check for a wildcard match (e.g., using '*' or other patterns)
if (fnmatch($model, $entity->modelClass)) {
$matchesPattern = true;

break;
}
}

// If no match is found, continue to the next strategy
if (!$matchesPattern) {
continue;
}

// Your logic when a match is found
// There's no on-change condition
if (blank($modelStrategy['on-change'] ?? null)) {
return $modelStrategy['strategy'];
return new Strategy($modelStrategy);
}

// Check if the attribute has changed to the expected value
Expand All @@ -292,7 +325,7 @@ public function getCrudStrategy(Entity $entity): string
// Is the expected value the same as the current value?
// If key == value, then we're checking if the attribute was just changed
if ($entity->isDirty($key) && ($key === $value || $entity->attributeEquals($key, $value))) {
return $modelStrategy['strategy'];
return new Strategy($modelStrategy);
}
}
}
Expand All @@ -314,7 +347,7 @@ public function invalidateTags(Invalidation $invalidation): void
}

Helpers::configString('edge-flush.invalidations.type') === 'batch'
? $this->markTagsAsObsolete($invalidation)
? $this->markAsObsolete($invalidation)
: $this->dispatchInvalidations($invalidation);
}

Expand Down Expand Up @@ -383,10 +416,21 @@ protected function invalidateObsoleteTags(): void
$this->dispatchInvalidations($invalidation);
}

protected function markAsObsolete(Invalidation $invalidation): void
{
$this->markTagsAsObsolete($invalidation);

$this->markUrlsAsObsolete($invalidation);
}

protected function markTagsAsObsolete(Invalidation $invalidation): void
{
$type = $invalidation->type();

if ($type !== 'tag') {
return;
}

$list = $invalidation->queryItemsList();

if ($list === "''" || is_null($type) || blank($type)) {

Check failure on line 436 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Call to function is_null() with 'tag' will always evaluate to false.

Check failure on line 436 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Call to function is_null() with 'tag' will always evaluate to false.

Check failure on line 436 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Call to function is_null() with 'tag' will always evaluate to false.
Expand All @@ -398,6 +442,25 @@ protected function markTagsAsObsolete(Invalidation $invalidation): void
$this->dbStatement($this->markTagsAsObsoleteSql($type, $list));
}

protected function markUrlsAsObsolete(Invalidation $invalidation): void
{
$type = $invalidation->type();

if ($type !== 'url') {
return;
}

$list = $invalidation->itemsList();

if ($list->isEmpty() || blank($type)) {
return;
}

Helpers::debug("Marking urls as obsolete: {$type} in ".json_encode($list));

$this->dbStatement($this->markUrlsAsObsoleteSql($list));
}

protected function markTagsAsObsoleteSql(string $type, string $list): string
{
if ($this->isMySQL()) {
Expand Down Expand Up @@ -452,6 +515,29 @@ protected function markTagsAsObsoleteSql(string $type, string $list): string
";
}

protected function markUrlsAsObsoleteSql(Collection $list): string
{
$wheres = $list->map(function (string $url) {

Check failure on line 520 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(string): non-falsy-string given.

Check failure on line 520 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(string): non-falsy-string given.

Check failure on line 520 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),mixed>::map() expects callable(mixed, int|string): string, Closure(string): non-falsy-string given.
if (strpos($url, "%") !== false) {
return "url like '{$url}'";
}

return "url_hash = '{$url->url_hash}'";

Check failure on line 525 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.3

Cannot access property $url_hash on string.

Check failure on line 525 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

Cannot access property $url_hash on string.

Check failure on line 525 in src/Services/Tags.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

Cannot access property $url_hash on string.
})->join(' or ');

Helpers::debug("Marking urls as obsolete: "."
update edge_flush_urls efu
set obsolete = true
where(obsolete = false and $wheres)
");

return "
update edge_flush_urls efu
set obsolete = true
where(obsolete = false and $wheres)
";
}

protected function dispatchInvalidations(Invalidation $invalidation): void
{
if ($invalidation->isEmpty() || !$this->enabled()) {
Expand Down
2 changes: 2 additions & 0 deletions src/Support/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ class Constants
const INVALIDATION_STRATEGY_DEPENDENTS = 'invalidate-dependents';

const INVALIDATION_STRATEGY_NONE = 'invalidate-none';

const INVALIDATION_STRATEGY_URLS = 'invalidate-urls';
}

0 comments on commit 60987d7

Please sign in to comment.