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

Fixes #118 Improve FlowControllingHttpContentProducer state machine. #120

Merged
merged 5 commits into from
Apr 9, 2018

Conversation

dvlato
Copy link
Contributor

@dvlato dvlato commented Mar 27, 2018

New event, DelayedTearDownEvent, created to replace IdleStateEvent.
Currently there's no handling of idle events in the FSM in FlowControllingHttpContentProducer, so the logic has been kept untouched.

…te machine.

New event DelayedTearDownEvent created to replace IdleStateEvent.
producer.receivedChunks(),
producer.emittedBytes(),
producer.emittedChunks()))),
() -> contentProducer.ifPresent(producer -> producer.tearDownResources(cause)),
Copy link
Contributor

Choose a reason for hiding this comment

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

The tearDownResources event is scheduled in a controlled fashion. That is, the tearDownResources is always scheduled after a short time to ensure state machine is orderly brought down. Therefore cause doesn't have to be passed in.

Copy link
Contributor Author

@dvlato dvlato Mar 27, 2018

Choose a reason for hiding this comment

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

I would say that if we have to publish an error, it will be more informative if it is the same error that caused the "channelInactive" -so they can be easily linked when reading the logs-, than if we make up an Exception as in your example in the comment below (TimedOutExceptionWhatever).

I have nonetheless implemented the change as per your suggestion keeping the ResponseTimeoutException as previously.

.transition(BUFFERING_COMPLETED, ContentSubscribedEvent.class, this::contentSubscribedEventWhileBufferingCompleted)
.transition(BUFFERING_COMPLETED, ContentEndEvent.class, s -> BUFFERING_COMPLETED)

.transition(STREAMING, RxBackpressureRequestEvent.class, this::rxBackpressureRequestEventWhileStreaming)
.transition(STREAMING, ContentChunkEvent.class, this::contentChunkEventWhileStreaming)
.transition(STREAMING, ChannelInactiveEvent.class, e -> emitErrorAndTerminate(e.cause()))
.transition(STREAMING, ChannelExceptionEvent.class, e -> emitErrorAndTerminate(e.cause()))
.transition(STREAMING, ChannelIdleEvent.class, e -> emitErrorAndTerminate(new ResponseTimeoutException(origin)))
.transition(STREAMING, DelayedTearDownEvent.class, e -> emitErrorAndTerminate(e.cause()))
Copy link
Contributor

Choose a reason for hiding this comment

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

I would use a different method for the state transition handler. For example:

+                .transition(STREAMING, DelayedTearDownEvent.class, e -> tearDown())

And then in the tearDown method:

private void tearDown() {
   emitErrorAndTerminate(new TimedOutExceptionWhatever());  // Choose an appropriate exception here.
}

So I would have a dedicated method specifically for the tearDown transition. This exposes the state transition logic more explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That sounds like an improvement, but in your example we are emitting an error, I assume, to signal an invalid combination of state+event. Doesn't it make more sense to use a new 'tearDown' method for the cases in which we are calling 'releaseAndTerminate' ?

…te machine.

New event DelayedTearDownEvent created to replace IdleStateEvent.
… necessary states:

  BUFFERING_COMPLETED
  EMITTING_BUFFERED_CONTENT
… necessary states:

  BUFFERING_COMPLETED
  EMITTING_BUFFERED_CONTENT
@@ -53,6 +53,7 @@
private final Runnable askForMore;
private final Runnable onCompleteAction;
private final Consumer<Throwable> onTerminateAction;
private Runnable delayedTearDownAction;
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be final.

.transition(BUFFERING_COMPLETED, ChannelExceptionEvent.class, s -> BUFFERING_COMPLETED)
.transition(BUFFERING_COMPLETED, ChannelIdleEvent.class, this::releaseAndTerminate)
.transition(BUFFERING_COMPLETED, DelayedTearDownEvent.class, this::tearDown)
Copy link
Contributor

Choose a reason for hiding this comment

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

I am thinking we should call this::releaseAndTerminate directly since the this::tearDown method is identical.

.transition(EMITTING_BUFFERED_CONTENT, ChannelExceptionEvent.class, s -> EMITTING_BUFFERED_CONTENT)
.transition(EMITTING_BUFFERED_CONTENT, ChannelIdleEvent.class, e -> emitErrorAndTerminate(e.cause()))
.transition(EMITTING_BUFFERED_CONTENT, DelayedTearDownEvent.class, this::tearDownWithError)
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps it is better to use emitErrorAndTerminate instead of tearDownWithError because they are identical.


private ProducerState tearDown(CausalEvent event) {
return releaseAndTerminate(event);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned in the previous comments let's get rid of tearDown and tearDownWithError methods.

producer.receivedBytes(),
producer.receivedChunks(),
producer.emittedBytes(),
producer.emittedChunks()))),
Copy link
Contributor

Choose a reason for hiding this comment

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

Please ensure these stats are passed in to the ResponseTimeoutException.
Even better please add a test that verifies that the counters are present in the exception when it is torn down.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or instead log a warning using FlowControllingHttpContentProducer.warningMessage. This is the preferred option IMO.

Copy link
Contributor

Choose a reason for hiding this comment

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

The log messages can be tested with LoggingTestSupport. Please look for examples of usage in the codebase. It is quite easy to use.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternatively raise a separate GitHub enhancement issue.

TearDown methods removed
Exception in the teardownevent contains bytecount.
@mikkokar mikkokar merged commit 153ec50 into ExpediaGroup:master Apr 9, 2018
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.

3 participants