vlingo/xoom-common

failedOutcomeValue ignored if chained with multiple AndThen statements

Closed this issue · 8 comments

Seems like this is the bug that you can easily reproduce with the following test:

@Test
  public void TestThatFailureOutcomeFails()
  {
    final Completes<Integer> completes = new BasicCompletes<>(new Scheduler());
    completes
            .andThen(new Integer(-100), (value) -> 2 * value)
            .andThen((x) -> andThenValue = x)
            .otherwise((x) -> failureValue = 1000);

    completes.with(-100);
    Integer completed = completes.await();

    assertTrue(completes.hasFailed());
    assertEquals(new Integer(-1), andThenValue);
    assertEquals(new Integer(1000), failureValue);
  }

The failedOutcomeValue from .andThen(new Integer(-100), (value) -> 2 * value) is not taken into account. When calling completes.with(-100); this line : https://github.com/vlingo/vlingo-common/blob/c858e9235d1912c1afc5fe5a881627955820a7f0/src/main/java/io/vlingo/common/BasicCompletes.java#L565 evaluates to null

As suggested by @VaughnVernon it might be that the second andThen overwrites the value with null because it is not nested but added up to the first andThen

@VaughnVernon Checked the test and it still fails and completes.hasFailed() is false

As I'm changing in .NET implementation how continuations are executed, I have exactly the same problem now. From what I see as .andThen(new Integer(-100), (value) -> 2 * value) is scheduled for execution immediately when we call completes.With(-100); it doesn't matter anymore, because the continuation was already run.

I'm lost what should be the correct behavior.

@VaughnVernon Checked the test and it still fails and completes.hasFailed() is false

As I'm changing in .NET implementation how continuations are executed, I have exactly the same problem now. From what I see as .andThen(new Integer(-100), (value) -> 2 * value) is scheduled for execution immediately when we call completes.With(-100); it doesn't matter anymore, because the continuation was already run.

I'm lost what should be the correct behavior.

Seems like it's not that. Everything starts to execute only when with(-100) is called. So it seems that it's not fixed yet

@tjaskula The execution must not start until with(outcome). The test is clean on local and Travis. There were bugs in your test so I had to change it. See the fixed test in BasicCompletesTest.

@VaughnVernon Ok, this is the new test

@Test
  public void testThatNonNullFailureOutcomeFails() {
    final Completes<Integer> completes = new BasicCompletes<>(new Scheduler());

    completes
            .andThen(new Integer(-100), (value) -> 2 * value)
            .andThen((x) -> andThenValue = x)
            .otherwise((x) -> failureValue = 1000);

    completes.with(-100);

    final Integer completed = completes.await();

    assertTrue(completes.hasFailed());
    assertEquals(new Integer(1000), completed);
    assertEquals(null, andThenValue);
    assertEquals(new Integer(1000), failureValue);
  }

My question is why assertEquals(new Integer(1000), completed); ? I thought that in that case the execution of 2 * value should not have happened and the 1000 not computed ?

It means that even if the failedOutcomeValue == passed in value it executes the current continuation but not the next one and if fails back to otherwise ?

@tjaskula The otherwise is executed because of the failure valve and it sets 1000.

Ok, so it executes the function and tries to execute the Otherwise branch with failedOutcome

Yes. It should be that any outcome in the pipeline that produces the failure value should execute the otherwise function. This includes before the first andThen.

Ok but the failure value must equal the outcome of previous execution or passed in value