Skip to content

Commit a5b1a14

Browse files
authored
Merge pull request #167 from bearsunday/attribute-interceptor-docs
Document cache attributes and interceptors
2 parents a039994 + 374a20e commit a5b1a14

15 files changed

+232
-12
lines changed

src-annotation/Cacheable.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@
66

77
use Attribute;
88

9+
/**
10+
* Marks a resource class as cacheable with TTL-based expiration
11+
*
12+
* Traditional time-based caching where cache expires after a specified duration.
13+
* For event-driven cache invalidation based on resource dependencies, use
14+
* #[CacheableResponse] or #[DonutCache] instead.
15+
*
16+
* Example:
17+
* ```php
18+
* // Cache for 1 hour
19+
* #[Cacheable(expirySecond: 3600)]
20+
*
21+
* // Cache with predefined expiry preset
22+
* #[Cacheable(expiry: 'short')] // short, medium, long, never
23+
*
24+
* // Cache until specific time from body field
25+
* #[Cacheable(expiryAt: 'expires_at')]
26+
* ```
27+
*
28+
* Interceptors bound:
29+
* - CacheInterceptor (onGet methods)
30+
* - CommandInterceptor (onPut/onPatch/onDelete methods)
31+
*
32+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#cacheable
33+
*/
934
#[Attribute(Attribute::TARGET_CLASS)]
1035
final class Cacheable
1136
{

src-annotation/CacheableResponse.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,42 @@
55
namespace BEAR\RepositoryModule\Annotation;
66

77
use Attribute;
8-
use BEAR\QueryRepository\DonutCacheableResponseInterceptor;
98
use BEAR\QueryRepository\DonutCacheModule;
10-
use BEAR\QueryRepository\DonutCommandInterceptor;
119

1210
/**
11+
* Enables event-driven cache invalidation for fully cacheable responses
12+
*
13+
* For content that is fundamentally static but changes predictably via resource
14+
* methods (onPut, onDelete, etc.). Unlike #[Cacheable] which uses TTL-based
15+
* expiration, this enables tag-based invalidation driven by resource dependencies.
16+
* The entire response is cached and receives an ETag for conditional requests,
17+
* enabling 304 (Not Modified) responses to reduce network transfer costs.
18+
*
19+
* Example:
20+
* ```php
21+
* #[CacheableResponse]
22+
* class Article extends ResourceObject
23+
* {
24+
* public function onGet(int $id): static
25+
* {
26+
* // ...
27+
* }
28+
*
29+
* #[RefreshCache]
30+
* public function onDelete(int $id): static
31+
* {
32+
* // ...
33+
* }
34+
* }
35+
* ```
36+
*
37+
* Interceptors bound:
38+
* - DonutCacheableResponseInterceptor (onGet methods when applied to class)
39+
* - DonutCommandInterceptor (onPut/onPatch/onDelete methods when applied to class)
40+
* - DonutCacheInterceptor (when applied to method)
41+
*
1342
* @see DonutCacheModule
14-
* @see DonutCacheableResponseInterceptor
15-
* @see DonutCommandInterceptor
43+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#event-driven-content
1644
*/
1745
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
1846
final class CacheableResponse

src-annotation/DonutCache.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,33 @@
66

77
use Attribute;
88
use BEAR\QueryRepository\DonutCacheModule;
9-
use BEAR\QueryRepository\DonutCommandInterceptor;
109

1110
/**
11+
* Enables event-driven donut caching for resources with non-cacheable embedded content
12+
*
13+
* For content that is fundamentally static but changes predictably via resource
14+
* methods, with some embedded resources that cannot be cached. Unlike #[Cacheable]
15+
* which uses TTL-based expiration, this enables tag-based invalidation. Only
16+
* cacheable portions are stored; no ETag is generated for the entire response.
17+
*
18+
* Example:
19+
* ```php
20+
* #[DonutCache]
21+
* class BlogPosting extends ResourceObject
22+
* {
23+
* #[Embed(rel: 'comment', src: 'app://self/comments')]
24+
* public function onGet(int $id): static
25+
* {
26+
* // ...
27+
* }
28+
* }
29+
* ```
30+
*
31+
* Interceptors bound:
32+
* - DonutCacheInterceptor (onGet methods when applied to class, or any method when applied to method)
33+
*
1234
* @see DonutCacheModule
13-
* @see DonutCacheInterceptor
14-
* @see DonutCommandInterceptor
35+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#donut-cache
1536
*/
1637
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
1738
final class DonutCache

src-annotation/HttpCache.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,28 @@
1515
*
1616
* Builds a complex Cache-Control header
1717
*
18+
* Example:
19+
* ```php
20+
* // Cache for 1 hour
21+
* #[HttpCache(maxAge: 3600)]
22+
*
23+
* // Cache with revalidation when stale
24+
* #[HttpCache(maxAge: 3600, mustRevalidate: true)]
25+
*
26+
* // Private cache (not shared cache like CDN)
27+
* #[HttpCache(isPrivate: true, maxAge: 300)]
28+
*
29+
* // CDN cache for 1 hour, browser cache for 5 minutes
30+
* #[HttpCache(maxAge: 300, sMaxAge: 3600)]
31+
*
32+
* // For disabling cache, use #[NoHttpCache] instead
33+
* ```
34+
*
35+
* Interceptors bound:
36+
* - HttpCacheInterceptor (onGet methods)
37+
*
1838
* @see HttpCacheInterceptor
39+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html
1940
*/
2041
#[Attribute(Attribute::TARGET_CLASS)]
2142
final class HttpCache extends AbstractCacheControl

src-annotation/NoHttpCache.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
*
1313
* Simplified notation to say that you don't want anything cached
1414
*
15+
* Interceptors bound:
16+
* - HttpCacheInterceptor (onGet methods)
17+
*
1518
* @see HttpCacheInterceptor
19+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html
1620
*/
1721
#[Attribute(Attribute::TARGET_CLASS)]
1822
final class NoHttpCache extends AbstractCacheControl

src-annotation/Purge.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,27 @@
66

77
use Attribute;
88

9-
/** @see RefreshInterceptor */
9+
/**
10+
* Purges cache for specified URI after command execution
11+
*
12+
* Behavior differs based on class attributes:
13+
* - **#[Cacheable] classes**: CommandInterceptor automatically binds to all
14+
* command methods (onPut/onPatch/onDelete) and processes #[Purge] annotations
15+
* - **Non-Cacheable classes**: RefreshInterceptor binds only to methods explicitly
16+
* marked with #[Purge] or #[Refresh]
17+
*
18+
* Example:
19+
* ```php
20+
* #[Purge(uri: 'app://self/user/profile?user_id={id}')]
21+
* #[Purge(uri: 'app://self/user/friend?user_id={id}')]
22+
* public function onDelete(int $id): static
23+
* {
24+
* // ...
25+
* }
26+
* ```
27+
*
28+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#tag-based-cache-invalidation
29+
*/
1030
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
1131
final class Purge extends AbstractCommand
1232
{

src-annotation/Refresh.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,27 @@
55
namespace BEAR\RepositoryModule\Annotation;
66

77
use Attribute;
8-
use BEAR\QueryRepository\RefreshInterceptor;
98

10-
/** @see RefreshInterceptor */
9+
/**
10+
* Refreshes cache for specified URI after command execution
11+
*
12+
* Behavior differs based on class attributes:
13+
* - **#[Cacheable] classes**: CommandInterceptor automatically binds to all
14+
* command methods (onPut/onPatch/onDelete) and processes #[Refresh] annotations
15+
* - **Non-Cacheable classes**: RefreshInterceptor binds only to methods explicitly
16+
* marked with #[Purge] or #[Refresh]
17+
*
18+
* Example:
19+
* ```php
20+
* #[Refresh(uri: 'app://self/user/profile?user_id={id}')]
21+
* public function onPut(int $id, string $name): static
22+
* {
23+
* // ...
24+
* }
25+
* ```
26+
*
27+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#event-driven-content
28+
*/
1129
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
1230
final class Refresh extends AbstractCommand
1331
{

src-annotation/RefreshCache.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@
55
namespace BEAR\RepositoryModule\Annotation;
66

77
use Attribute;
8-
use BEAR\QueryRepository\DonutCommandInterceptor;
98

10-
/** @see DonutCommandInterceptor */
9+
/**
10+
* Refreshes donut cache after command execution
11+
*
12+
* Interceptors bound:
13+
* - DonutCacheInterceptor
14+
*
15+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#cache-invalidation
16+
*/
1117
#[Attribute(Attribute::TARGET_METHOD)]
1218
final class RefreshCache
1319
{

src/CacheInterceptor.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@
1717

1818
use const E_USER_WARNING;
1919

20+
/**
21+
* Interceptor for TTL-based caching on CQRS queries with #[Cacheable]
22+
*
23+
* Bound to query methods (onGet) of classes marked with #[Cacheable].
24+
* Retrieves cached resource state if available, otherwise executes
25+
* the method and stores the result with configured TTL.
26+
*
27+
* @see \BEAR\RepositoryModule\Annotation\Cacheable
28+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#cacheable
29+
*/
2030
final readonly class CacheInterceptor implements MethodInterceptor
2131
{
2232
public function __construct(

src/CommandInterceptor.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@
1212
use Ray\Aop\MethodInterceptor;
1313
use Ray\Aop\MethodInvocation;
1414

15+
/**
16+
* Interceptor for cache invalidation on CQRS commands with #[Purge] or #[Refresh]
17+
*
18+
* Automatically bound to all command methods (onPut/onPatch/onDelete) of #[Cacheable] classes.
19+
* Processes #[Purge] and #[Refresh] annotations on these methods and executes cache
20+
* invalidation after successful write operations.
21+
*
22+
* For non-Cacheable classes, use RefreshInterceptor instead by explicitly marking methods
23+
* with #[Purge] or #[Refresh].
24+
*
25+
* @see \BEAR\RepositoryModule\Annotation\Purge
26+
* @see \BEAR\RepositoryModule\Annotation\Refresh
27+
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#tag-based-cache-invalidation
28+
*/
1529
final readonly class CommandInterceptor implements MethodInterceptor
1630
{
1731
/** @param CommandInterface[] $commands */

0 commit comments

Comments
 (0)