Skip to content

Commit

Permalink
Fix app dispatching multiple invalidations on create
Browse files Browse the repository at this point in the history
  • Loading branch information
antonioribeiro committed Feb 20, 2023
1 parent bf7a4c2 commit 533d034
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 47 deletions.
13 changes: 9 additions & 4 deletions config/edge-flush.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,18 @@
*/
'tags' => [
'excluded-model-classes' => [
// Twill modules
'\Models\Translations*',
'\Models\Slugs*',
'\Models\Revisions*',

// Twill capsules
'*\Models\*Translation',
'*\Models\*Slug',
'*\Models\*Revision',

// Other classes
'Spatie\Activitylog\Models\Activity',
],

'format' => 'app-%environment%-%sha1%',
Expand Down Expand Up @@ -326,10 +335,6 @@
'strategy' => 'invalidate-all',
]
],

'models' => [
'ignore' => \Spatie\Activitylog\Models\Activity::class,
]
],

/**
Expand Down
5 changes: 4 additions & 1 deletion src/Services/Invalidation.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ public function absorbCloudFront(AwsResult $invalidation): self
return $this;
}

$statusCode = $invalidation['@metadata']['statusCode'];

$invalidation = Helpers::toArray($invalidation['Invalidation']);

$time = $invalidation['CreateTime'] ?? null;
Expand All @@ -109,7 +111,8 @@ public function absorbCloudFront(AwsResult $invalidation): self

$this->setId($invalidation['Id'] ?? null)
->setStatus($invalidation['Status'] ?? null)
->setCreatedAt($time);
->setCreatedAt($time)
->setSuccess($statusCode === 201);

return $this;
}
Expand Down
104 changes: 62 additions & 42 deletions src/Services/Tags.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ class Tags

protected Collection $tags;

protected Collection $invalidationDispatched;

public Collection $processedTags;

public function __construct()
{
$this->tags = collect();

$this->processedTags = collect();

$this->invalidationDispatched = collect();
}

public function addTag(Model $model): void
Expand Down Expand Up @@ -182,14 +186,6 @@ public function storeCacheTags(
->map(fn(mixed $item) => "'" . Helpers::toString($item) . "'")
->join(',');

$this->dbStatement("
update edge_flush_tags
set obsolete = false
where index in ({$indexes})
and is_valid = true
and obsolete = false
");

$this->dbStatement("
update edge_flush_urls
set was_purged_at = null,
Expand All @@ -201,13 +197,26 @@ public function storeCacheTags(
from edge_flush_tags
where index in ({$indexes})
and is_valid = true
and obsolete = false
and obsolete = true
)
");

$this->dbStatement("
update edge_flush_tags
set obsolete = false
where index in ({$indexes})
and is_valid = true
and obsolete = true
");
}
}

public function dispatchInvalidationsForModel(Collection|string|Model $models): void {
Helpers::debug([
'dispatchInvalidationsForModel - models: ',
$models->map(fn(Model $model) => get_class($model)." ({$model->id})")->implode(', ')
]);

if (blank($models)) {
return;
}
Expand All @@ -218,25 +227,25 @@ public function dispatchInvalidationsForModel(Collection|string|Model $models):
return;
}

/**
* @var Model $model
*/
$model = $models instanceof Collection
? $models->first()
: $models;
$models = $this->onlyValidModels($models);

if (!$this->modelBelongsToProject($model)) {
$models = $this->notYetDispatched($models);

if ($models->isEmpty()) {
return;
}

/**
* @var Model $model
*/
$model = $models->first();

$model->wasRecentlyCreated
? $this->dispatchInvalidationsForCreatedModel($models)
: $this->dispatchInvalidationsForUpdatedModel($models);
}

public function dispatchInvalidationsForCreatedModel(
Collection|string|Model $models
): void {
public function dispatchInvalidationsForCreatedModel(Collection $models): void {
/**
* @var string $strategy
*/
Expand All @@ -251,9 +260,7 @@ public function dispatchInvalidationsForCreatedModel(
throw new \Exception("Strategy '{$strategy}' Not implemented");
}

public function dispatchInvalidationsForUpdatedModel(
Collection|string|Model $models
): void {
public function dispatchInvalidationsForUpdatedModel(Collection $models): void {
/**
* @var string $strategy
*/
Expand All @@ -269,23 +276,6 @@ public function dispatchInvalidationsForUpdatedModel(
throw new \Exception("Strategy '{$strategy}' Not implemented");
}

if (blank($models)) {
return;
}

$models =
$models instanceof Model ? collect([$models]) : collect($models);

$models = $models->filter(
fn($model) => $this->tagIsNotExcluded(
$model instanceof Model ? get_class($model) : $model,
),
);

if ($models->isEmpty()) {
return;
}

Helpers::debug(
'INVALIDATING tags for models: ' .
$models
Expand Down Expand Up @@ -448,6 +438,8 @@ public function invalidateAll(bool $force = false): Invalidation
$count = 0;

do {
Helpers::debug('Invalidating all tags... -> '.$count);

if ($count++ > 0) {
sleep(2);
}
Expand Down Expand Up @@ -682,10 +674,38 @@ public function markUrlsAsWarmed(Collection $urls): void
$this->dbStatement($sql);
}

public function modelBelongsToProject(Model $model): bool
public function onlyValidModels($models)
{
$models =
$models instanceof Model ? collect([$models]) : collect($models);

return $models->filter(
fn($model) => $this->tagIsNotExcluded(
$model instanceof Model ? get_class($model) : $model,
),
);
}

public function notYetDispatched($models)
{
$ignore = config('edge-flush.invalidations.models.ignore', []);
$tags = $models->mapWithKeys(
function ($model) {
$tag = $this->makeModelName(
$model
);

return [$tag => $tag];
}
);

$missing = $tags->diff($this->invalidationDispatched);

$this->invalidationDispatched = $this->invalidationDispatched->merge(
$missing
);

return !in_array(get_class($model), (array) $ignore);
return $models->filter(fn($model) => $missing->contains(
$this->makeModelName($model)
));
}
}

0 comments on commit 533d034

Please sign in to comment.