Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add waitForProcessingState to engine #218

Merged
merged 14 commits into from
Mar 2, 2022
Merged

Add waitForProcessingState to engine #218

merged 14 commits into from
Mar 2, 2022

Conversation

remcowesterhoud
Copy link
Contributor

@remcowesterhoud remcowesterhoud commented Feb 28, 2022

Description

In #202 we have a flaky tests. In this test we have a process that's triggered by a timer start event. We increase the time of the engine to trigger this timer, sleep for 100 ms, wait for the engine to reach an idle state and assert that the process instance gets completed.

This solution has a few problems. First of all we use a Thread.sleep() to give the engine some time to trigger the timers. This is a dirty solution and it'd be better if we have a solution that only waits until the engine is running again.
The second problem is that the engine has not always triggered the timers within 100 ms. Because of this the engine is considered idle, without actually finishing the processing.

This PR adds a waitForProcessingState to the engine. This method is very similar to the waitForIdleState method we already have. Just like that method it uses the IdleStateMonitor with a callback to wait until the engine has started committing records again.
A timeout needs to be specified to prevent waiting forever in case the engine will be permanently idle.

Related issues

closes #202

Definition of Done

Not all items need to be done depending on the issue and the pull request.

Code changes:

  • The changes are backwards compatibility with previous versions
  • If it fixes a bug then PRs are created to backport the fix

Testing:

  • There are unit/integration tests that verify all acceptance criterias of the issue
  • New tests are written to ensure backwards compatibility with further versions
  • The behavior is tested manually

Documentation:

  • Javadoc has been written
  • The documentation is updated

In some instances users might want to wait until the engine is processing. 1 such case is after increasing the time of the ActorScheduler. The engine should start triggering timers. It takes some time before the TRIGGERED records are written to the stream. By introducing a waitForProcessingState method users have the possibility to wait a given amount of time until the TRIGGERED record should be available.
@github-actions
Copy link

github-actions bot commented Feb 28, 2022

Unit Test Results

128 files  128 suites   5m 38s ⏱️
325 tests 325 ✔️ 0 💤 0
788 runs  788 ✔️ 0 💤 0

Results for commit f6e3a51.

♻️ This comment has been updated with latest results.

In some instances users might want to wait until the engine is processing. 1 such case is after increasing the time of the ActorScheduler. The engine should start triggering timers. It takes some time before the TRIGGERED records are written to the stream. By introducing a waitForProcessingState method users have the possibility to wait a given amount of time until the TRIGGERED record should be available.
When we increase the time it takes some time before the engine has started processing again, and before it is writing new records to the stream. If we immediately wait for an idle state after increasting the time it will immediately say that it is idle, even though any potential timers have not yet been triggered.
By waiting for up to 1 second to see if the engine has started processing again we can make sure the timers have been triggered. After this we still need to wait until the engine is idle again, to not modify the existing functionality.
Copy link
Contributor

@pihme pihme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

Some suggestions for name changes.

And maybe we should start writing tests also for classes like the idle state. The longer we wait, the more painful it will be to start writing tests for a class like that.

waitForBusyState may be more descriptive to our users compared to waitForProcessingState.
To keep it in line with the waitForIdleState method a new `waitForBusyState()` has been introduced.
EngineStateMonitor is a more fitting name. This is because we're not only interested in the idle state of the engine, but also the busy state.

Some methods have also been renamed to increase the clarity of what they do.
Similarly to waitForBusyState, waitForIdleState now has a timeout. If the engine has not reached an idle state within the specified timeout a TimeoutException will be thrown for the user to handle.
@remcowesterhoud
Copy link
Contributor Author

Thanks for reviewing @pihme. I've applied your suggestions and created a unit test for the IdleStateMonitor. The test is somewhat complex because I needed to make my own LogStreamReader. If you see a better solution for this please let me know!

waitForIdleState now requires a timeout to be specified. This commits adds this to all the tests that at some point wait for an idle state to be reached.
Add unit tests to verify the callbacks of the EngineStateMonitor are called at the correct times.
Copy link
Contributor

@pihme pihme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

I have some comments.

If you make bigger changes to the test, I would like to review those again. Otherwise, no need to do another review round

@remcowesterhoud
Copy link
Contributor Author

@pihme I made some bigger changes to the test so I'd like another review.

The biggest change is that I added a way to lock the state. This is required because when we switch to a busy state and register a callback the check if we are already in an idle state. This executes this method:

private void forwardToLastEvent() {
    synchronized (reader) {
      while (reader.hasNext()) {
        lastEventPosition = reader.next().getPosition();
      }
    }
  }

This iteration causes the state to become idle. Before this change as a workaround I registered the busy callback before actually changing the state to busy. This was confusing so I switched this up, but because of it I required a way to lock the state into a busy state. That's why I added the stateLocked flag.

Renamed runProcessingCallbacks() to notifyProcessingCallbacks()

Refactored the EngineStateMonitorTest
- Extracted some shared functionality to a beforeEach method
- Changed the structure of the tests to be more clear what it does. Given a callback, when the engine is busy/idle and we register a callback, then the callback should be notified.
- Explicitly change the to an idle state in the idle state tests (even if we are already idle)
Copy link
Contributor

@pihme pihme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick feedback; didn't do a full review yet

Copy link
Contributor

@pihme pihme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely going in the right direction, Some details are still confusing

Locking the state in idle/busy allows us to add the callback without it being triggered as a result from adding it. We can than make the part where it trigger more explicit by change to the other state.
…sync

These positions should stay synchronized. Differences are going to cause weird behaviour where we think we are in an idle/busy state, but the positions indicate something else.
Copy link
Contributor

@pihme pihme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flaky test: ProcessEventInspectionsTest.testFindLastProcessInstance
2 participants