<div dir="ltr"><div class="gmail_extra"><div>Reviving the thread...</div><div><br></div><div>Paul, this is a little more complicated than just the return value of the put. In Infinispan prior to 6.0.1, this would have always worked with a replicated asynchronous cache:</div>

<div><br></div><div>cache.put(k, v); // return value ignored</div><div>v1 = cache.get(k);</div><div>assertEquals(v, v1);</div><div><br></div><div>The behaviour of Infinispan prior to 6.0.1 was to write the value to the local cache synchronously, and only replicate the value to the other owners asynchronously.</div>

<div>Of course, if the cache was distributed and the originator was not an owner, the assertion could have failed anyway, because the remote get could be executed before the remote put.</div><div>The get(k) is not guaranteed to return the value inserted by the put(k, v), but it did work most of the time.</div>

<div><br></div><div>Since 6.0.1, the originator doesn&#39;t update the local value synchronously any more, unless it is the primary owner. If it is a backup owner, it will send the update asynchronously to the primary owner, which will then update the backup owners (including the originator) synchronously, while holding the lock. This was supposed to change in 5.3.0, as replicated mode was already using lock delegation in 5.3.0, but EntryWrappingInterceptor had an outdated check that meant the originator did both the synchronous update and the asynchronous one. The fix in 6.0.1 was just to remove the synchronous update.</div>

<div><br></div><div>Personally I think the pre-6.0.1 behaviour was a bit dangerous, because the get would return the updated value *almost* all of the time. So there was a chance that tests would work, and the app would only fail in production. putIfAbsent will also behave more like an atomic operation with 6.0.1+, at least as long as the primary owner of the key doesn&#39;t change.</div>
<div><br></div><div>That&#39;s not to say the current behaviour is perfect. I&#39;m open to changing REPL_ASYNC back to updating the local data container first (if owner) and then sending the write command asynchronously to all the members in parallel, like we did in 5.2.0 and before. </div><div><br></div><div>We could also change DIST_ASYNC to behave the same, because the current behaviour is a little too close to what putAsync does in DIST_SYNC mode, and people using async replication should be ok with nodes applying modifications in a different order (it happens on primary owner change anyway). </div><div><br></div><div>However, I&#39;m not sure what we should do for atomic operations like replace(key, oldValue, newValues). I would suggest throwing a UnsupportedOperationException, because the operation is very unlikely to be atomic. It&#39;s true that PFER is also specified as behaving the same as putIfAbsent, but the PFER check is going to be on the originator only so we can just remove that bit from the Javadoc.</div><div><br></div><div>Another option would be to change PFER only to behave like in 5.3.0 and 6.0.0. We could say PFER performs two put operations, one that&#39;s local-only and one that&#39;s replicated but asynchronous (updating the value on the originator a second time). Or we could say PFER always updates the value on the local node only...</div><div><br></div><div>Cheers</div><div>Dan</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>
</div></blockquote><div class="gmail_quote">On Tue, Sep 2, 2014 at 3:19 PM, Paul Ferraro <span dir="ltr">&lt;<a href="mailto:paul.ferraro@redhat.com" target="_blank">paul.ferraro@redhat.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div>----- Original Message -----<br>
&gt; From: &quot;Galder Zamarreño&quot; &lt;<a href="mailto:galder@redhat.com" target="_blank">galder@redhat.com</a>&gt;<br>
&gt; To: &quot;infinispan -Dev List&quot; &lt;<a href="mailto:infinispan-dev@lists.jboss.org" target="_blank">infinispan-dev@lists.jboss.org</a>&gt;, &quot;Paul Ferraro&quot; &lt;<a href="mailto:paul.ferraro@redhat.com" target="_blank">paul.ferraro@redhat.com</a>&gt;<br>


&gt; Sent: Monday, September 1, 2014 11:08:45 AM<br>
&gt; Subject: Asynchronous cache&#39;s &quot;void put()&quot; call expectations changed from 6.0.0 to 6.0.1/7.0<br>
&gt;<br>
&gt; Hi all,<br>
&gt;<br>
&gt; @Paul, this might be important for WF if using async repl caches (the same I<br>
&gt; think applies to distributed async caches too)<br>
<br>
</div>Luckily, Dan warned me that of this behavioral change well in advance.<br>
Any time we need a reliable return value from a Cache.put(...), we use Flag.FORCE_SYNCHRONOUS so that the same code will work for sync and async caches alike.</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div><div><br>
&gt; Today I’ve been trying to upgrade Infinispan version in Hibernate master from<br>
&gt; 6.0.0.Final to 7.0.0.Beta1. Overall, it’s all worked fine but there’s one<br>
&gt; test that has started failing.<br>
&gt;<br>
&gt; Essentialy, this is a clustered test for a repl async cache (w/ cluster cache<br>
&gt; loader) where a non-owner cache node does put() and immediately, on the same<br>
&gt; cache, it calls a get(). The test is failing because the get() does not see<br>
&gt; the effects of the put(), even if both operations are called on the same<br>
&gt; cache instance.<br>
&gt;<br>
&gt; According to Dan, this should have been happening since [1] was implemented,<br>
&gt; but it’s really started happening since [2] when lock delegation was enabled<br>
&gt; for replicated caches (EntryWrappingInterceptor.isUsingLockDelegation is now<br>
&gt; true whereas in 6.0.0 it was false).<br>
&gt;<br>
&gt; Not sure we set expectations in this regard, but clearly it’s big change in<br>
&gt; terms of expectations on when “void put()” completes for async repl caches.<br>
&gt; I’m not sure how we should handle this, but it definitely needs some<br>
&gt; discussion and adjuts documentation/javadoc if needed. Can we do something<br>
&gt; differently?<br>
&gt;<br>
&gt; Indepent of how we resolve this, this is the result of once again of trying<br>
&gt; to shoehole async behaviour into sync APIs. Any async caches (DIST, INV,<br>
&gt; REPL) should really be accessed exclusively via the AsyncCache API, where<br>
&gt; you can return quickly and use the future, and any listener to attach to it<br>
&gt; (a bit ala Java8’s CompletableFuture.map lambda calls) as a way to signal<br>
&gt; that the operation has completed, and then you have an API and cache mode<br>
&gt; that make sense and is consistent with how async APIs work.<br>
&gt;<br>
&gt; Right now, when a repl async cache’s “void put()” call is not very well<br>
&gt; defined. Does it return when message has been put on the network? What<br>
&gt; impact does it have in the local cache contents?<br>
&gt;<br>
&gt; Also, a very big problem of the change of behaviour is that if left like<br>
&gt; that, you are forcing users to code differently, using the same “void put()”<br>
&gt; API depending on the configuration (whether async/sync). As clearly shown by<br>
&gt; the issue above, this is very confusing. It’s a lot more logical IMO, and<br>
&gt; I’ve already sent an email on this very same topic [3] back in January, that<br>
&gt; whether a cache is sync or async should be based purely on the API used and<br>
&gt; forget about the static configuration flag on whether the cache is async or<br>
&gt; sync.<br>
<br>
</div></div>I would agree would this last statement.  Consistent semantics are a good thing.<br>
If you do change this, however, just let me know well in advance.<br>
<div><div><br>
&gt; Cheers,<br>
&gt;<br>
&gt; [1] <a href="https://issues.jboss.org/browse/ISPN-2772" target="_blank">https://issues.jboss.org/browse/ISPN-2772</a><br>
&gt; [2] <a href="https://issues.jboss.org/browse/ISPN-3354" target="_blank">https://issues.jboss.org/browse/ISPN-3354</a><br>
&gt; [3] <a href="http://lists.jboss.org/pipermail/infinispan-dev/2014-January/014448.html" target="_blank">http://lists.jboss.org/pipermail/infinispan-dev/2014-January/014448.html</a><br>
&gt; --<br>
&gt; Galder Zamarreño<br>
&gt; <a href="mailto:galder@redhat.com" target="_blank">galder@redhat.com</a><br>
&gt; <a href="http://twitter.com/galderz" target="_blank">twitter.com/galderz</a><br>
&gt;<br>
&gt;<br>
<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" target="_blank">https://lists.jboss.org/mailman/listinfo/infinispan-dev</a></div></div></blockquote></div><br></div></div>