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

Closing reactor connection and children. #19924

Merged
merged 128 commits into from
Apr 12, 2021
Merged

Conversation

conniey
Copy link
Member

@conniey conniey commented Mar 17, 2021

  • Closing reactor connection and children.
  • Adding asynchronous disposes so we wait for the connection/sessions/links to complete.
  • Updating *Processor usage to new reactor Sinks..
  • Performing remoteCredit checks in reactor dispatcher so that we don't get into a condition where in flux deliveries are being settled before we add credits.

Related: #18070

@conniey conniey self-assigned this Mar 17, 2021
@conniey conniey force-pushed the conniey/messaging-factory branch 2 times, most recently from 08eb9ab to ce4a583 Compare March 17, 2021 21:05
@conniey
Copy link
Member Author

conniey commented Mar 17, 2021

/azp run java - eventhubs - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@conniey conniey force-pushed the conniey/messaging-factory branch 3 times, most recently from 998f964 to 8d6ef0e Compare March 23, 2021 06:56
@conniey conniey changed the title (WIP) Closing reactor connection and children. Closing reactor connection and children. Mar 24, 2021
@conniey conniey force-pushed the conniey/messaging-factory branch from 952c1f0 to 500ad8c Compare April 9, 2021 18:45
@conniey conniey force-pushed the conniey/messaging-factory branch from 500ad8c to 45d9f8e Compare April 9, 2021 19:06
@conniey conniey merged commit 6b66681 into master Apr 12, 2021
@conniey conniey deleted the conniey/messaging-factory branch April 12, 2021 16:31
conniey added a commit that referenced this pull request Apr 12, 2021
* Adding lock around creation of reactor.

* Align with Track 1 by scheduling pending sends after operation timeout.
Changing hasStarted check.

* ReactorSession has reference to AmqpConnection (parent) to dispose.

* SessionHandler passes along its remote state instead of Active.

* Only sets errorCondition when it exists.

* Emitting a connection when it is active. Also, adding timeout messages.

* Connect AmqpConnection to dispose of child when shutdown signal received.

* When endpointStates or shutdownSignals are received, the sender is no longer "connected".

* ReactorSender: Rename to isClosed. Adding Mono.

* ReactorReceiver: Adding async closing.

* ReactorExecutor: Close scheduler when there is no more work.

* ReactorSender: Change logging to verbose.

* ReactorSession: Close session when it has completed all tasks.

* Update connection to close when sessions are disposed.

* Update Connection to only propagate more shutdown signals if it has not been signaled already.

* Adding retry time to close ReactorExecutor.

* Moves decodeMessage and remote credit into dispatcher.invoke method.

* Do not use .distinct() for endpoint handlers.

* Use boundedElastic in EventHubClient instead of deprecated elastic().

* Dispose sender and receiver when it is no longer authorized.

* Using distinctUntilChanged() rather than keeping track of endpoints myself.

* Add PartitionPump to release the scheduler when a partition is closed.

* Use try/catch around dispose in case an exception occurs.

* Adding shutdown signals to ReactorDispatcher

* Adding AsyncAutoCloseable and using it to dispose Reactor classes.

* Emitting exception when IOException thrown before reactor is closed.

* Catching RejectedExecutionException in the case that the IO signal is closed, so we can close resources manually.

* Removing unused scheduler.

* Removing duplicated logging.

* Fixing possible NPE between checking key and getting value.

* Only take while AzureCredentialTokenManager is not disposed.

* Checking for NPE when closing links.

* Removing comment about elastic scheduler since it is not configurable.
/**
* Asynchronous class to close resources.
*/
public interface AsyncAutoCloseable extends AutoCloseable {
Copy link
Member

Choose a reason for hiding this comment

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

Why do we want to extend AutoCloseable? Any class that wants to support both sync and async close method can implement both interfaces.

Copy link
Member Author

Choose a reason for hiding this comment

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

Jonathan had mentioned that it would be nice if our AsyncAutoCloseable works nicely with try-with-resources syntactic sugar.

if (isDisposed.getAndSet(true)) {
logger.verbose("connectionId[{}] was already disposed. {}", connectionId, message);
} else {
dispose(new AmqpShutdownSignal(false, false, message));
Copy link
Member

Choose a reason for hiding this comment

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

When an error occurs, we should inspect the AMQP error to ensure that the error was meant for this connection by comparing the connection id in the error with the current connection id. Otherwise, we'll dispose of a good connection when the error was for an older connection that is no longer active. We should do the same for session and link errors as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

The ConnectionHandler is bound to a single connection, so it will always be the same one. When we create a proton-j Connection, we bind an instance of the ConnectionHandler to it. So each connection has its own connection handler instance.

Comment on lines +132 to +140
// When we encounter an error refreshing authorization results, close the receive link.
final Mono<Void> operation =
closeAsync(String.format(
"connectionId[%s] linkName[%s] Token renewal failure. Disposing receive link.",
amqpConnection.getId(), getLinkName()),
new ErrorCondition(Symbol.getSymbol(AmqpErrorCondition.NOT_ALLOWED.getErrorCondition()),
error.getMessage()));

return operation.then(Mono.empty());
Copy link
Member

Choose a reason for hiding this comment

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

Can this be done in the subscribe's error handler instead of using onErrorResume? It is odd to have an empty error handler below.

Copy link
Member Author

Choose a reason for hiding this comment

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

I had that before but on an error, we want to output another async operation (ie. close the receiver) and the handlers only support synchronous callbacks, I moved it back to be a part of the chain.

} catch (IOException e) {
logger.warning("Unable to schedule work to add more credits.", e);
sink.error(new RuntimeException(String.format(
Copy link
Member

Choose a reason for hiding this comment

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

Use UncheckedIOException instead when mapping IOException to a runtime exception.
https://docs.oracle.com/javase/8/docs/api/java/io/UncheckedIOException.html

Copy link
Member Author

Choose a reason for hiding this comment

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

Sweet. I've never heard of this.

}));
next.receive()
.onBackpressureBuffer(maxQueueSize, BufferOverflowStrategy.ERROR)
.subscribe(message -> {
Copy link
Member

Choose a reason for hiding this comment

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

Should this subscribe have an error handler to dispose the link if there's an error?

Copy link
Member Author

Choose a reason for hiding this comment

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

No because the underlying deliverySink this fetches from never outputs an onError, it will do that via the endpointStates

conniey added a commit that referenced this pull request Apr 12, 2021
* Adding lock around creation of reactor.

* Align with Track 1 by scheduling pending sends after operation timeout.
Changing hasStarted check.

* ReactorSession has reference to AmqpConnection (parent) to dispose.

* SessionHandler passes along its remote state instead of Active.

* Only sets errorCondition when it exists.

* Emitting a connection when it is active. Also, adding timeout messages.

* Connect AmqpConnection to dispose of child when shutdown signal received.

* When endpointStates or shutdownSignals are received, the sender is no longer "connected".

* ReactorSender: Rename to isClosed. Adding Mono.

* ReactorReceiver: Adding async closing.

* ReactorExecutor: Close scheduler when there is no more work.

* ReactorSender: Change logging to verbose.

* ReactorSession: Close session when it has completed all tasks.

* Update connection to close when sessions are disposed.

* Update Connection to only propagate more shutdown signals if it has not been signaled already.

* Adding retry time to close ReactorExecutor.

* Moves decodeMessage and remote credit into dispatcher.invoke method.

* Do not use .distinct() for endpoint handlers.

* Use boundedElastic in EventHubClient instead of deprecated elastic().

* Dispose sender and receiver when it is no longer authorized.

* Using distinctUntilChanged() rather than keeping track of endpoints myself.

* Add PartitionPump to release the scheduler when a partition is closed.

* Use try/catch around dispose in case an exception occurs.

* Adding shutdown signals to ReactorDispatcher

* Adding AsyncAutoCloseable and using it to dispose Reactor classes.

* Emitting exception when IOException thrown before reactor is closed.

* Catching RejectedExecutionException in the case that the IO signal is closed, so we can close resources manually.

* Removing unused scheduler.

* Removing duplicated logging.

* Fixing possible NPE between checking key and getting value.

* Only take while AzureCredentialTokenManager is not disposed.

* Checking for NPE when closing links.

* Removing comment about elastic scheduler since it is not configurable.
benbp pushed a commit that referenced this pull request Apr 28, 2021
* Adding lock around creation of reactor.

* Align with Track 1 by scheduling pending sends after operation timeout.
Changing hasStarted check.

* ReactorSession has reference to AmqpConnection (parent) to dispose.

* SessionHandler passes along its remote state instead of Active.

* Only sets errorCondition when it exists.

* Emitting a connection when it is active. Also, adding timeout messages.

* Connect AmqpConnection to dispose of child when shutdown signal received.

* When endpointStates or shutdownSignals are received, the sender is no longer "connected".

* ReactorSender: Rename to isClosed. Adding Mono.

* ReactorReceiver: Adding async closing.

* ReactorExecutor: Close scheduler when there is no more work.

* ReactorSender: Change logging to verbose.

* ReactorSession: Close session when it has completed all tasks.

* Update connection to close when sessions are disposed.

* Update Connection to only propagate more shutdown signals if it has not been signaled already.

* Adding retry time to close ReactorExecutor.

* Moves decodeMessage and remote credit into dispatcher.invoke method.

* Do not use .distinct() for endpoint handlers.

* Use boundedElastic in EventHubClient instead of deprecated elastic().

* Dispose sender and receiver when it is no longer authorized.

* Using distinctUntilChanged() rather than keeping track of endpoints myself.

* Add PartitionPump to release the scheduler when a partition is closed.

* Use try/catch around dispose in case an exception occurs.

* Adding shutdown signals to ReactorDispatcher

* Adding AsyncAutoCloseable and using it to dispose Reactor classes.

* Emitting exception when IOException thrown before reactor is closed.

* Catching RejectedExecutionException in the case that the IO signal is closed, so we can close resources manually.

* Removing unused scheduler.

* Removing duplicated logging.

* Fixing possible NPE between checking key and getting value.

* Only take while AzureCredentialTokenManager is not disposed.

* Checking for NPE when closing links.

* Removing comment about elastic scheduler since it is not configurable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants