doanduyhai / Achilles

An advanced Java Object Mapper/Query DSL generator for Cassandra
http://achilles.archinnov.info
Apache License 2.0
241 stars 92 forks source link

How to get result from conditional update #343

Closed wittyameta closed 6 years ago

wittyameta commented 6 years ago

I tried using a custom ResultListener, but it doesn't always work correctly.

public class ResultListener implements LWTResultListener {

  private boolean applied;

  @Override
  public void onSuccess() {
     applied = true;
  }

  @Override
  public void onError(LWTResult lwtResult) {
    applied = false;
  }

  public boolean isApplied() {
    return applied;
  }
}

From my caller class, I call isApplied() but it seems that the onSuccess method is called asynchronously. The caller class doesn't see the updated value of applied field

doanduyhai commented 6 years ago

I understand your problem but it's the nature of asynchronous execution. To solve this, in my integration test, I have the following pattern:


  final CountDownLatch latch = new CountDownLatch(1);
  final AtomicBoolean success = new AtomicBoolean(false);

 //When
        manager
                .dsl()
                .update()
                .fromBaseTable()
                 ...
                .withLwtResultListener(new LWTResultListener() {
                    @Override
                    public void onSuccess() {
                        success.getAndSet(true);
                    }

                    @Override
                    public void onError(LWTResult lwtResult) {
                    }
                })
                .withResultSetAsyncListener(rs -> {
                    latch.countDown();
                    return rs;
                })
                .executeAsync();

        //Then
        latch.await();
       assertThat(success.get()).isTrue();

First I declare 2 variables:

With withLwtResultListener() I passed in an instance of LWTResultListener to set the atomic boolean value to true

However, if you only do that, the main thread will call immediately assertThat(success.get()).isTrue() before the LWTResultListener has a chance to be called ...

Therefore I need to add an withResultSetAsyncListener() to trigger the latch count down when the result set is available asynchronously.

In the main execution thread, I block on latch.await() until the latch.countDown() is called.

You can adapt this pattern to your use-case

wittyameta commented 6 years ago

Thanks!