Disable caching for a single use case
Goal: make one cached use case stop using the cache — here, always serve
GET /events live — while every other cache keeps working with its defaults.
- Seam: the use-case interface (or its
Default*). - City files: one
@Service. - Applies to: both topologies.
The key fact
@Cacheable / @CacheEvict live on the platform default implementation and act on the
method that is actually invoked. Annotations are not inherited across an override, so
an override that simply omits @Cacheable is not cached — and because you only replace that
one use case, every other cache (cityPlaces, userProfile, the event detail cache, …) is
untouched.
modelcity.cache.* exposes a global toggle (enabled), a default-ttl and per-cache
TTLs (ttls.<name>) — but no per-cache disable flag. Turning off caching for one
operation is an override, not a config line. (You can set a very short TTL — see
Tune the cache — but that is throttling, not disabling.)
Recipe
Extend the default and override the method, dropping @Cacheable while keeping
@Transactional. Delegating to super reuses the platform body; the super call is a
self-invocation, so the default's @Cacheable never fires.
// com.modelcity.leisure.events.usecase.UncachedGetEventsUseCase
@Service
public class UncachedGetEventsUseCase extends DefaultGetEventsUseCase {
public UncachedGetEventsUseCase(EventStore<? extends EventView, EventRequestDto> eventStore) {
super(eventStore);
}
@Override
@Transactional(readOnly = true) // kept; @Cacheable intentionally omitted → not cached
public Page<EventSummaryDto> execute(EventType type, Boolean paid, int page, String locale) {
return super.execute(type, paid, page, locale);
}
}
DefaultGetEventsUseCase is @ModelCityDisabledIfInherited; your subclass covers the
GetEventsUseCase seam, so the default is removed at startup — no duplicate, no events
caching on this path.
Notes
- Where the annotation lives decides what you override. The
eventslist cache is on the use case (as above). Theeventdetail cache is on a separate@Component(CachedEventReader) injected intoDefaultGetEventUseCase— to bypass that one, your override ofGetEventUseCasemust read without going throughCachedEventReader. - The opposite direction is symmetric: an override that wants caching must re-declare
@Cacheable(see Override a read use case). - Writes evict via
@CacheEvict. If you disable a read cache, you can leave the matching evicts in place — evicting a cache nobody populates is harmless.
Verify
Enable the cache (CACHE_ENABLED=true) and hit GET /events twice: with the default it is
served from Valkey on the second call; with this override every call hits PostgreSQL, while a
second GET /city-places is still cache-served.