Details
Assignee
Michael OffnerMichael OffnerReporter
David RogersDavid RogersPriority
NewLabels
New Issue warning screen
Before you create a new Issue, please post to the mailing list first https://dev.lucee.org
Once the issue has been verified, one of the Lucee team will ask you to file an issue
Details
Details
Assignee
Michael Offner
Michael OffnerReporter
David Rogers
David RogersPriority
Labels
New Issue warning screen
Before you create a new Issue, please post to the mailing list first https://dev.lucee.org
Once the issue has been verified, one of the Lucee team will ask you to file an issue
Created 3 March 2023 at 14:50
Updated 29 May 2024 at 08:06
In the following code, a race between cachePut/cacheGet can result in the following behavior:
var x = {value: 42} cachePut("key", x) // other args to this aren't important var y = cacheGet("key") y.value = 43 expect(cacheGet("key").value).toBe(42) // fails, 43 was written to redis
The core of the issue seems to be that
cachePut
is not synchronous with respect to write completion, and aftercachePut
returns, but before the write to redis completes,cacheGet
will return a reference to the value which is queued for writing. If, prior to write completion, that reference itself is written to, the changes will be reflected when the the write to redis occurs.This manifested for us in the following way:
// thread1 var template = {value: "Hello {user}"} cachePut("key", template) // other args to this aren't important notifyWorldThatCacheIsCoherent() // assumes cachePut is synchronous // thread2 blockOnCoherentCache(); var assumedCopyOfTemplate = cacheGet("key") replace_USER_withName(assumedCopyOfTemplate, "Alice"); assert(assumedCopyOfTemplate.value == "Hello Alice") // much later blockOnCoherentCache(); var assumedCopyOfTemplate = cacheGet("key") // here we have {value: "Hello Alice"} replace_USER_withName(assumedCopyOfTemplate, "Bob"); assert(assumedCopyOfTemplate.value == "Hello Bob") // fails
Probably the driver’s implementation of
cachePut
should be synchronous, or support a synchronous mode.(aside: is there a guarantee that
cachePut
is synchronous, or is it up to the driver? It doesn’t seem to be mentioned in cachePut documentation. If a driver is asynchronous, is there an API to be notified of write completion (cachePut returns a Future<void> or something)? Most code seems to assume cachePut is synchronous.)