ben-manes / caffeine

A high performance caching library for Java
Apache License 2.0
15.9k stars 1.6k forks source link

ExpireAfterCreate test failing based on EndDate from cached object #1450

Closed dwalker64 closed 9 months ago

dwalker64 commented 9 months ago

I'm caching an object (JCache unfortunately). In the configuration I'm using one of the fields, LocalDate endDate, from the object to calculate when it should expire.

public long expireAfterCreate(String key, CacheObject cacheObject, long currentTime) {
     LocalDate expirationDate = cacheObject.getEndDate().plusDays(5);
     Duration duration = Duration.between(LocalDateTime.now(), LocalDateTime(expirationDate, LocalTime.MIDNIGHT));
     return duration;
}

I'm using FakeTicker in my test.

The particular test that's failing is:

ticker.advance(5, TimeUnit.DAYS);
assertNull(cache.get(key));

I've tried advancing 1 second beyond that point as well. But the object is still in the cache. I've also executed Thread.sleep(10* 1000); thinking that a background thread has not done its thing. But the object is still in the cache.

Not sure what I'm doing incorrectly here. Any guidance is much appreciated.

ben-manes commented 9 months ago

hmm.. can you write a self contained unit test or java project that I can step through? It shouldn't be returning an expired entry even if not yet discarded internally and instead fake a cache miss.

ben-manes commented 9 months ago

Here's some unit tests if somehow helpful...

dwalker64 commented 9 months ago

Here's an example. It's now failing on the 2 assertion:

ExpirationTest.java.txt

dwalker64 commented 9 months ago

Here's that build.gradle file:

/*

plugins { // Apply the application plugin to add support for building a CLI application in Java. id 'application' id "io.franzbecker.gradle-lombok" version "5.0.0" }

java.sourceCompatibility = JavaVersion.VERSION_1_8 java.targetCompatibility = JavaVersion.VERSION_1_8

lombok { version = "1.18.+" sha256 = "" // skip verifyLombok task }

repositories { // Use Maven Central for resolving dependencies. mavenCentral() }

dependencies { compileOnly 'org.projectlombok:lombok:1.18.28' annotationProcessor 'org.projectlombok:lombok'

// This dependency is used by the application.
implementation 'com.google.guava:guava:31.1-jre'
implementation 'com.google.inject:guice:5.0.1'
implementation 'org.jsr107.ri:cache-annotations-ri:1.1.1'
implementation 'com.github.ben-manes.caffeine:caffeine:2.9.1'
implementation 'com.github.ben-manes.caffeine:jcache:2.9.1'

// Use JUnit Jupiter for testing.
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
testImplementation 'org.junit.vintage:junit-vintage-engine:5.9.1'
testImplementation 'com.google.guava:guava-testlib:31.1-jre'

}

application { // Define the main class for the application. mainClass = 'jcacheexpirationexample.App' }

tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() }

ben-manes commented 9 months ago

Running your test and it fails for the opposite reason of the entry being null (not found). That is because you are setting the new duration to immediately expire after a read or update. If I change that to return currentDuration then your test passes.

@Override
public long expireAfterUpdate(@NonNull String key, @NonNull CachedObject value,
    long currentTime, @NonNegative long currentDuration) {
  return 0;
}

@Override
public long expireAfterRead(@NonNull String key, @NonNull CachedObject value,
    long currentTime, @NonNegative long currentDuration) {
  return 0;
}
dwalker64 commented 9 months ago

I changed those two methods to return currentDuration and it passes as you say.

In my production code, I am returning currentDuration and it's still failing. I'm left wondering what's different between my two tests.

ben-manes commented 9 months ago

if you'd like to jump on a teams or zoom I might be able to help debug you through it.

dwalker64 commented 9 months ago

Wow!!! So generous! How can I send you a zoom link privately?

ben-manes commented 9 months ago

ben.manes @ gmail

dwalker64 commented 9 months ago

Thank you for all your awesome help! You Rock!!!