Use when building or modifying Java/Kotlin applications with CoCache two-level distributed coherent caching. Invoke for @CoCache cache interfaces, @JoinCacheable composition, Redis-backed coherence, Spring Boot integration, cache proxy behavior, custom cache backends, cache penetration protection (missing guards), cache breakdown protection, Redis failure policy (strict-failure, missing-guard sentinel), Redis TTL-drift test failures, or CoCache TCK tests.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add Ahoo-Wang/skills --skill cocache --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Cocache?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/ahoo-wang-cocache)More formats (shields.io, HTML) on the badges page.
---
name: cocache
description: Use when building or modifying Java/Kotlin applications with CoCache two-level distributed coherent caching. Invoke for @CoCache cache interfaces, @JoinCacheable composition, Redis-backed coherence, Spring Boot integration, cache proxy behavior, custom cache backends, cache penetration protection (missing guards), cache breakdown protection, Redis failure policy (strict-failure, missing-guard sentinel), Redis TTL-drift test failures, or CoCache TCK tests.
---
# CoCache Development Guide
CoCache is a Java/Kotlin two-level distributed coherent cache framework:
- L2 client-side cache: local Map, Guava, or Caffeine cache.
- L1 distributed cache: Redis-backed shared cache.
- Coherence: `CacheEvictedEventBus` publishes evictions so peer instances invalidate local entries.
## Start Here
Choose the smallest reference that fits the request:
| Task | Read |
|------|------|
| Add CoCache to a Spring or Spring Boot app; configure Redis failure behavior or the missing-guard sentinel | `references/setup.md` |
| Compose cached values with `@JoinCacheable` | `references/join-cache.md` |
| Write or update tests | `references/testing.md` |
| Implement a custom L1/L2 cache, event bus, key converter, or source | `references/custom-implementation.md` |
## Repository Rules
When editing this repository, follow `AGENTS.md`:
- Use `me.ahoo.test.asserts.assert` and `.assert()` in Kotlin tests; do not use AssertJ `assertThat()`.
- Extend the TCK specs in `cocache-test` for cache implementations.
- Ask before changing `cocache-api` public interfaces or adding dependencies.
- Run the relevant Gradle checks before finishing; prefer `./gradlew check` for broad changes.
## Core Model
Define one cache interface per cache domain. The interface extends `Cache<K, V>`, is annotated with `@CoCache`, and is registered through `@EnableCoCache`. CoCache creates a proxy at runtime.
```kotlin
@CoCache(keyPrefix = "user:", ttl = 120)
@GuavaCache(maximumSize = 1_000_000, expireAfterAccess = 120, expireUnit = TimeUnit.SECONDS)
interface UserCache : Cache<String, User>
@SpringBootApplication
@EnableCoCache(caches = [UserCache::class])
class App
```
Use caches through Kotlin operators: `cache[key]`, `cache[key] = value`, `cache.evict(key)`, and `cache.getCache(key)` when `CacheValue` metadata is required.
## Extension Points
CoCache auto-configures defaults, but each component can be overridden:
- Per cache, define named beans such as `UserCache.CacheSource`, `UserCache.ClientSideCache`, `UserCache.KeyConverter`, or `UserCache.JoinKeyExtractor`.
- Globally, define beans by type; auto-configured beans use `@ConditionalOnMissingBean`.
- For data loading, implement `CacheSource<K, V>.loadCacheValue(key)` and return `DefaultCacheValue.forever(value)`, `DefaultCacheValue.ttlAt(value, ttl)`, or bounded `DefaultCacheValue.missingGuard(ttl, amplitude)` values. Returning `null` for a missing key is also valid — CoCache auto-caches a missing guard with the cache's TTL (cache-penetration protection).
## Testing Pattern
CoCache provides abstract specs in `cocache-test` for compatibility coverage:
- `CacheSpec<K,V>` for base cache behavior.
- `ClientSideCacheSpec<V>` for L2 caches.
- `DistributedCacheSpec<V>` for L1 caches.
- `DefaultCoherentCacheSpec<K,V>` for two-level coherent cache behavior and cache breakdown protection.
- `MultipleInstanceSyncSpec<K,V>` and `CacheEvictedEventBusSpec` for cross-instance coherence and event buses.
Use the repo's `createCacheEntry(): Pair<K, V>` contract:
```kotlin
class MyDistributedCacheTest : DistributedCacheSpec<String>() {
override fun createCache(): DistributedCache<String> {
return MyDistributedCache()
}
override fun createCacheEntry(): Pair<String, String> {
return UUID.randomUUID().toString() to "test_value"
}
}
```
## Key Classes
| Class | Module | Purpose |
|-------|--------|---------|
| `Cache<K,V>` | cocache-api | Base cache interface |
| `CoherentCache<K,V>` | cocache-core | Two-level cache engine |
| `DefaultCoherentCache` | cocache-core | Default implementation |
| `ClientSideCache<V>` | cocache-api | L2 local cache interface |
| `MapClientSideCache` | cocache-core | ConcurrentHashMap impl |
| `GuavaClientSideCache` | cocache-core | Guava Cache impl |
| `CaffeineClientSideCache` | cocache-core | Caffeine Cache impl |
| `DistributedCache<V>` | cocache-core | L1 distributed cache interface |
| `RedisDistributedCache` | cocache-spring-redis | Redis impl |
| `CacheSource<K,V>` | cocache-api | Data source loader |
| `CacheEvictedEventBus` | cocache-core | Event bus for coherence |
| `RedisCacheEvictedEventBus` | cocache-spring-redis | Redis Pub/Sub impl |
| `JoinCache<K1,V1,K2,V2>` | cocache-api | Composed cache interface |
| `SimpleJoinCache` | cocache-core | Default JoinCache impl |
| `KeyFilter` | cocache-core | Bloom filter for cache breakdown protection |
| `BloomKeyFilter` | cocache-core | Guava BloomFilter impl |
## Build Commands
```bash
./gradlew build -x test
./gradlew test
./gradlew :cocache-core:test
./gradlew :cocache-core:test --tests "me.ahoo.cache.proxy.ProxyCacheTest"
./gradlew :cocache-spring-redis:check
./gradlew :cocache-spring-boot-starter:check
./gradlew check
```
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!