Skip to content

Commit

Permalink
Refresh cache only after request ends
Browse files Browse the repository at this point in the history
  • Loading branch information
bencroker committed Aug 26, 2024
1 parent a22a828 commit 322be36
Show file tree
Hide file tree
Showing 24 changed files with 344 additions and 511 deletions.
38 changes: 35 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,45 @@

## 5.7.0 - Unreleased

> [!IMPORTANT]
> To ensure the changes are applied, the cache should be refreshed after this update completes.
### Added

- Added compatibility for tracking of relation fields in Craft 5.3.0.
- Added compatibility for detecting eager-loading opportunities in the Blitz Hints utility in Craft 5.3.0.
- Added a check for whether the cache should be refreshed after every request has ended, meaning that setting the `RefreshCacheService::batchMode` property no longer serves a purposes and can be safely removed.
- Added compatibility with Craft 5.3.0 for detecting eager-loading opportunities in the Blitz Hints utility.

### Changed

- The expiry date displayed in the element sidebar panel now reflects the entry’s expiry date, if set and sooner than the cached page’s expiry date ([#698](https://github.com/putyourlightson/craft-blitz/issues/698)).
- Changed the default cache control header values back their more explicit values.
- The `refreshCacheEnabled` config setting is now actually respected.

### Fixed

- Fixed the nested element type count displayed in the Blitz Diagnostics utility.
- Fixed a bug in which the date cached and expiry dates were not being displayed in the correct timezone in the element sidebar panel ([#698](https://github.com/putyourlightson/craft-blitz/issues/698)).
- Fixed a bug in which the homepage was not being displayed as cached in the element sidebar panel.
- Fixed a bug that was causing integrity constraint violation errors to be logged ([#699](https://github.com/putyourlightson/craft-blitz/issues/699)).

### Deprecated

- Deprecated the `RefreshCacheService::batchMode` property.

## 5.6.4 - 2024-08-15

> [!NOTE]
> The cache should be cleared or refreshed after this update completes.
### Changed

- Recreated some database tables to ensure that composite primary keys are correctly created.

## 5.6.3 - 2024-08-15

### Fixed

- Fixed an exception that could be thrown during database migrations when using MariaDB ([#693](https://github.com/putyourlightson/craft-blitz/issues/693)).

## 5.6.2 - 2024-08-05

Expand Down Expand Up @@ -156,7 +187,8 @@

### Changed

The `blitz/cache/refresh-cache-tags` and `blitz/cache/refresh-expired-elements` no longer forcibly generate the cache.
The `blitz/cache/refresh-cache-tags` and
`blitz/cache/refresh-expired-elements` no longer forcibly generate the cache.

## 5.1.3 - 2024-04-13

Expand Down
85 changes: 16 additions & 69 deletions src/Blitz.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
use craft\events\RegisterUserPermissionsEvent;
use craft\helpers\UrlHelper;
use craft\log\MonologTarget;
use craft\queue\jobs\ResaveElements;
use craft\queue\Queue as CraftQueue;
use craft\services\Dashboard;
use craft\services\Elements;
use craft\services\Plugins;
Expand Down Expand Up @@ -67,7 +65,6 @@
use yii\di\Instance;
use yii\log\Dispatcher;
use yii\log\Logger;
use yii\queue\ExecEvent;
use yii\queue\Queue;

/**
Expand Down Expand Up @@ -119,7 +116,7 @@ public static function config(): array
/**
* @inheritdoc
*/
public string $schemaVersion = '5.6.0';
public string $schemaVersion = '5.7.0.1';

/**
* @inheritdoc
Expand All @@ -146,17 +143,24 @@ public function init(): void
$this->registerVariables();
$this->registerLogTarget();

// Potentially refresh the cache at the end of every request
Craft::$app->onAfterRequest(function() {
$this->refreshCache->refresh();
});

// Register events
$this->registerCacheableRequestEvents();
$this->registerElementEvents();
$this->registerResaveElementEvents();
$this->registerStructureEvents();
$this->registerIntegrationEvents();
$this->registerHintsUtilityEvents();
$this->registerClearCaches();
if ($this->settings->refreshCacheEnabled) {
$this->registerElementEvents();
$this->registerStructureEvents();
$this->registerIntegrationEvents();
}

// Register control panel events
if (Craft::$app->getRequest()->getIsCpRequest()) {
// Register site and control panel events
if (Craft::$app->getRequest()->getIsSiteRequest()) {
$this->registerHintsUtilityEvents();
} else {
$this->registerCpUrlRules();
$this->registerUtilities();
$this->registerWidgets();
Expand Down Expand Up @@ -305,7 +309,7 @@ private function registerLogTarget(): void
*/
private function registerCacheableRequestEvents(): void
{
// Register application init event
// Register web application init event
Event::on(Application::class, Application::EVENT_INIT,
function() {
$this->cacheRequest->setDefaultCacheControlHeader();
Expand Down Expand Up @@ -404,57 +408,6 @@ function(ElementEvent|MultiElementActionEvent $event) {
}
}

/**
* Registers resave element events.
*
* Using Craft’s bulk operations events is not possible, since we need to track changes and the bulk operation can span multiple requests.
* https://craftcms.com/docs/5.x/extend/events.html#bulk-operations
*/
private function registerResaveElementEvents(): void
{
// Enable batch mode
$events = [
[Elements::class, Elements::EVENT_BEFORE_RESAVE_ELEMENTS],
[Elements::class, Elements::EVENT_BEFORE_PROPAGATE_ELEMENTS],
];
foreach ($events as $event) {
Event::on($event[0], $event[1],
function() {
$this->refreshCache->batchMode = true;
}
);
}

Event::on(Queue::class, Queue::EVENT_BEFORE_EXEC,
function(ExecEvent $event) {
if ($event->job instanceof ResaveElements) {
$this->refreshCache->batchMode = true;
}
}
);

// Refresh the cache
$events = [
[Elements::class, Elements::EVENT_AFTER_RESAVE_ELEMENTS],
[Elements::class, Elements::EVENT_AFTER_PROPAGATE_ELEMENTS],
];
foreach ($events as $event) {
Event::on($event[0], $event[1],
function() {
$this->refreshCache->refresh();
}
);
}

Event::on(CraftQueue::class, CraftQueue::EVENT_AFTER_EXEC_AND_RELEASE,
function(ExecEvent $event) {
if ($event->job instanceof ResaveElements) {
$this->refreshCache->refresh();
}
}
);
}

/**
* Registers structure events
*/
Expand Down Expand Up @@ -488,16 +441,10 @@ function() {
*/
private function registerHintsUtilityEvents(): void
{
// Ignore CP requests.
if (Craft::$app->getRequest()->getIsCpRequest()) {
return;
}

if (!$this->settings->hintsEnabled) {
return;
}

// Add the event listener without “appending”, so it triggers as early as possible.
Event::on(ElementQuery::class, ElementQuery::EVENT_BEFORE_PREPARE,
function(CancelableEvent $event) {
/** @var ElementQuery $elementQuery */
Expand Down
8 changes: 3 additions & 5 deletions src/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@
// `\putyourlightson\blitz\models\SettingsModel::QUERY_STRINGS_CACHE_URLS_AS_SAME_PAGE`: Cache URLs with query strings as the same page
//'queryStringCaching' => \putyourlightson\blitz\models\SettingsModel::QUERY_STRINGS_DO_NOT_CACHE_URLS,


// The query string parameters to include (retain) when caching a URL (regular expressions may be used).
//'includedQueryStringParams' => [
// [
Expand Down Expand Up @@ -195,7 +194,7 @@
// Whether the cache should be refreshed when an element is saved but not live.
//'refreshCacheWhenElementSavedNotLive' => false,

// Whether non-HTML responses should be cached. With this setting enabled, Blitz will also cache pages that return non-HTML responses. If enabled, you should ensure that URIs that should not be caches, such as API endpoints, XML sitemaps, etc. are added as excluded URI patterns.
// Whether non-HTML responses should be cached. With this setting enabled, Blitz will also cache pages that return non-HTML responses. If enabled, you should ensure that URIs that should not be cached, such as API endpoints, XML sitemaps, etc. are added as excluded URI patterns.
//'cacheNonHtmlResponses' => false,

// Whether elements should be tracked in the database.
Expand Down Expand Up @@ -226,18 +225,17 @@
// The integrations to initialise.
//'integrations' => [
// 'putyourlightson\blitz\drivers\integrations\CommerceIntegration',
// 'putyourlightson\blitz\drivers\integrations\FeedMeIntegration',
// 'putyourlightson\blitz\drivers\integrations\SeomaticIntegration',
//],

// The value to send in the cache control header for non-cached pages.
//'defaultCacheControlHeader' => 'no-store',

// The value to send in the cache control header for cached pages.
//'cacheControlHeader' => 'public, maxage=31536000',
//'cacheControlHeader' => 'public, s-maxage=31536000, max-age=0',

// The value to send in the cache control header for expired pages.
//'cacheControlHeaderExpired' => 'public, maxage=5',
//'cacheControlHeaderExpired' => 'public, s-maxage=5, max-age=0',

// Whether an `X-Powered-By: Blitz` header should be added to the response.
//'sendPoweredByHeader' => true,
Expand Down
25 changes: 3 additions & 22 deletions src/drivers/integrations/FeedMeIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@

namespace putyourlightson\blitz\drivers\integrations;

use craft\feedme\services\Process;
use putyourlightson\blitz\Blitz;
use yii\base\Event;

/**
* @deprecated in 5.7.0
*/
class FeedMeIntegration extends BaseIntegration
{
/**
Expand All @@ -20,22 +19,4 @@ public static function getRequiredPlugins(): array
['handle' => 'feed-me', 'version' => '4.0.0'],
];
}

/**
* @inheritdoc
*/
public static function registerEvents(): void
{
Event::on(Process::class, Process::EVENT_BEFORE_PROCESS_FEED,
function() {
Blitz::$plugin->refreshCache->batchMode = true;
}
);

Event::on(Process::class, Process::EVENT_AFTER_PROCESS_FEED,
function() {
Blitz::$plugin->refreshCache->refresh();
}
);
}
}
4 changes: 0 additions & 4 deletions src/drivers/integrations/SeomaticIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ function(InvalidateContainerCachesEvent $event) {

if (!empty($elementIds)) {
Blitz::$plugin->refreshCache->addElementIds($elementQuery->elementType, $elementIds);

if (Blitz::$plugin->refreshCache->batchMode === false) {
Blitz::$plugin->refreshCache->refresh();
}
}
}
// Don't refresh cache for single URIs, since Blitz takes care of that for us.
Expand Down
10 changes: 4 additions & 6 deletions src/helpers/ElementQueryHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,11 @@ public static function getNormalizedElementQueryIdParam(mixed $value): mixed
}

/**
* Returns whether the element query has numeric IDs that may be related element IDs.
* Returns whether the element query has numeric element IDs.
*
* @see BaseRelationField::getRelationTargetIds()
*/
public static function hasRelatedElementIds(ElementQuery $elementQuery): bool
public static function hasNumericElementIds(ElementQuery $elementQuery): bool
{
if (!is_array($elementQuery->id)) {
return false;
Expand Down Expand Up @@ -454,13 +454,11 @@ public static function isNestedEntryQuery(ElementQuery $elementQuery): bool
}

/**
* Evaluate whether the element query has an owner.
* Evaluate whether the element query is for a specific field and owner.
*
* @see EntryQuery::beforePrepare()
*/
return !empty($elementQuery->fieldId)
|| !empty($elementQuery->ownerId)
|| !empty($elementQuery->primaryOwnerId);
return !empty($elementQuery->fieldId) && !empty($elementQuery->ownerId);
}

/**
Expand Down
21 changes: 17 additions & 4 deletions src/helpers/ElementSidebarHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use craft\elements\Category;
use craft\elements\Entry;
use craft\events\DefineElementEditorHtmlEvent;
use craft\helpers\Db;
use craft\helpers\DateTimeHelper;
use craft\helpers\Html;
use craft\helpers\UrlHelper;
use putyourlightson\blitz\Blitz;
Expand Down Expand Up @@ -75,20 +75,33 @@ private static function metaFieldsHtml(Element $element): string
'siteId' => $element->siteId,
'uri' => $element->uri,
]);
if ($siteUri->uri === Element::HOMEPAGE_URI) {
$siteUri->uri = '';
}
$cachedValue = Blitz::$plugin->cacheStorage->get($siteUri);

/** @var CacheRecord|null $cacheRecord */
$cacheRecord = CacheRecord::find()
->where($siteUri->toArray())
->one();

$dateCached = $cacheRecord ? DateTimeHelper::toDateTime($cacheRecord->dateCached) : null;
$expiryDate = $cacheRecord ? DateTimeHelper::toDateTime($cacheRecord->expiryDate) : null;

if (property_exists($element, 'expiryDate')) {
$elementExpiryDate = DateTimeHelper::toDateTime($element->expiryDate);
if ($elementExpiryDate) {
$expiryDate = $expiryDate ? min($elementExpiryDate, $expiryDate) : $elementExpiryDate;
}
}

$html = Craft::$app->getView()->renderTemplate('blitz/_element-sidebar', [
'cached' => !empty($cachedValue),
'expired' => $cacheRecord && $cacheRecord->expiryDate && $cacheRecord->expiryDate <= Db::prepareDateForDb('now'),
'expired' => $expiryDate && $expiryDate <= DateTimeHelper::toDateTime('now'),
'isCacheable' => Blitz::$plugin->cacheRequest->getIsCacheableSiteUri($siteUri),
'pageId' => $cacheRecord->id ?? null,
'dateCached' => $cacheRecord->dateCached ?? null,
'expiryDate' => $cacheRecord->expiryDate ?? null,
'dateCached' => $dateCached,
'expiryDate' => $expiryDate,
'refreshActionUrl' => UrlHelper::actionUrl('blitz/cache/refresh-page', $siteUri->toArray()),
]);

Expand Down
7 changes: 7 additions & 0 deletions src/helpers/IntegrationHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ public static function getAllIntegrations(): array
{
$integrations = Blitz::$plugin->settings->integrations;

// Only return integrations that exist (to prevent using legacy integrations).
foreach ($integrations as $key => $integration) {
if (!class_exists($integration)) {
unset($integrations[$key]);
}
}

$event = new RegisterComponentTypesEvent([
'types' => $integrations,
]);
Expand Down
Loading

0 comments on commit 322be36

Please sign in to comment.