Michael Maraist - 2009-08-09

I've had three expiration policy issues related how date-created and date-last-accessed are used (forgive me, I don't have the source/doc's in front of my, so the names are aliases)

My understanding is that
max-age relates to date-created and is set on every put and is immutable.
max-idle relates to date-last-accessed which is set on every successful get.

However, the max-idle can expire an element on a get, even if the item is still there.  Producing, what I consider a useless expiration + rebuilding.

Now I imagine in some alter-universe there is a use-case where this is the desired action.  But consider web session data.  You give
max-age: 1 day
max-idle: 30 min (corresponds to the session-timeout)

Every miss will be immediately succeeded by a put of the rebuild item.

The expirations are really only there for good-candidate expiration selection.

If they happen to click in 31 minutes - it really isn't desirable to trigger the eviction.

The second type of situation is that max-age is used to define when the data is no longer trust-worthy.  If that's the case, I can't imagine a use-case where max-idle also defines max-trust-worthiness - how could a read renew it's validity?  (Though maybe something like version-checked hibernate could assert this condition).  But it would trigger an eviction of that node anyway after mutation due to version mismatching.

The third type is when the caller can renew the max-age based on knowledge of the current context.  Meaning on each get, it might be able to know that the element SHOULD only live for x seconds, or CAN live for at least X more seconds.

Thus I recommend a new configuration-item (possibly even the default)

expire-get-on-idle:

Namely, if we do a get and this mode is off, we ONLY check for max-age.

The max-age and max-idle are checked when searching for desirable eviction candidates on a put.

The second use-case that I've been hit with, are expiring data at exactly midnight.. This isn't currently possible - well, not without hacking, since the Element is immutable and final (which I agree is a good thing).

Ideally, the end-user can specify on the put an expiration timestamp.

What would seem to be a more natural Elmenent pair of fields are:

Element
  date_expires
  date_idles

Then the checks are

boolean isEvictionCandidate(long now) {  return date_idle < now || date_expires < now; }
boolean isExpired(long now) { return date_expires < now; }

This does several things.
1) Removes/consolidates the potentially expensive call to System.currentTimeInMillis 500 times (especially when checking dozens of elements for ideal eviction candidates).  The invoker trivially creates it, but also can reuse it.
2) Allows gets to avoid being expired needlessly
3) Dramatically simplifies the expiration-checker code
4) Allows configureable expiration policies
4a) For no expiration or only one form of expiration, the one or two timestamps are set to LONG.MAX_LONG, so they'll always fail the check
4b) For specialized expiration policies (such as midnight), the invoker can provide the expiration-timestamp.
4c) Expiration can potentially be recomputed by the caller (but this would require exposing setters for the two timestamps as public methods).

Now the problem, obvoiusly is that there might be 3'rd party code that relies on the existing timestamp getters, so there's a legacy issue.

Thoughts???