Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
869a8c26
Commit
869a8c26
authored
Sep 29, 2019
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.1.x'
Closes gh-18411
parents
fab80d69
a1fb1bcf
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
97 additions
and
2 deletions
+97
-2
CachingOperationInvoker.java
...tuate/endpoint/invoker/cache/CachingOperationInvoker.java
+39
-2
CachingOperationInvokerTests.java
.../endpoint/invoker/cache/CachingOperationInvokerTests.java
+58
-0
No files found.
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvoker.java
View file @
869a8c26
...
...
@@ -16,12 +16,17 @@
package
org
.
springframework
.
boot
.
actuate
.
endpoint
.
invoker
.
cache
;
import
java.time.Duration
;
import
java.util.Map
;
import
java.util.Objects
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
org.springframework.boot.actuate.endpoint.InvocationContext
;
import
org.springframework.boot.actuate.endpoint.invoke.OperationInvoker
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ObjectUtils
;
/**
...
...
@@ -29,10 +34,14 @@ import org.springframework.util.ObjectUtils;
* configurable time to live.
*
* @author Stephane Nicoll
* @author Christoph Dreis
* @author Phillip Webb
* @since 2.0.0
*/
public
class
CachingOperationInvoker
implements
OperationInvoker
{
private
static
final
boolean
IS_REACTOR_PRESENT
=
ClassUtils
.
isPresent
(
"reactor.core.publisher.Mono"
,
null
);
private
final
OperationInvoker
invoker
;
private
final
long
timeToLive
;
...
...
@@ -68,8 +77,8 @@ public class CachingOperationInvoker implements OperationInvoker {
CachedResponse
cached
=
this
.
cachedResponse
;
if
(
cached
==
null
||
cached
.
isStale
(
accessTime
,
this
.
timeToLive
))
{
Object
response
=
this
.
invoker
.
invoke
(
context
);
this
.
cachedResponse
=
new
CachedResponse
(
response
,
accessTime
);
return
response
;
cached
=
create
CachedResponse
(
response
,
accessTime
);
this
.
cachedResponse
=
cached
;
}
return
cached
.
getResponse
();
}
...
...
@@ -85,6 +94,13 @@ public class CachingOperationInvoker implements OperationInvoker {
return
false
;
}
private
CachedResponse
createCachedResponse
(
Object
response
,
long
accessTime
)
{
if
(
IS_REACTOR_PRESENT
)
{
return
new
ReactiveCachedResponse
(
response
,
accessTime
,
this
.
timeToLive
);
}
return
new
CachedResponse
(
response
,
accessTime
);
}
/**
* Apply caching configuration when appropriate to the given invoker.
* @param invoker the invoker to wrap
...
...
@@ -124,4 +140,25 @@ public class CachingOperationInvoker implements OperationInvoker {
}
/**
* {@link CachedResponse} variant used when Reactor is present.
*/
static
class
ReactiveCachedResponse
extends
CachedResponse
{
ReactiveCachedResponse
(
Object
response
,
long
creationTime
,
long
timeToLive
)
{
super
(
applyCaching
(
response
,
timeToLive
),
creationTime
);
}
private
static
Object
applyCaching
(
Object
response
,
long
timeToLive
)
{
if
(
response
instanceof
Mono
)
{
return
((
Mono
<?>)
response
).
cache
(
Duration
.
ofMillis
(
timeToLive
));
}
if
(
response
instanceof
Flux
)
{
return
((
Flux
<?>)
response
).
cache
(
Duration
.
ofMillis
(
timeToLive
));
}
return
response
;
}
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvokerTests.java
View file @
869a8c26
...
...
@@ -17,14 +17,18 @@
package
org
.
springframework
.
boot
.
actuate
.
endpoint
.
invoker
.
cache
;
import
java.security.Principal
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.junit.jupiter.api.Test
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
org.springframework.boot.actuate.endpoint.InvocationContext
;
import
org.springframework.boot.actuate.endpoint.SecurityContext
;
import
org.springframework.boot.actuate.endpoint.invoke.MissingParametersException
;
import
org.springframework.boot.actuate.endpoint.invoke.OperationInvoker
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
...
@@ -39,6 +43,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
* Tests for {@link CachingOperationInvoker}.
*
* @author Stephane Nicoll
* @author Christoph Dreis
* @author Phillip Webb
*/
class
CachingOperationInvokerTests
{
...
...
@@ -62,6 +68,30 @@ class CachingOperationInvokerTests {
assertCacheIsUsed
(
parameters
);
}
@Test
void
cacheInTtlWithMonoResponse
()
{
MonoOperationInvoker
.
invocations
=
0
;
MonoOperationInvoker
target
=
new
MonoOperationInvoker
();
InvocationContext
context
=
new
InvocationContext
(
mock
(
SecurityContext
.
class
),
Collections
.
emptyMap
());
CachingOperationInvoker
invoker
=
new
CachingOperationInvoker
(
target
,
500L
);
Object
response
=
((
Mono
<?>)
invoker
.
invoke
(
context
)).
block
();
Object
cachedResponse
=
((
Mono
<?>)
invoker
.
invoke
(
context
)).
block
();
assertThat
(
MonoOperationInvoker
.
invocations
).
isEqualTo
(
1
);
assertThat
(
response
).
isSameAs
(
cachedResponse
);
}
@Test
void
cacheInTtlWithFluxResponse
()
{
FluxOperationInvoker
.
invocations
=
0
;
FluxOperationInvoker
target
=
new
FluxOperationInvoker
();
InvocationContext
context
=
new
InvocationContext
(
mock
(
SecurityContext
.
class
),
Collections
.
emptyMap
());
CachingOperationInvoker
invoker
=
new
CachingOperationInvoker
(
target
,
500L
);
Object
response
=
((
Flux
<?>)
invoker
.
invoke
(
context
)).
blockLast
();
Object
cachedResponse
=
((
Flux
<?>)
invoker
.
invoke
(
context
)).
blockLast
();
assertThat
(
FluxOperationInvoker
.
invocations
).
isEqualTo
(
1
);
assertThat
(
response
).
isSameAs
(
cachedResponse
);
}
private
void
assertCacheIsUsed
(
Map
<
String
,
Object
>
parameters
)
{
OperationInvoker
target
=
mock
(
OperationInvoker
.
class
);
Object
expected
=
new
Object
();
...
...
@@ -122,4 +152,32 @@ class CachingOperationInvokerTests {
verify
(
target
,
times
(
2
)).
invoke
(
context
);
}
private
static
class
MonoOperationInvoker
implements
OperationInvoker
{
static
int
invocations
;
@Override
public
Object
invoke
(
InvocationContext
context
)
throws
MissingParametersException
{
return
Mono
.
fromCallable
(()
->
{
invocations
++;
return
Mono
.
just
(
"test"
);
});
}
}
private
static
class
FluxOperationInvoker
implements
OperationInvoker
{
static
int
invocations
;
@Override
public
Object
invoke
(
InvocationContext
context
)
throws
MissingParametersException
{
return
Flux
.
fromIterable
(()
->
{
invocations
++;
return
Arrays
.
asList
(
"spring"
,
"boot"
).
iterator
();
});
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment