package play.api.cache
import java.time.Instant
import java.util.concurrent.atomic.AtomicInteger
import scala.concurrent.duration.*
import scala.util.Random
import jakarta.inject.*
import play.api.cache.ehcache.EhCacheApi
import play.api.http
import play.api.mvc.*
import play.api.test.*
import play.api.Application
import scala.concurrent.Future
class CachedSpec2 extends PlaySpecification {
sequential
def cached(implicit app: Application) = {
new Cached(app.injector.instanceOf[AsyncCacheApi])(using app.materializer)
}
// Tests here don't use the body
val Action = ActionBuilder.ignoringBody
"the cached action" should {
"refresh only if content changed" in new WithApplication() {
override def running() = {
var content = "1"
val action = cached(using app)(_.uri, duration = 1)(Action(Results.Ok(content)))
val resultA = action(FakeRequest("GET", "/a")).run()
status(resultA) must_== 200
contentAsString(resultA) must_== content
def useOldEtag(from: Future[Result] = resultA) =
action(FakeRequest("GET", "/a").withHeaders(IF_NONE_MATCH -> header(ETAG, from).get)).run()
status(useOldEtag()) must_== NOT_MODIFIED
Thread.sleep(1500) // sleep to expire cache
val resultAA = useOldEtag() // old etag refreshes cache
status(resultAA) must_== 200 // same content is returned on first request
header(ETAG, resultAA).get must_== header(ETAG, resultA).get
header(EXPIRES, resultAA).get must_!= header(EXPIRES, resultA).get // expires is updated
val resultAAA = useOldEtag() // subsequent requests have same etag and expires
status(resultAAA) must_== NOT_MODIFIED
header(ETAG, resultAA).get must_== header(ETAG, resultAAA).get
header(EXPIRES, resultAA).get must_== header(EXPIRES, resultAAA).get
// but updating content invalidates the old etag
content = "2"
Thread.sleep(1500) // sleep to expire cache
val resultB = useOldEtag()
status(resultB) must_== 200
contentAsString(resultB) must_== content
status(useOldEtag()) must_== 200
status(useOldEtag(from = resultB)) must_== NOT_MODIFIED
}
}
}
}
this causes sending a complete response to all clients every time cache entry expires, even if it did not change
here is a test with desired behavior for play 3.0.10
this causes sending a complete response to all clients every time cache entry expires, even if it did not change