Skip to content

Commit 533d034

Browse files
Fix app dispatching multiple invalidations on create
1 parent bf7a4c2 commit 533d034

File tree

3 files changed

+75
-47
lines changed

3 files changed

+75
-47
lines changed

config/edge-flush.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,18 @@
277277
*/
278278
'tags' => [
279279
'excluded-model-classes' => [
280+
// Twill modules
280281
'\Models\Translations*',
281282
'\Models\Slugs*',
282283
'\Models\Revisions*',
284+
285+
// Twill capsules
286+
'*\Models\*Translation',
287+
'*\Models\*Slug',
288+
'*\Models\*Revision',
289+
290+
// Other classes
291+
'Spatie\Activitylog\Models\Activity',
283292
],
284293

285294
'format' => 'app-%environment%-%sha1%',
@@ -326,10 +335,6 @@
326335
'strategy' => 'invalidate-all',
327336
]
328337
],
329-
330-
'models' => [
331-
'ignore' => \Spatie\Activitylog\Models\Activity::class,
332-
]
333338
],
334339

335340
/**

src/Services/Invalidation.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ public function absorbCloudFront(AwsResult $invalidation): self
101101
return $this;
102102
}
103103

104+
$statusCode = $invalidation['@metadata']['statusCode'];
105+
104106
$invalidation = Helpers::toArray($invalidation['Invalidation']);
105107

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

110112
$this->setId($invalidation['Id'] ?? null)
111113
->setStatus($invalidation['Status'] ?? null)
112-
->setCreatedAt($time);
114+
->setCreatedAt($time)
115+
->setSuccess($statusCode === 201);
113116

114117
return $this;
115118
}

src/Services/Tags.php

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ class Tags
2929

3030
protected Collection $tags;
3131

32+
protected Collection $invalidationDispatched;
33+
3234
public Collection $processedTags;
3335

3436
public function __construct()
3537
{
3638
$this->tags = collect();
3739

3840
$this->processedTags = collect();
41+
42+
$this->invalidationDispatched = collect();
3943
}
4044

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

185-
$this->dbStatement("
186-
update edge_flush_tags
187-
set obsolete = false
188-
where index in ({$indexes})
189-
and is_valid = true
190-
and obsolete = false
191-
");
192-
193189
$this->dbStatement("
194190
update edge_flush_urls
195191
set was_purged_at = null,
@@ -201,13 +197,26 @@ public function storeCacheTags(
201197
from edge_flush_tags
202198
where index in ({$indexes})
203199
and is_valid = true
204-
and obsolete = false
200+
and obsolete = true
205201
)
206202
");
203+
204+
$this->dbStatement("
205+
update edge_flush_tags
206+
set obsolete = false
207+
where index in ({$indexes})
208+
and is_valid = true
209+
and obsolete = true
210+
");
207211
}
208212
}
209213

210214
public function dispatchInvalidationsForModel(Collection|string|Model $models): void {
215+
Helpers::debug([
216+
'dispatchInvalidationsForModel - models: ',
217+
$models->map(fn(Model $model) => get_class($model)." ({$model->id})")->implode(', ')
218+
]);
219+
211220
if (blank($models)) {
212221
return;
213222
}
@@ -218,25 +227,25 @@ public function dispatchInvalidationsForModel(Collection|string|Model $models):
218227
return;
219228
}
220229

221-
/**
222-
* @var Model $model
223-
*/
224-
$model = $models instanceof Collection
225-
? $models->first()
226-
: $models;
230+
$models = $this->onlyValidModels($models);
227231

228-
if (!$this->modelBelongsToProject($model)) {
232+
$models = $this->notYetDispatched($models);
233+
234+
if ($models->isEmpty()) {
229235
return;
230236
}
231237

238+
/**
239+
* @var Model $model
240+
*/
241+
$model = $models->first();
242+
232243
$model->wasRecentlyCreated
233244
? $this->dispatchInvalidationsForCreatedModel($models)
234245
: $this->dispatchInvalidationsForUpdatedModel($models);
235246
}
236247

237-
public function dispatchInvalidationsForCreatedModel(
238-
Collection|string|Model $models
239-
): void {
248+
public function dispatchInvalidationsForCreatedModel(Collection $models): void {
240249
/**
241250
* @var string $strategy
242251
*/
@@ -251,9 +260,7 @@ public function dispatchInvalidationsForCreatedModel(
251260
throw new \Exception("Strategy '{$strategy}' Not implemented");
252261
}
253262

254-
public function dispatchInvalidationsForUpdatedModel(
255-
Collection|string|Model $models
256-
): void {
263+
public function dispatchInvalidationsForUpdatedModel(Collection $models): void {
257264
/**
258265
* @var string $strategy
259266
*/
@@ -269,23 +276,6 @@ public function dispatchInvalidationsForUpdatedModel(
269276
throw new \Exception("Strategy '{$strategy}' Not implemented");
270277
}
271278

272-
if (blank($models)) {
273-
return;
274-
}
275-
276-
$models =
277-
$models instanceof Model ? collect([$models]) : collect($models);
278-
279-
$models = $models->filter(
280-
fn($model) => $this->tagIsNotExcluded(
281-
$model instanceof Model ? get_class($model) : $model,
282-
),
283-
);
284-
285-
if ($models->isEmpty()) {
286-
return;
287-
}
288-
289279
Helpers::debug(
290280
'INVALIDATING tags for models: ' .
291281
$models
@@ -448,6 +438,8 @@ public function invalidateAll(bool $force = false): Invalidation
448438
$count = 0;
449439

450440
do {
441+
Helpers::debug('Invalidating all tags... -> '.$count);
442+
451443
if ($count++ > 0) {
452444
sleep(2);
453445
}
@@ -682,10 +674,38 @@ public function markUrlsAsWarmed(Collection $urls): void
682674
$this->dbStatement($sql);
683675
}
684676

685-
public function modelBelongsToProject(Model $model): bool
677+
public function onlyValidModels($models)
678+
{
679+
$models =
680+
$models instanceof Model ? collect([$models]) : collect($models);
681+
682+
return $models->filter(
683+
fn($model) => $this->tagIsNotExcluded(
684+
$model instanceof Model ? get_class($model) : $model,
685+
),
686+
);
687+
}
688+
689+
public function notYetDispatched($models)
686690
{
687-
$ignore = config('edge-flush.invalidations.models.ignore', []);
691+
$tags = $models->mapWithKeys(
692+
function ($model) {
693+
$tag = $this->makeModelName(
694+
$model
695+
);
696+
697+
return [$tag => $tag];
698+
}
699+
);
700+
701+
$missing = $tags->diff($this->invalidationDispatched);
702+
703+
$this->invalidationDispatched = $this->invalidationDispatched->merge(
704+
$missing
705+
);
688706

689-
return !in_array(get_class($model), (array) $ignore);
707+
return $models->filter(fn($model) => $missing->contains(
708+
$this->makeModelName($model)
709+
));
690710
}
691711
}

0 commit comments

Comments
 (0)