Re: ProtonJ2 Initial connection failure, reconnect logic
On Tue, Mar 12, 2024 at 8:42 PM Timothy Bish wrote: > On 3/12/24 16:25, Ciaran wrote: > > On Tue, Mar 12, 2024 at 7:13 PM Timothy Bish > wrote: > > > >> On 3/12/24 04:08, Ciaran wrote: > >>> On Mon, Mar 11, 2024 at 9:33 PM Timothy Bish > >> wrote: > The client re-connection logic treats a SASL authentication error as a > terminal state and will not continue reconnect attempts if it > receives a > SASL outcome that indicates anything other than a temporary failure > state so it should be stopping the reconnect if it was actually > failing > to authenticate. This is true on the first attempt as well as on > subsequent attempts to other hosts if you add more than one and it has > failed to reach any of the preceding hosts while attempt to recover > the > connection. > > From the error logs attached it doesn't appear as though SASL > authentication is your issue though, at least in so much as it isn't > logging anything indicating SASL authentication as the error. Instead > the connection appears to be failing because the remote has sent a > response to the Receiver attach that does not include the initial > delivery count value as required by the specification. > > You can capture more information about the AMQP frames being sent and > received by enabling frame tracing, see the docs for how to do that. > > > > >> > https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging > > >>> Thanks for getting back to me so quickly Tim, please find below the > >> frames > >>> for a successful > >>> connection and an unsuccessful connection. My test has actually been to > >>> specify an invalid user if > >>> that's relevant. > >>> > >>> I can see in both cases that the SASL challenge completes successfully, > >>> which I appreciate is > >>> strange, but I would imagine Azure Service Bus is a common enough > broker > >>> target for the library? > >> So looking at the frame trace it is clear the connection is being > >> established as the SASL outcome is returned as 'OK' and then a normal > >> Open exchange occurs so from the client point of view a connection was > >> successfully made so any initial reconnect attempts option won't apply > >> here as the connection "succeeded". For the connection to fail with bad > >> credentials the SASL outcome would need to indicate a failure. > >> > >> The connection breaks at the point the attach response arrives and is > >> lacking the mandatory initial-delivery-count field as per the AMQP 1.0 > >> specification. > >> > >> > >> > http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-attach > >> > >> It could be that the user you logged in as does not have read permission > >> and the server is trying to tell the client that the link will be closed > >> with an error condition in the Detach indicating that as the returned > >> response does not carry a source or target value (both are null) whereas > >> the sent Attach has an appropriate source and target value. If that is > >> what it is doing it gets it wrong as it omits the > >> 'initial-delivery-count' which is required for an Attach with the Role > >> of Sender (as per referenced spec above) regardless of the outcome of > >> the attach. > >> > >> Sorry, I think perhaps I've not explained myself well here, the user is > > correctly configured on Azure Service Bus. > > However, the fail case is where I provide an *invalid* (non-existant) > user > > or an *invalid* password. > > > > I can see that the SaSL challenges succeeds, and agree from a client > > perspective that this success is > > problematic when the credentials provided are invalid! I guess I'm > flagging > > that my configuration is not > > exotic, and Azure Service Bus is a fairly popular AMQP broker. > > As I pointed out the remote is telling the client that the connection > succeeded so from the client point of view there just isn't anything > that it can do here to know that your user doesn't exist. I'd say you > need to take this up with MS as there just isn't anything that can be > done here. > > > > If this is the desired behaviour of the client library when interacting > > with Azure, I'll stick with my work around, which is to create a > > connection & receiver with no reconnect semantics configured, check that > > connection succeeds, close it and then > > re-open with a retryable connection. > > > > P.S. Spotted a minor issue in the ReconnectOptions.java file and have > > submitted a pull request over on Github, > > confused the hell out of me for a while! > > - Cj. > > > > -- > Tim Bish > > > - > To unsubscribe, e-mail: users-unsubscr...@qpid.apache.org > For additional commands, e-mail: users-h...@qpid.apache.org Indeed, not a problem, I've a work-around in place! Thank you.
Re: ProtonJ2 Initial connection failure, reconnect logic
On 3/12/24 16:25, Ciaran wrote: On Tue, Mar 12, 2024 at 7:13 PM Timothy Bish wrote: On 3/12/24 04:08, Ciaran wrote: On Mon, Mar 11, 2024 at 9:33 PM Timothy Bish wrote: The client re-connection logic treats a SASL authentication error as a terminal state and will not continue reconnect attempts if it receives a SASL outcome that indicates anything other than a temporary failure state so it should be stopping the reconnect if it was actually failing to authenticate. This is true on the first attempt as well as on subsequent attempts to other hosts if you add more than one and it has failed to reach any of the preceding hosts while attempt to recover the connection. From the error logs attached it doesn't appear as though SASL authentication is your issue though, at least in so much as it isn't logging anything indicating SASL authentication as the error. Instead the connection appears to be failing because the remote has sent a response to the Receiver attach that does not include the initial delivery count value as required by the specification. You can capture more information about the AMQP frames being sent and received by enabling frame tracing, see the docs for how to do that. https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging Thanks for getting back to me so quickly Tim, please find below the frames for a successful connection and an unsuccessful connection. My test has actually been to specify an invalid user if that's relevant. I can see in both cases that the SASL challenge completes successfully, which I appreciate is strange, but I would imagine Azure Service Bus is a common enough broker target for the library? So looking at the frame trace it is clear the connection is being established as the SASL outcome is returned as 'OK' and then a normal Open exchange occurs so from the client point of view a connection was successfully made so any initial reconnect attempts option won't apply here as the connection "succeeded". For the connection to fail with bad credentials the SASL outcome would need to indicate a failure. The connection breaks at the point the attach response arrives and is lacking the mandatory initial-delivery-count field as per the AMQP 1.0 specification. http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-attach It could be that the user you logged in as does not have read permission and the server is trying to tell the client that the link will be closed with an error condition in the Detach indicating that as the returned response does not carry a source or target value (both are null) whereas the sent Attach has an appropriate source and target value. If that is what it is doing it gets it wrong as it omits the 'initial-delivery-count' which is required for an Attach with the Role of Sender (as per referenced spec above) regardless of the outcome of the attach. Sorry, I think perhaps I've not explained myself well here, the user is correctly configured on Azure Service Bus. However, the fail case is where I provide an *invalid* (non-existant) user or an *invalid* password. I can see that the SaSL challenges succeeds, and agree from a client perspective that this success is problematic when the credentials provided are invalid! I guess I'm flagging that my configuration is not exotic, and Azure Service Bus is a fairly popular AMQP broker. As I pointed out the remote is telling the client that the connection succeeded so from the client point of view there just isn't anything that it can do here to know that your user doesn't exist. I'd say you need to take this up with MS as there just isn't anything that can be done here. If this is the desired behaviour of the client library when interacting with Azure, I'll stick with my work around, which is to create a connection & receiver with no reconnect semantics configured, check that connection succeeds, close it and then re-open with a retryable connection. P.S. Spotted a minor issue in the ReconnectOptions.java file and have submitted a pull request over on Github, confused the hell out of me for a while! - Cj. -- Tim Bish - To unsubscribe, e-mail: users-unsubscr...@qpid.apache.org For additional commands, e-mail: users-h...@qpid.apache.org
Re: ProtonJ2 Initial connection failure, reconnect logic
On Tue, Mar 12, 2024 at 7:13 PM Timothy Bish wrote: > On 3/12/24 04:08, Ciaran wrote: > > On Mon, Mar 11, 2024 at 9:33 PM Timothy Bish > wrote: > > > >> > >> The client re-connection logic treats a SASL authentication error as a > >> terminal state and will not continue reconnect attempts if it receives a > >> SASL outcome that indicates anything other than a temporary failure > >> state so it should be stopping the reconnect if it was actually failing > >> to authenticate. This is true on the first attempt as well as on > >> subsequent attempts to other hosts if you add more than one and it has > >> failed to reach any of the preceding hosts while attempt to recover the > >> connection. > >> > >> From the error logs attached it doesn't appear as though SASL > >> authentication is your issue though, at least in so much as it isn't > >> logging anything indicating SASL authentication as the error. Instead > >> the connection appears to be failing because the remote has sent a > >> response to the Receiver attach that does not include the initial > >> delivery count value as required by the specification. > >> > >> You can capture more information about the AMQP frames being sent and > >> received by enabling frame tracing, see the docs for how to do that. > >> > >> > >> > https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging > >> > >> > > Thanks for getting back to me so quickly Tim, please find below the > frames > > for a successful > > connection and an unsuccessful connection. My test has actually been to > > specify an invalid user if > > that's relevant. > > > > I can see in both cases that the SASL challenge completes successfully, > > which I appreciate is > > strange, but I would imagine Azure Service Bus is a common enough broker > > target for the library? > > So looking at the frame trace it is clear the connection is being > established as the SASL outcome is returned as 'OK' and then a normal > Open exchange occurs so from the client point of view a connection was > successfully made so any initial reconnect attempts option won't apply > here as the connection "succeeded". For the connection to fail with bad > credentials the SASL outcome would need to indicate a failure. > > The connection breaks at the point the attach response arrives and is > lacking the mandatory initial-delivery-count field as per the AMQP 1.0 > specification. > > > http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-attach > > It could be that the user you logged in as does not have read permission > and the server is trying to tell the client that the link will be closed > with an error condition in the Detach indicating that as the returned > response does not carry a source or target value (both are null) whereas > the sent Attach has an appropriate source and target value. If that is > what it is doing it gets it wrong as it omits the > 'initial-delivery-count' which is required for an Attach with the Role > of Sender (as per referenced spec above) regardless of the outcome of > the attach. > > Sorry, I think perhaps I've not explained myself well here, the user is correctly configured on Azure Service Bus. However, the fail case is where I provide an *invalid* (non-existant) user or an *invalid* password. I can see that the SaSL challenges succeeds, and agree from a client perspective that this success is problematic when the credentials provided are invalid! I guess I'm flagging that my configuration is not exotic, and Azure Service Bus is a fairly popular AMQP broker. If this is the desired behaviour of the client library when interacting with Azure, I'll stick with my work around, which is to create a connection & receiver with no reconnect semantics configured, check that connection succeeds, close it and then re-open with a retryable connection. P.S. Spotted a minor issue in the ReconnectOptions.java file and have submitted a pull request over on Github, confused the hell out of me for a while! - Cj.
Re: ProtonJ2 Initial connection failure, reconnect logic
On 3/12/24 04:08, Ciaran wrote: On Mon, Mar 11, 2024 at 9:33 PM Timothy Bish wrote: The client re-connection logic treats a SASL authentication error as a terminal state and will not continue reconnect attempts if it receives a SASL outcome that indicates anything other than a temporary failure state so it should be stopping the reconnect if it was actually failing to authenticate. This is true on the first attempt as well as on subsequent attempts to other hosts if you add more than one and it has failed to reach any of the preceding hosts while attempt to recover the connection. From the error logs attached it doesn't appear as though SASL authentication is your issue though, at least in so much as it isn't logging anything indicating SASL authentication as the error. Instead the connection appears to be failing because the remote has sent a response to the Receiver attach that does not include the initial delivery count value as required by the specification. You can capture more information about the AMQP frames being sent and received by enabling frame tracing, see the docs for how to do that. https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging Thanks for getting back to me so quickly Tim, please find below the frames for a successful connection and an unsuccessful connection. My test has actually been to specify an invalid user if that's relevant. I can see in both cases that the SASL challenge completes successfully, which I appreciate is strange, but I would imagine Azure Service Bus is a common enough broker target for the library? So looking at the frame trace it is clear the connection is being established as the SASL outcome is returned as 'OK' and then a normal Open exchange occurs so from the client point of view a connection was successfully made so any initial reconnect attempts option won't apply here as the connection "succeeded". For the connection to fail with bad credentials the SASL outcome would need to indicate a failure. The connection breaks at the point the attach response arrives and is lacking the mandatory initial-delivery-count field as per the AMQP 1.0 specification. http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-attach It could be that the user you logged in as does not have read permission and the server is trying to tell the client that the link will be closed with an error condition in the Detach indicating that as the returned response does not carry a source or target value (both are null) whereas the sent Attach has an appropriate source and target value. If that is what it is doing it gets it wrong as it omits the 'initial-delivery-count' which is required for an Attach with the Role of Sender (as per referenced spec above) regardless of the outcome of the attach. When the username is invalid: -> SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] SaslMechanisms{saslServerMechanisms=[MSSBCBS, PLAIN, ANONYMOUS, EXTERNAL]} -> SASL:[1793436274:0] SaslInit{mechanism=PLAIN, initialResponse="\x00INVALID_USERNAME\x00VALID_PASSWORD"...(truncated), hostname='MY_HOST.servicebus.windows.net'} <- SASL:[1793436274:0] SaslOutcome{code=OK, additionalData="Welcome!"} -> AMQP:[1793436274:0] AMQP,0,1,0,0 <- AMQP:[1793436274:0] AMQP,0,1,0,0 -> AMQP:[1793436274:0] Open{ containerId='ID:c07c99d2-692b-4c77--b56bfeb2e2e0:1:1', hostname=' cjtestmq.servicebus.windows.net', maxFrameSize=65536, channelMax=65535, idleTimeOut=6, outgoingLocales=null, incomingLocales=null, offeredCapabilities=null, desiredCapabilities=[ANONYMOUS-RELAY], properties=null} -> AMQP:[1793436274:0] Begin{remoteChannel=null, nextOutgoingId=0, incomingWindow=1600, outgoingWindow=2147483647, handleMax=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} -> AMQP:[1793436274:0] Attach{name='receiver-ID:c07c99d2-692b-4c77--b56bfeb2e2e0:1:1:1:1', handle=0, role=RECEIVER, sndSettleMode=UNSETTLED, rcvSettleMode=FIRST, source=Source{address='testq', durable=NONE, expiryPolicy=LINK_DETACH, timeout=0, dynamic=false, dynamicNodeProperties=null, distributionMode=null, filter=null, defaultOutcome=Modified{deliveryFailed=true, undeliverableHere=false, messageAnnotations=null}, outcomes=[amqp:accepted:list, amqp:rejected:list, amqp:released:list, amqp:modified:list], capabilities=null}, target=Target{address='testq', durable=NONE, expiryPolicy=SESSION_END, timeout=0, dynamic=false, dynamicNodeProperties=null, capabilities=null}, unsettled=null, incompleteUnsettled=null, initialDeliveryCount=null, maxMessageSize=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} -> AMQP:[1793436274:0] Flow{nextIncomingId=null, incomingWindow=1600, nextOutgoingId=0, outgoingWindow=2147483647, handle=0, deliveryCount=null, linkCredit=10, available=null, drain=false, echo=null, properties=null} <- AMQP:[1793436274:0] Open{
Re: ProtonJ2 Initial connection failure, reconnect logic
On Mon, Mar 11, 2024 at 9:33 PM Timothy Bish wrote: > > > The client re-connection logic treats a SASL authentication error as a > terminal state and will not continue reconnect attempts if it receives a > SASL outcome that indicates anything other than a temporary failure > state so it should be stopping the reconnect if it was actually failing > to authenticate. This is true on the first attempt as well as on > subsequent attempts to other hosts if you add more than one and it has > failed to reach any of the preceding hosts while attempt to recover the > connection. > > From the error logs attached it doesn't appear as though SASL > authentication is your issue though, at least in so much as it isn't > logging anything indicating SASL authentication as the error. Instead > the connection appears to be failing because the remote has sent a > response to the Receiver attach that does not include the initial > delivery count value as required by the specification. > > You can capture more information about the AMQP frames being sent and > received by enabling frame tracing, see the docs for how to do that. > > > https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging > > Thanks for getting back to me so quickly Tim, please find below the frames for a successful connection and an unsuccessful connection. My test has actually been to specify an invalid user if that's relevant. I can see in both cases that the SASL challenge completes successfully, which I appreciate is strange, but I would imagine Azure Service Bus is a common enough broker target for the library? When the username is invalid: -> SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] SaslMechanisms{saslServerMechanisms=[MSSBCBS, PLAIN, ANONYMOUS, EXTERNAL]} -> SASL:[1793436274:0] SaslInit{mechanism=PLAIN, initialResponse="\x00INVALID_USERNAME\x00VALID_PASSWORD"...(truncated), hostname='MY_HOST.servicebus.windows.net'} <- SASL:[1793436274:0] SaslOutcome{code=OK, additionalData="Welcome!"} -> AMQP:[1793436274:0] AMQP,0,1,0,0 <- AMQP:[1793436274:0] AMQP,0,1,0,0 -> AMQP:[1793436274:0] Open{ containerId='ID:c07c99d2-692b-4c77--b56bfeb2e2e0:1:1', hostname=' cjtestmq.servicebus.windows.net', maxFrameSize=65536, channelMax=65535, idleTimeOut=6, outgoingLocales=null, incomingLocales=null, offeredCapabilities=null, desiredCapabilities=[ANONYMOUS-RELAY], properties=null} -> AMQP:[1793436274:0] Begin{remoteChannel=null, nextOutgoingId=0, incomingWindow=1600, outgoingWindow=2147483647, handleMax=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} -> AMQP:[1793436274:0] Attach{name='receiver-ID:c07c99d2-692b-4c77--b56bfeb2e2e0:1:1:1:1', handle=0, role=RECEIVER, sndSettleMode=UNSETTLED, rcvSettleMode=FIRST, source=Source{address='testq', durable=NONE, expiryPolicy=LINK_DETACH, timeout=0, dynamic=false, dynamicNodeProperties=null, distributionMode=null, filter=null, defaultOutcome=Modified{deliveryFailed=true, undeliverableHere=false, messageAnnotations=null}, outcomes=[amqp:accepted:list, amqp:rejected:list, amqp:released:list, amqp:modified:list], capabilities=null}, target=Target{address='testq', durable=NONE, expiryPolicy=SESSION_END, timeout=0, dynamic=false, dynamicNodeProperties=null, capabilities=null}, unsettled=null, incompleteUnsettled=null, initialDeliveryCount=null, maxMessageSize=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} -> AMQP:[1793436274:0] Flow{nextIncomingId=null, incomingWindow=1600, nextOutgoingId=0, outgoingWindow=2147483647, handle=0, deliveryCount=null, linkCredit=10, available=null, drain=false, echo=null, properties=null} <- AMQP:[1793436274:0] Open{ containerId='5ffc5786e5b94e6da195e4e1c4660dd8_G4', hostname='null', maxFrameSize=65536, channelMax=4999, idleTimeOut=12, outgoingLocales=null, incomingLocales=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} <- AMQP:[1793436274:0] Begin{remoteChannel=0, nextOutgoingId=1, incomingWindow=5000, outgoingWindow=1600, handleMax=255, offeredCapabilities=null, desiredCapabilities=null, properties=null} <- AMQP:[1793436274:0] Attach{name='receiver-ID:c07c99d2-692b-4c77--b56bfeb2e2e0:1:1:1:1', handle=0, role=SENDER, sndSettleMode=null, rcvSettleMode=null, source=null, target=null, unsettled=null, incompleteUnsettled=null, initialDeliveryCount=null, maxMessageSize=null, offeredCapabilities=null, desiredCapabilities=null, properties=null} -> AMQP:[1793436274:0] Close{error=Error{condition=null, description='Sending peer attach had no initial delivery count', info=null}} 07:53:20,966 WARN ClientTransportListener:63 - Caught problem during incoming data processing: Sending peer attach had no initial delivery count For reference, when the username is valid: -> SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] AMQP,3,1,0,0 <- SASL:[1793436274:0] SaslMechanisms{saslServerMechanisms=[MSSBCBS, PLAIN, ANONYMOUS,
Re: ProtonJ2 Initial connection failure, reconnect logic
On 3/11/24 16:54, Ciaran wrote: Hi all, I'm taking a look at using ProtonJ2 to talk to Azure Service Bus and I've successfully gotten everything up and running, with and without websockets, now I'm turning my attention to the 'unhappy path' of network drop-outs and misconfigurations leading to connection failures. Is it possible to have a behaviour where: - If an initial connection fails, the error is immediately propagated and background reconnect attempts are not attempted. - If an initial connection was successful then background reconnect attempts are attempted. >From looking through the api docs and reading the code, I believed that configuring the following would exhibit the behaviours described. options.reconnectOptions().reconnectEnabled(true); options.reconnectOptions().maxInitialConnectionAttempts(1); options.reconnectOptions().useReconnectBackOff(); *However, when connecting to Azure Service Bus with a deliberately invalid password, it appears as though the reconnect logic is continuing in the background (exceptions spamming my log ), not aborting on first connection attempt. *Is this the expected behaviour? I took a brief look at the code and can see that 'connectionEstablished' in the ClientConnection class is being called even though the connection can't possibly succeed as the authentication is wrong, is that expected behaviour of the internals? I've tried to summarise the code I have below, I've removed error handling, resource cleanup for clarity: final String serverHost = "MY_HOST.servicebus.windows.net"; final int serverPort = 443; final String address = "testq"; final String user = "MY_USER"; final String password= "MY_PASSWORD_BUT_INVALIDATED_FOR_THIS_TEST"; final boolean useSSL = true; final boolean useWebSockets = true; final Client client = Client.create(); ConnectionOptions options = new ConnectionOptions().user(user).password(password); options.sslOptions().sslEnabled(useSSL); options.transportOptions().useWebSockets(useWebSockets); options.transportOptions().webSocketPath("/$servicebus/websocket"); options.reconnectOptions().reconnectEnabled(true); options.reconnectOptions().maxInitialConnectionAttempts(1); options.reconnectOptions().useReconnectBackOff(); Connection connection = client.connect(serverHost, serverPort, options); ReceiverOptions ro = new ReceiverOptions(); ro.autoAccept(false); Receiver receiver = connection.openReceiver( address, ro); My exception / warning logs are contained at the end of the email, the second email repeats until a ClientOperationTimedOutException is thrown with the message 'Link open timed out waiting for remote to respond'. Obviously, I could seperate the code into one client that does not have reconnect logic enabled to determine if a connection is even *possible* before engaging my proper client, but it seemed like the API offerred the behaviour I was after? Thank you for your patience if you made it this far - Cj. The client re-connection logic treats a SASL authentication error as a terminal state and will not continue reconnect attempts if it receives a SASL outcome that indicates anything other than a temporary failure state so it should be stopping the reconnect if it was actually failing to authenticate. This is true on the first attempt as well as on subsequent attempts to other hosts if you add more than one and it has failed to reach any of the preceding hosts while attempt to recover the connection. From the error logs attached it doesn't appear as though SASL authentication is your issue though, at least in so much as it isn't logging anything indicating SASL authentication as the error. Instead the connection appears to be failing because the remote has sent a response to the Receiver attach that does not include the initial delivery count value as required by the specification. You can capture more information about the AMQP frames being sent and received by enabling frame tracing, see the docs for how to do that. https://github.com/apache/qpid-protonj2/blob/main/protonj2-client-docs/Configuration.md#logging Exception / logs below --- 20:49:52,348 WARN SaslMechanismSelector:130 - Caught exception while trying to create SASL mechanism MSSBCBS: No Matching SASL Mechanism with name: MSSBCBS 20:49:52,652 WARN ClientTransportListener:63 - Caught problem during incoming data processing: Sending peer attach had no initial delivery count org.apache.qpid.protonj2.engine.exceptions.EngineFailedException: Sending peer attach had no initial delivery count at org.apache.qpid.protonj2.engine.exceptions.ProtonExceptionSupport.createFailedException(ProtonExceptionSupport.java:63) at org.apache.qpid.protonj2.engine.exceptions.ProtonExceptionSupport.createFailedException(ProtonExceptionSupport.java:31) at org.apache.qpid.protonj2.engine.impl.ProtonEngine.engineFailed(ProtonEngine.java:306) at
ProtonJ2 Initial connection failure, reconnect logic
Hi all, I'm taking a look at using ProtonJ2 to talk to Azure Service Bus and I've successfully gotten everything up and running, with and without websockets, now I'm turning my attention to the 'unhappy path' of network drop-outs and misconfigurations leading to connection failures. Is it possible to have a behaviour where: - If an initial connection fails, the error is immediately propagated and background reconnect attempts are not attempted. - If an initial connection was successful then background reconnect attempts are attempted. >From looking through the api docs and reading the code, I believed that configuring the following would exhibit the behaviours described. options.reconnectOptions().reconnectEnabled(true); options.reconnectOptions().maxInitialConnectionAttempts(1); options.reconnectOptions().useReconnectBackOff(); *However, when connecting to Azure Service Bus with a deliberately invalid password, it appears as though the reconnect logic is continuing in the background (exceptions spamming my log ), not aborting on first connection attempt. *Is this the expected behaviour? I took a brief look at the code and can see that 'connectionEstablished' in the ClientConnection class is being called even though the connection can't possibly succeed as the authentication is wrong, is that expected behaviour of the internals? I've tried to summarise the code I have below, I've removed error handling, resource cleanup for clarity: final String serverHost = "MY_HOST.servicebus.windows.net"; final int serverPort = 443; final String address = "testq"; final String user = "MY_USER"; final String password= "MY_PASSWORD_BUT_INVALIDATED_FOR_THIS_TEST"; final boolean useSSL = true; final boolean useWebSockets = true; final Client client = Client.create(); ConnectionOptions options = new ConnectionOptions().user(user).password(password); options.sslOptions().sslEnabled(useSSL); options.transportOptions().useWebSockets(useWebSockets); options.transportOptions().webSocketPath("/$servicebus/websocket"); options.reconnectOptions().reconnectEnabled(true); options.reconnectOptions().maxInitialConnectionAttempts(1); options.reconnectOptions().useReconnectBackOff(); Connection connection = client.connect(serverHost, serverPort, options); ReceiverOptions ro = new ReceiverOptions(); ro.autoAccept(false); Receiver receiver = connection.openReceiver( address, ro); My exception / warning logs are contained at the end of the email, the second email repeats until a ClientOperationTimedOutException is thrown with the message 'Link open timed out waiting for remote to respond'. Obviously, I could seperate the code into one client that does not have reconnect logic enabled to determine if a connection is even *possible* before engaging my proper client, but it seemed like the API offerred the behaviour I was after? Thank you for your patience if you made it this far - Cj. Exception / logs below --- 20:49:52,348 WARN SaslMechanismSelector:130 - Caught exception while trying to create SASL mechanism MSSBCBS: No Matching SASL Mechanism with name: MSSBCBS 20:49:52,652 WARN ClientTransportListener:63 - Caught problem during incoming data processing: Sending peer attach had no initial delivery count org.apache.qpid.protonj2.engine.exceptions.EngineFailedException: Sending peer attach had no initial delivery count at org.apache.qpid.protonj2.engine.exceptions.ProtonExceptionSupport.createFailedException(ProtonExceptionSupport.java:63) at org.apache.qpid.protonj2.engine.exceptions.ProtonExceptionSupport.createFailedException(ProtonExceptionSupport.java:31) at org.apache.qpid.protonj2.engine.impl.ProtonEngine.engineFailed(ProtonEngine.java:306) at org.apache.qpid.protonj2.engine.impl.ProtonEngine.ingest(ProtonEngine.java:271) at org.apache.qpid.protonj2.engine.impl.ProtonEngine.ingest(ProtonEngine.java:54) at org.apache.qpid.protonj2.client.impl.ClientTransportListener.transportRead(ClientTransportListener.java:59) at org.apache.qpid.protonj2.client.transport.netty4.TcpTransport$NettyDefaultHandler.dispatchReadBuffer(TcpTransport.java:522) at org.apache.qpid.protonj2.client.transport.netty4.WebSocketTransport$NettyWebSocketTransportHandler.channelRead0(WebSocketTransport.java:239) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at