<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Wed, Jul 22, 2015 at 10:53 AM Dan Berindei &lt;<a href="mailto:dan.berindei@gmail.com">dan.berindei@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Is it possible/feasible to skip the notification from the backups to<br>
the primary (and back) when there is no clustered expiration listener?<br></blockquote><div><br></div><div>Unfortunately there is no way to distinguish whether or a listener is create, modify, remove or expiration.  So this would only work if there are no clustered listeners.</div><div><br></div><div>This however should be feasible.  This shouldn&#39;t be hard to add.</div><div><br></div><div>The only thing I would have to figure out is what happens in the case of a rehash and the node that removed the value is now the primary owner and some nodes have the old value and someone registers an expiration listener.  I am thinking I should only raise the event if the primary owner still has the value.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Dan<br>
<br>
<br>
On Tue, Jul 21, 2015 at 5:25 PM, William Burns &lt;<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a>&gt; wrote:<br>
&gt; So I wanted to sum up what it looks like the plan is for this in regards to<br>
&gt; cluster expiration for ISPN 8.<br>
&gt;<br>
&gt; First off to not make it ambiguous, maxIdle being used with a clustered<br>
&gt; cache will provide undefined and unsupported behavior.  This can and will<br>
&gt; expire entries on a single node without notifying other cluster members<br>
&gt; (essentially it will operate as it does today unchanged).<br>
&gt;<br>
&gt; This leaves me to talk solely about lifespan cluster expiration.<br>
&gt;<br>
&gt; Lifespan Expiration events are fired by the primary owner of an expired key<br>
&gt;<br>
&gt; - when accessing an expired entry.<br>
&gt;<br>
&gt; - by the reaper thread.<br>
&gt;<br>
&gt; If the expiration is detected by a node other than the primary owner, an<br>
&gt; expiration command is sent to it and null is returned immediately not<br>
&gt; waiting for a response.<br>
&gt;<br>
&gt; Expiration event listeners follow the usual rules for sync/async: in the<br>
&gt; case of a sync listener, the handler is invoked while holding the lock,<br>
&gt; whereas an async listener will not hold locks.<br>
&gt;<br>
&gt; It is desirable for expiration events to contain both the key and value.<br>
&gt; However currently cache stores do not provide the value when they expire<br>
&gt; values.  Thus we can only guarantee the value is present when an in memory<br>
&gt; expiration event occurs.  We could plan on adding this later.<br>
&gt;<br>
&gt; Also as you may have guessed this doesn&#39;t touch strict expiration, which I<br>
&gt; think we have come to the conclusion should only work with maxIdle and as<br>
&gt; such this is not explored with this iteration.<br>
&gt;<br>
&gt; Let me know if you guys think this approach is okay.<br>
&gt;<br>
&gt; Cheers,<br>
&gt;<br>
&gt;  - Will<br>
&gt;<br>
&gt; On Tue, Jul 14, 2015 at 1:51 PM Radim Vansa &lt;<a href="mailto:rvansa@redhat.com" target="_blank">rvansa@redhat.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Yes, I know about [1]. I&#39;ve worked that around by storing timestamp in<br>
&gt;&gt; the entry as well and when a new record is added, the &#39;expired&#39;<br>
&gt;&gt; invalidations are purged. But I can&#39;t purge that if I don&#39;t access it -<br>
&gt;&gt; Infinispan needs to handle that internally.<br>
&gt;&gt;<br>
&gt;&gt; Radim<br>
&gt;&gt;<br>
&gt;&gt; [1] <a href="https://hibernate.atlassian.net/browse/HHH-6219" rel="noreferrer" target="_blank">https://hibernate.atlassian.net/browse/HHH-6219</a><br>
&gt;&gt;<br>
&gt;&gt; On 07/14/2015 05:45 PM, Dennis Reed wrote:<br>
&gt;&gt; &gt; On 07/14/2015 11:08 AM, Radim Vansa wrote:<br>
&gt;&gt; &gt;&gt; On 07/14/2015 04:19 PM, William Burns wrote:<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; On Tue, Jul 14, 2015 at 9:37 AM William Burns &lt;<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a><br>
&gt;&gt; &gt;&gt;&gt; &lt;mailto:<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       On Tue, Jul 14, 2015 at 4:41 AM Dan Berindei<br>
&gt;&gt; &gt;&gt;&gt;       &lt;<a href="mailto:dan.berindei@gmail.com" target="_blank">dan.berindei@gmail.com</a> &lt;mailto:<a href="mailto:dan.berindei@gmail.com" target="_blank">dan.berindei@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           Processing expiration only on the reaper thread sounds nice,<br>
&gt;&gt; &gt;&gt;&gt; but I<br>
&gt;&gt; &gt;&gt;&gt;           have one reservation: processing 1 million entries to see<br>
&gt;&gt; &gt;&gt;&gt; that<br>
&gt;&gt; &gt;&gt;&gt;           1 of<br>
&gt;&gt; &gt;&gt;&gt;           them is expired is a lot of work, and in the general case we<br>
&gt;&gt; &gt;&gt;&gt;           will not<br>
&gt;&gt; &gt;&gt;&gt;           be able to ensure an expiration precision of less than 1<br>
&gt;&gt; &gt;&gt;&gt;           minute (maybe<br>
&gt;&gt; &gt;&gt;&gt;           more, with a huge SingleFileStore attached).<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       This isn&#39;t much different then before.  The only difference is<br>
&gt;&gt; &gt;&gt;&gt;       that if a user touched a value after it expired it wouldn&#39;t show<br>
&gt;&gt; &gt;&gt;&gt;       up (which is unlikely with maxIdle especially).<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           What happens to users who need better precision? In<br>
&gt;&gt; &gt;&gt;&gt;           particular, I know<br>
&gt;&gt; &gt;&gt;&gt;           some JCache tests were failing because HotRod was only<br>
&gt;&gt; &gt;&gt;&gt; supporting<br>
&gt;&gt; &gt;&gt;&gt;           1-second resolution instead of the 1-millisecond resolution<br>
&gt;&gt; &gt;&gt;&gt;           they were<br>
&gt;&gt; &gt;&gt;&gt;           expecting.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       JCache is an interesting piece.  The thing about JCache is that<br>
&gt;&gt; &gt;&gt;&gt;       the spec is only defined for local caches.  However I wouldn&#39;t<br>
&gt;&gt; &gt;&gt;&gt;       want to muddy up the waters in regards to it behaving<br>
&gt;&gt; &gt;&gt;&gt; differently<br>
&gt;&gt; &gt;&gt;&gt;       for local/remote.  In the JCache scenario we could add an<br>
&gt;&gt; &gt;&gt;&gt;       interceptor to prevent it returning such values (we do something<br>
&gt;&gt; &gt;&gt;&gt;       similar already for events).  JCache behavior vs ISPN behavior<br>
&gt;&gt; &gt;&gt;&gt;       seems a bit easier to differentiate.  But like you are getting<br>
&gt;&gt; &gt;&gt;&gt; at,<br>
&gt;&gt; &gt;&gt;&gt;       either way is not very appealing.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           I&#39;m even less convinced about the need to guarantee that a<br>
&gt;&gt; &gt;&gt;&gt;           clustered<br>
&gt;&gt; &gt;&gt;&gt;           expiration listener will only be triggered once, and that<br>
&gt;&gt; &gt;&gt;&gt; the<br>
&gt;&gt; &gt;&gt;&gt;           entry<br>
&gt;&gt; &gt;&gt;&gt;           must be null everywhere after that listener was invoked.<br>
&gt;&gt; &gt;&gt;&gt;           What&#39;s the<br>
&gt;&gt; &gt;&gt;&gt;           use case?<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       Maybe Tristan would know more to answer.  To be honest this work<br>
&gt;&gt; &gt;&gt;&gt;       seems fruitless unless we know what our end users want here.<br>
&gt;&gt; &gt;&gt;&gt;       Spending time on something for it to thrown out is never fun :(<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       And the more I thought about this the more I question the<br>
&gt;&gt; &gt;&gt;&gt; validity<br>
&gt;&gt; &gt;&gt;&gt;       of maxIdle even.  It seems like a very poor way to prevent<br>
&gt;&gt; &gt;&gt;&gt; memory<br>
&gt;&gt; &gt;&gt;&gt;       exhaustion, which eviction does in a much better way and has<br>
&gt;&gt; &gt;&gt;&gt; much<br>
&gt;&gt; &gt;&gt;&gt;       more flexible algorithms.  Does anyone know what maxIdle would<br>
&gt;&gt; &gt;&gt;&gt; be<br>
&gt;&gt; &gt;&gt;&gt;       used for that wouldn&#39;t be covered by eviction?  The only thing I<br>
&gt;&gt; &gt;&gt;&gt;       can think of is cleaning up the cache store as well.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; Actually I guess for session/authentication related information this<br>
&gt;&gt; &gt;&gt;&gt; would be important.  However maxIdle isn&#39;t really as usable in that<br>
&gt;&gt; &gt;&gt;&gt; case since most likely you would have a sticky session to go back to<br>
&gt;&gt; &gt;&gt;&gt; that node which means you would never refresh the last used date on<br>
&gt;&gt; &gt;&gt;&gt; the copies (current implementation).  Without cluster expiration you<br>
&gt;&gt; &gt;&gt;&gt; could lose that session information on a failover very easily.<br>
&gt;&gt; &gt;&gt; I would say that maxIdle can be used as for memory management as kind<br>
&gt;&gt; &gt;&gt; of<br>
&gt;&gt; &gt;&gt; WeakHashMap - e.g. in 2LC the maxIdle is used to store some record for<br>
&gt;&gt; &gt;&gt; a<br>
&gt;&gt; &gt;&gt; short while (regular transaction lifespan ~ seconds to minutes), and<br>
&gt;&gt; &gt;&gt; regularly the record is removed. However, to make sure that we don&#39;t<br>
&gt;&gt; &gt;&gt; leak records in this cache (if something goes wrong and the remove does<br>
&gt;&gt; &gt;&gt; not occur), it is removed.<br>
&gt;&gt; &gt; Note that just relying on maxIdle doesn&#39;t guarantee you won&#39;t leak<br>
&gt;&gt; &gt; records in this use case (specifically with the way the current<br>
&gt;&gt; &gt; hibernate-infinispan 2LC implementation uses it).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Hibernate-infinispan adds entries to its own Map stored in Infinispan,<br>
&gt;&gt; &gt; and expects maxIdle to remove the map if it skips a remove.  But in a<br>
&gt;&gt; &gt; current case, we found that due to frequent accesses to that same map<br>
&gt;&gt; &gt; the entries never idle out and it ends up in OOME).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; -Dennis<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;&gt; I can guess how long the transaction takes place, but not how many<br>
&gt;&gt; &gt;&gt; parallel transactions there are. With eviction algorithms (where I am<br>
&gt;&gt; &gt;&gt; not sure about the exact guarantees) I can set the cache to not hold<br>
&gt;&gt; &gt;&gt; more than N entries, but I can&#39;t know for sure that my record does not<br>
&gt;&gt; &gt;&gt; suddenly get evicted after shorter period, possibly causing some<br>
&gt;&gt; &gt;&gt; inconsistency.<br>
&gt;&gt; &gt;&gt; So this is similar to WeakHashMap by removing the key &quot;when it can&#39;t be<br>
&gt;&gt; &gt;&gt; used anymore&quot; because I know that the transaction will finish before<br>
&gt;&gt; &gt;&gt; the<br>
&gt;&gt; &gt;&gt; deadline. I don&#39;t care about the exact size, I don&#39;t want to tune that,<br>
&gt;&gt; &gt;&gt; I just don&#39;t want to leak.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;    From my POV the non-strict maxIdle and strict expiration would be a<br>
&gt;&gt; &gt;&gt; nice compromise.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Radim<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           Note that this would make the reaper thread less efficient:<br>
&gt;&gt; &gt;&gt;&gt; with<br>
&gt;&gt; &gt;&gt;&gt;           numOwners=2 (best case), half of the entries that the reaper<br>
&gt;&gt; &gt;&gt;&gt;           touches<br>
&gt;&gt; &gt;&gt;&gt;           cannot be expired, because the node isn&#39;t the primary node.<br>
&gt;&gt; &gt;&gt;&gt; And to<br>
&gt;&gt; &gt;&gt;&gt;           make matters worse, the same reaper thread would have to<br>
&gt;&gt; &gt;&gt;&gt; perform a<br>
&gt;&gt; &gt;&gt;&gt;           (synchronous?) RPC for each entry to ensure it expires<br>
&gt;&gt; &gt;&gt;&gt; everywhere.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       I have debated about this, it could something like a sync<br>
&gt;&gt; &gt;&gt;&gt;       removeAll which has a special marker to tell it is due to<br>
&gt;&gt; &gt;&gt;&gt;       expiration (which would raise listeners there), while also<br>
&gt;&gt; &gt;&gt;&gt; sending<br>
&gt;&gt; &gt;&gt;&gt;       a cluster expiration event to other non owners.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           For maxIdle I&#39;d like to know more information about how<br>
&gt;&gt; &gt;&gt;&gt;           exactly the<br>
&gt;&gt; &gt;&gt;&gt;           owners would coordinate to expire an entry. I&#39;m pretty sure<br>
&gt;&gt; &gt;&gt;&gt; we<br>
&gt;&gt; &gt;&gt;&gt;           cannot<br>
&gt;&gt; &gt;&gt;&gt;           avoid ignoring some reads (expiring an entry immediately<br>
&gt;&gt; &gt;&gt;&gt; after<br>
&gt;&gt; &gt;&gt;&gt;           it was<br>
&gt;&gt; &gt;&gt;&gt;           read), and ensuring that we don&#39;t accidentally extend an<br>
&gt;&gt; &gt;&gt;&gt;           entry&#39;s life<br>
&gt;&gt; &gt;&gt;&gt;           (like the current code does, when we transfer an entry to a<br>
&gt;&gt; &gt;&gt;&gt;           new owner)<br>
&gt;&gt; &gt;&gt;&gt;           also sounds problematic.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       For lifespan it is simple, the primary owner just expires it<br>
&gt;&gt; &gt;&gt;&gt; when<br>
&gt;&gt; &gt;&gt;&gt;       it expires there.  There is no coordination needed in this case<br>
&gt;&gt; &gt;&gt;&gt; it<br>
&gt;&gt; &gt;&gt;&gt;       just sends the expired remove to owners etc.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       Max idle is more complicated as we all know.  The primary owner<br>
&gt;&gt; &gt;&gt;&gt;       would send a request for the last used time for a given key or<br>
&gt;&gt; &gt;&gt;&gt; set<br>
&gt;&gt; &gt;&gt;&gt;       of keys.  Then the owner would take those times and check for a<br>
&gt;&gt; &gt;&gt;&gt;       new access it isn&#39;t aware of.  If there isn&#39;t then it would send<br>
&gt;&gt; &gt;&gt;&gt; a<br>
&gt;&gt; &gt;&gt;&gt;       remove command for the key(s).  If there is a new access the<br>
&gt;&gt; &gt;&gt;&gt; owner<br>
&gt;&gt; &gt;&gt;&gt;       would instead send the last used time to all of the owners.  The<br>
&gt;&gt; &gt;&gt;&gt;       expiration obviously would have a window that if a read occurred<br>
&gt;&gt; &gt;&gt;&gt;       after sending a response that could be ignored.  This could be<br>
&gt;&gt; &gt;&gt;&gt;       resolved by using some sort of 2PC and blocking reads during<br>
&gt;&gt; &gt;&gt;&gt; that<br>
&gt;&gt; &gt;&gt;&gt;       period but I would say it isn&#39;t worth it.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       The issue with transferring to a new node refreshing the last<br>
&gt;&gt; &gt;&gt;&gt;       update/lifespan seems like just a bug we need to fix<br>
&gt;&gt; &gt;&gt;&gt; irrespective<br>
&gt;&gt; &gt;&gt;&gt;       of this issue IMO.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           I&#39;m not saying expiring entries on each node independently<br>
&gt;&gt; &gt;&gt;&gt; is<br>
&gt;&gt; &gt;&gt;&gt;           perfect,<br>
&gt;&gt; &gt;&gt;&gt;           far from it. But I wouldn&#39;t want us to provide new<br>
&gt;&gt; &gt;&gt;&gt; guarantees that<br>
&gt;&gt; &gt;&gt;&gt;           could hurt performance without a really good use case.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       I would guess that user perceived performance should be a little<br>
&gt;&gt; &gt;&gt;&gt;       faster with this.  But this also depends on an alternative that<br>
&gt;&gt; &gt;&gt;&gt; we<br>
&gt;&gt; &gt;&gt;&gt;       decided on :)<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;       Also the expiration thread pool is set to min priority atm so it<br>
&gt;&gt; &gt;&gt;&gt;       may delay removal of said objects but hopefully (if the jvm<br>
&gt;&gt; &gt;&gt;&gt;       supports) it wouldn&#39;t overrun a CPU while processing unless it<br>
&gt;&gt; &gt;&gt;&gt; has<br>
&gt;&gt; &gt;&gt;&gt;       availability.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           Cheers<br>
&gt;&gt; &gt;&gt;&gt;           Dan<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           On Mon, Jul 13, 2015 at 9:25 PM, Tristan Tarrant<br>
&gt;&gt; &gt;&gt;&gt;           &lt;<a href="mailto:ttarrant@redhat.com" target="_blank">ttarrant@redhat.com</a> &lt;mailto:<a href="mailto:ttarrant@redhat.com" target="_blank">ttarrant@redhat.com</a>&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;           &gt; After re-reading the whole original thread, I agree with<br>
&gt;&gt; &gt;&gt;&gt; the<br>
&gt;&gt; &gt;&gt;&gt;           proposal<br>
&gt;&gt; &gt;&gt;&gt;           &gt; with two caveats:<br>
&gt;&gt; &gt;&gt;&gt;           &gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt; - ensure that we don&#39;t break JCache compatibility<br>
&gt;&gt; &gt;&gt;&gt;           &gt; - ensure that we document this properly<br>
&gt;&gt; &gt;&gt;&gt;           &gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt; Tristan<br>
&gt;&gt; &gt;&gt;&gt;           &gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt; On 13/07/2015 18:41, Sanne Grinovero wrote:<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; +1<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; You had me convinced at the first line, although &quot;A lot<br>
&gt;&gt; &gt;&gt;&gt; of<br>
&gt;&gt; &gt;&gt;&gt;           code can now<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; be removed and made simpler&quot; makes it look extremely<br>
&gt;&gt; &gt;&gt;&gt; nice.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; On 13 Jul 2015 18:14, &quot;William Burns&quot;<br>
&gt;&gt; &gt;&gt;&gt; &lt;<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; &lt;mailto:<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a><br>
&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:mudokonman@gmail.com" target="_blank">mudokonman@gmail.com</a>&gt;&gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     This is a necro of [1].<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     With Infinispan 8.0 we are adding in clustered<br>
&gt;&gt; &gt;&gt;&gt;           expiration.  That<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     includes an expiration event raised that is clustered<br>
&gt;&gt; &gt;&gt;&gt;           as well.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     Unfortunately expiration events currently occur<br>
&gt;&gt; &gt;&gt;&gt;           multiple times (if<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     numOwners &gt; 1) at different times across nodes in a<br>
&gt;&gt; &gt;&gt;&gt;           cluster.  This<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     makes coordinating a single cluster expiration event<br>
&gt;&gt; &gt;&gt;&gt;           quite difficult.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     To work around this I am proposing that the<br>
&gt;&gt; &gt;&gt;&gt; expiration<br>
&gt;&gt; &gt;&gt;&gt;           of an event<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     is done solely by the owner of the given key that is<br>
&gt;&gt; &gt;&gt;&gt;           now expired.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     This would fix the issue of having multiple events<br>
&gt;&gt; &gt;&gt;&gt; and<br>
&gt;&gt; &gt;&gt;&gt;           the event can<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     be raised while holding the lock for the given key so<br>
&gt;&gt; &gt;&gt;&gt;           concurrent<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     modifications would not be an issue.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     The problem arises when you have other nodes that<br>
&gt;&gt; &gt;&gt;&gt; have<br>
&gt;&gt; &gt;&gt;&gt;           expiration<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     set but expire at different times.  Max idle is the<br>
&gt;&gt; &gt;&gt;&gt;           biggest offender<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     with this as a read on an owner only refreshes the<br>
&gt;&gt; &gt;&gt;&gt;           owners timestamp,<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     meaning other owners would not be updated and expire<br>
&gt;&gt; &gt;&gt;&gt;           preemptively.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     To have expiration work properly in this case you<br>
&gt;&gt; &gt;&gt;&gt; would<br>
&gt;&gt; &gt;&gt;&gt;           need<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     coordination between the owners to see if anyone has<br>
&gt;&gt; &gt;&gt;&gt; a<br>
&gt;&gt; &gt;&gt;&gt;           higher<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     value.  This requires blocking and would have to be<br>
&gt;&gt; &gt;&gt;&gt;           done while<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     accessing a key that is expired to be sure if<br>
&gt;&gt; &gt;&gt;&gt;           expiration happened or<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     not.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     The linked dev listing proposed instead to only<br>
&gt;&gt; &gt;&gt;&gt; expire<br>
&gt;&gt; &gt;&gt;&gt;           an entry by<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     the reaper thread and not on access.  In this case a<br>
&gt;&gt; &gt;&gt;&gt;           read will<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     return a non null value until it is fully expired,<br>
&gt;&gt; &gt;&gt;&gt;           increasing hit<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     ratios possibly.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     Their are quire a bit of real benefits for this:<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     1. Cluster cache reads would be much simpler and<br>
&gt;&gt; &gt;&gt;&gt;           wouldn&#39;t have to<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     block to verify the object exists or not since this<br>
&gt;&gt; &gt;&gt;&gt;           would only be<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     done by the reaper thread (note this would have only<br>
&gt;&gt; &gt;&gt;&gt;           happened if the<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     entry was expired locally).  An access would just<br>
&gt;&gt; &gt;&gt;&gt;           return the value<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     immediately.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     2. Each node only expires entries it owns in the<br>
&gt;&gt; &gt;&gt;&gt; reaper<br>
&gt;&gt; &gt;&gt;&gt;           thread<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     reducing how many entries they must check or remove.<br>
&gt;&gt; &gt;&gt;&gt;           This also<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     provides a single point where events would be raised<br>
&gt;&gt; &gt;&gt;&gt; as<br>
&gt;&gt; &gt;&gt;&gt;           we need.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     3. A lot of code can now be removed and made simpler<br>
&gt;&gt; &gt;&gt;&gt; as<br>
&gt;&gt; &gt;&gt;&gt;           it no longer<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     has to check for expiration.  The expiration check<br>
&gt;&gt; &gt;&gt;&gt;           would only be<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     done in 1 place, the expiration reaper thread.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     The main issue with this proposal is as the other<br>
&gt;&gt; &gt;&gt;&gt;           listing mentions<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     is if user code expects the value to be gone after<br>
&gt;&gt; &gt;&gt;&gt;           expiration for<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     correctness.  I would say this use case is not as<br>
&gt;&gt; &gt;&gt;&gt;           compelling for<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     maxIdle, especially since we never supported it<br>
&gt;&gt; &gt;&gt;&gt;           properly.  And in<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     the case of lifespan the user could very easily store<br>
&gt;&gt; &gt;&gt;&gt;           the expiration<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     time in the object that they can check after a get as<br>
&gt;&gt; &gt;&gt;&gt;           pointed out in<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     the other thread.<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     [1]<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; <a href="http://infinispan-developer-list.980875.n3.nabble.com/infinispan-dev-strictly-not-returning-expired-values-td3428763.html" rel="noreferrer" target="_blank">http://infinispan-developer-list.980875.n3.nabble.com/infinispan-dev-strictly-not-returning-expired-values-td3428763.html</a><br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;  _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;     infinispan-dev mailing list<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; infinispan-dev mailing list<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt; &gt;&gt;&gt;           &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt; --<br>
&gt;&gt; &gt;&gt;&gt;           &gt; Tristan Tarrant<br>
&gt;&gt; &gt;&gt;&gt;           &gt; Infinispan Lead<br>
&gt;&gt; &gt;&gt;&gt;           &gt; JBoss, a division of Red Hat<br>
&gt;&gt; &gt;&gt;&gt;           &gt; _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt;           &gt; infinispan-dev mailing list<br>
&gt;&gt; &gt;&gt;&gt;           &gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;           &gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt; &gt;&gt;&gt;           _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt;           infinispan-dev mailing list<br>
&gt;&gt; &gt;&gt;&gt;           <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt;           &lt;mailto:<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;<br>
&gt;&gt; &gt;&gt;&gt;           <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; _______________________________________________<br>
&gt;&gt; &gt;&gt;&gt; infinispan-dev mailing list<br>
&gt;&gt; &gt;&gt;&gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt; _______________________________________________<br>
&gt;&gt; &gt; infinispan-dev mailing list<br>
&gt;&gt; &gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; &gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; --<br>
&gt;&gt; Radim Vansa &lt;<a href="mailto:rvansa@redhat.com" target="_blank">rvansa@redhat.com</a>&gt;<br>
&gt;&gt; JBoss Performance Team<br>
&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; infinispan-dev mailing list<br>
&gt;&gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; infinispan-dev mailing list<br>
&gt; <a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
&gt; <a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
_______________________________________________<br>
infinispan-dev mailing list<br>
<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/infinispan-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a><br>
</blockquote></div></div>