Reputation: 1
I am doing a sample project for managing some generic background jobs, mainly to practice how to work with cache in Spring Boot. My key problem is managing retention time for jobs, based on their state.
This is the job class
@Slf4j
@RequiredArgsConstructor
@Getter
public class Job implements Runnable {
private final UUID uuid;
private State state = State.READY;
@Override
public void run() {
log.info("Starting job {}", uuid);
state = State.RUNNING;
try {
Thread.sleep(1_000L * 60L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error(e.getMessage());
state = State.INTERRUPTED;
return;
}
state = State.COMPLETED;
}
public enum State {
READY,
RUNNING,
COMPLETED,
INTERRUPTED
}
}
I have created this Caffeine<UUID, Job>
bean, specifying my retention logic:
@Bean
public Caffeine<UUID, Job> caffeine() {
return Caffeine.newBuilder()
.expireAfter(new Expiry<>() {
@Override
public long expireAfterCreate(UUID uuid, Job job, long currentTime) {
return job.getState() == State.READY ? TimeUnit.DAYS.toNanos(3) : 0;
}
@Override
public long expireAfterUpdate(UUID uuid, Job job, long currentTime,
@NonNegative long currentDuration) {
return TimeUnit.DAYS.toNanos(
switch (job.getState()) {
case READY, INTERRUPTED -> 3;
case RUNNING, COMPLETED -> 1;
}
);
}
@Override
public long expireAfterRead(UUID uuid, Job job, long currentTime,
@NonNegative long currentDuration) {
return expireAfterUpdate(uuid, job, currentTime, currentDuration);
}
});
}
The issue arises when I want to integrate it with CaffeineCacheManager
.
CaffeineCacheManager#setCaffeine
requires Caffeine<Object, Object>
.
I am not even allowed to cast it:
@Bean
public CacheManager cacheManager(@Value("${spring.cache.cache-names}") String... cacheNames) {
var cacheManager = new CaffeineCacheManager(cacheNames);
cacheManager.setCaffeine((Caffeine<Object, Object>) caffeine());
return cacheManager;
}
inconvertible types; cannot cast 'com.github.benmanes.caffeine.cache.Caffeine<java.util.UUID,dev.jakublaba.backgroundprocessingapi.model.entity.Job>' to 'com.github.benmanes.caffeine.cache.Caffeine<java.lang.Object,java.lang.Object>'
The only thing I can think of right now is declaring caffeine
bean as Caffeine<Object, Object>
and do some absolutely atrocious casting inside Expiry
implementation, but is there a more elegant and type safe way to do this?
I am using Spring Boot 3.2.5 and Caffeine 3.1.8
Upvotes: 0
Views: 222
Reputation: 650
Not Type safe, but short:
@Bean
public CacheManager cacheManager(@Value("${spring.cache.cache-names}") String... cacheNames) {
var cacheManager = new CaffeineCacheManager(cacheNames);
cacheManager.setCaffeine((Caffeine) caffeine());
return cacheManager;
}
Upvotes: 1