Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
ohdear_integration
Manage
Activity
Members
Labels
Plan
Wiki
Custom issue tracker
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
project
ohdear_integration
Commits
f45b367c
Commit
f45b367c
authored
8 months ago
by
Lio Novelli
Browse files
Options
Downloads
Patches
Plain Diff
Issue
#3450841
by useernamee, petar_basic: Caching issue
parent
bed75002
No related branches found
No related tags found
1 merge request
!23
Resolve #3450841 "Caching issue"
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
README.md
+18
-0
18 additions, 0 deletions
README.md
src/Controller/OhDearIntegrationController.php
+76
-30
76 additions, 30 deletions
src/Controller/OhDearIntegrationController.php
src/OhDearSdkService.php
+7
-0
7 additions, 0 deletions
src/OhDearSdkService.php
with
101 additions
and
30 deletions
README.md
+
18
−
0
View file @
f45b367c
...
...
@@ -82,3 +82,21 @@ about cron runs. Currently only default drupal cron is supported.
The cron ping uri can be overridden with
`OHDEAR_CRON_URI`
environment
variable.
### Caching
The healthcheck results endpoint allows caching but it is disabled by default.
To enable the caching manually add
`healthcheck_cache_max_age`
to the
`ohdear_integration.settings.yml`
config file with the value in seconds how
long the resource should be cached.
If
`healthcheck_cache_max_age`
configuration option is not provided, the
resource is not cached.
For this functionality to work properly requests to
`/json/oh-dear-health-check-results`
endpoint should come with the secret provided as URL query parameter and not
as secret header - if you have Drupal's internal page cache installed. Internal
page cache does not respect Cache contexts. One tricky way to resolve this issue
is to add a redirect for requests to endpoint with the
`oh-dear-health-check-secret`
header to the same enpoint but with the URL query parameter
`?oh-dear-health-check-secret=<value-of-header>`
.
This diff is collapsed.
Click to expand it.
src/Controller/OhDearIntegrationController.php
+
76
−
30
View file @
f45b367c
...
...
@@ -4,7 +4,6 @@ namespace Drupal\ohdear_integration\Controller;
use
Drupal\Core\Access\AccessResult
;
use
Drupal\Core\Cache\CacheableJsonResponse
;
use
Drupal\Core\Cache\CacheableMetadata
;
use
Drupal\Core\Cache\CacheableResponseInterface
;
use
Drupal\Core\Controller\ControllerBase
;
use
Drupal\Core\Logger\LoggerChannelFactoryInterface
;
...
...
@@ -22,6 +21,7 @@ use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
* Returns responses for OhDear Integration routes.
*/
class
OhDearIntegrationController
extends
ControllerBase
{
use
LoggerChannelTrait
;
/**
...
...
@@ -59,6 +59,13 @@ class OhDearIntegrationController extends ControllerBase {
*/
protected
$cacheMaxAge
;
/**
* Timestamp when monitoring results were computed.
*
* @var int|string|null
*/
protected
$finishedAt
;
/**
* Constructs OhDear integration controller.
*
...
...
@@ -112,30 +119,25 @@ class OhDearIntegrationController extends ControllerBase {
403
,
[
'Cache-Control'
=>
'private, no-cache, no-store, must-revalidate'
,
'Last-Modified'
=>
$this
->
formatDateString
(
$this
->
requestStack
->
getCurrentRequest
()
->
server
->
get
(
'REQUEST_TIME'
)
??
time
()),
],
TRUE
);
}
else
{
$data
=
$this
->
ohDearGenerator
->
getData
();
$
max_age
=
$this
->
getCacheMaxAge
()
;
$
this
->
finishedAt
=
json_decode
(
$data
,
TRUE
)[
'finishedAt'
]
??
'0'
;
$json_response
=
new
CacheableJsonResponse
(
$data
,
200
,
[
'Cache-Control'
=>
"public,max-age=
$max_age
,s-maxage=
$max_age
"
,
],
$this
->
computeHeaders
(),
TRUE
);
}
// Cache is mostly set outside of context.
$this
->
addCacheToResponse
(
$json_response
);
$cacheable_metadata
=
$json_response
->
getCacheableMetadata
();
$this
->
refineCacheMetadata
(
$cacheable_metadata
);
$json_response
->
addCacheableDependency
(
$cacheable_metadata
);
return
$json_response
;
});
$this
->
addCacheToResponse
(
$response
);
// If there is metadata left on the context, apply it on the response.
if
(
!
$context
->
isEmpty
())
{
if
(
$metadata
=
$context
->
pop
())
{
...
...
@@ -146,23 +148,50 @@ class OhDearIntegrationController extends ControllerBase {
return
$response
;
}
/**
* Return the header array.
*
* @return array
* Array of header names as keys and values as values.
*
* @throws \Exception
*/
protected
function
computeHeaders
():
array
{
$max_age
=
$this
->
getCacheMaxAge
()
??
0
;
$headers
=
[];
if
(
$max_age
)
{
$finishedAt
=
$this
->
finishedAt
??
0
;
if
(
!
$finishedAt
)
{
$this
->
getLogger
(
'ohdear_integration'
)
->
warning
(
'FinishedAt time is missing.'
);
}
$expires
=
(
int
)
$finishedAt
+
(
int
)
$max_age
;
$headers
[
'Cache-Control'
]
=
"public,max-age=
$max_age
,s-maxage=
$max_age
"
;
$headers
[
'Last-Modified'
]
=
$this
->
formatDateString
(
$finishedAt
);
$headers
[
'Expires'
]
=
$this
->
formatDateString
(
$expires
);
$headers
[
'ETag'
]
=
$finishedAt
;
}
else
{
$headers
[
'Cache-Control'
]
=
'private,no-cache,must-revalidate'
;
$headers
[
'Last-Modified'
]
=
$this
->
formatDateString
(
$this
->
requestStack
->
getCurrentRequest
()
->
server
->
get
(
'REQUEST_TIME'
)
??
time
());
}
return
$headers
;
}
/**
* Add cache configuration to response.
*
* @param CacheableResponseInterface $response
* @param
\Drupal\Core\Cache\
CacheableResponseInterface $response
* Response to add cache to.
*
* @return CacheableResponseInterface
* @return
\Drupal\Core\Cache\
CacheableResponseInterface
* Response with cache added.
*/
protected
function
addCacheToResponse
(
CacheableResponseInterface
$response
)
{
$cache_max_age
=
$this
->
getCacheMaxAge
();
if
(
!
$cache_max_age
||
!
$response
->
isCacheable
())
{
// 403 response is not cacheable.
$response
->
headers
->
set
(
'Cache-Control'
,
'private,no-cache,must-revalidate'
);
}
else
{
$response
->
headers
->
set
(
'Cache-Control'
,
"public,max-age=
$cache_max_age
,s-maxage=
$cache_max_age
"
);
if
(
!
$response
->
headers
->
has
(
'Cache-Control'
))
{
$headers
=
$this
->
computeHeaders
();
foreach
(
$headers
as
$header
=>
$value
)
{
$response
->
headers
->
set
(
$header
,
$value
);
}
}
$cacheable_metadata
=
$response
->
getCacheableMetadata
();
$this
->
refineCacheMetadata
(
$cacheable_metadata
);
...
...
@@ -171,7 +200,23 @@ class OhDearIntegrationController extends ControllerBase {
}
/**
* Get cache max age configuration
* Adds cache metadata related to the healthheck.
*
* @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $cacheable_dependency
* An object implementing RefinableCacheableDependencyInterface.
*/
protected
function
refineCacheMetadata
(
RefinableCacheableDependencyInterface
$cacheable_dependency
)
{
$cacheable_dependency
->
addCacheContexts
([
'url.query_args:oh-dear-health-check-secret'
,
'headers:oh-dear-health-check-secret'
,
'user.roles'
,
]);
$cacheable_dependency
->
addCacheTags
([
'monitoring_sensor_result'
]);
$cacheable_dependency
->
setCacheMaxAge
(
$this
->
getCacheMaxAge
()
??
0
);
}
/**
* Get cache max age configuration.
*
* @return mixed
*/
...
...
@@ -205,19 +250,20 @@ class OhDearIntegrationController extends ControllerBase {
}
/**
*
Adds cache metadata related to the healthheck
.
*
Convert timestamp to date string
.
*
* @param \Drupal\Core\Cache\RefinableCacheableDependencyInterface $cacheable_dependency
* An object implementing RefinableCacheableDependencyInterface.
* @param string $timestamp
* Timestamp.
*
* @return string
* Formatted date time.
*
* @throws \Exception
*/
protected
function
refineCacheMetadata
(
RefinableCacheableDependencyInterface
$cacheable_dependency
)
{
$cacheable_dependency
->
addCacheContexts
([
'url.query_args:oh-dear-health-check-secret'
,
'headers:oh-dear-health-check-secret'
,
'user.roles'
,
]);
$cacheable_dependency
->
addCacheTags
([
'monitoring_sensor_result'
]);
$cacheable_dependency
->
setCacheMaxAge
(
$this
->
getCacheMaxAge
()
??
0
);
protected
function
formatDateString
(
string
$timestamp
):
string
{
$date
=
new
\DateTimeImmutable
(
'@'
.
$timestamp
);
$date
=
$date
->
setTimezone
(
new
\DateTimeZone
(
'UTC'
));
return
$date
->
format
(
'D, d M Y H:i:s'
)
.
' GMT'
;
}
}
This diff is collapsed.
Click to expand it.
src/OhDearSdkService.php
+
7
−
0
View file @
f45b367c
...
...
@@ -57,6 +57,13 @@ class OhDearSdkService {
*/
protected
$ohDearCronUri
;
/**
* Value to be used in max-age property of Cache-Control header.
*
* @var string|int|null
*/
protected
$ohDearHealthcheckCacheMaxAge
;
/**
* Constructs an OhDearSdkService object.
*
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment