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

[service-bus] Allow initLink() and closeLink() to lock, preventing reentrancy/concurrency issues #10807

Conversation

richardpark-msft
Copy link
Member

initLink and closeLink had some basic coordination so they wouldn't stomp over each other but they never coordinated via locks which made it so the state of the object would be different than you expected.

This commit makes it so both closeLink and openLink depend on the same lock, which allows you to make the modifications to the link state obey ordering. This simplifies some parts of the code that tried to avoid opening and closing simultaneously.

As part of this the lock token that was being used in other parts of the code has been subsumed into LinkEntity instead so some modification to the detached/init methods of child classes changed.

Also, removed some code in ManagementLink that has become redundant with our unified initLink() code (abort signal handling and some link state checking).

Fixes #10656

…he open/close state of the link into LinkEntity.
The detach() calls have been simplified dramatically. Logically this appears okay - all init()/close() calls will run serially now (thanks to the lock) so it's perfectly safe to allow them to "coallesce".

The net result will still be an initialized connection.
…etached

- Remove unneeded checkAborted method - we can just let the normal initLink function handle it.
* Fix isOpen() to return false when the internal link hasn't yet been defined
* Strip out <a:address> from the log prefix - it's already encoded into the entity name.
…rtSignal handling (initLink will handle it all).
Copy link
Contributor

@ramya-rao-a ramya-rao-a 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, left a few comments. Please take a look

sdk/servicebus/service-bus/src/core/linkEntity.ts Outdated Show resolved Hide resolved
sdk/servicebus/service-bus/src/core/messageSender.ts Outdated Show resolved Hide resolved
@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

sdk/servicebus/service-bus/src/core/linkEntity.ts Outdated Show resolved Hide resolved
sdk/servicebus/service-bus/src/core/messageSender.ts Outdated Show resolved Hide resolved
sdk/servicebus/service-bus/src/core/messageSender.ts Outdated Show resolved Hide resolved
sdk/servicebus/service-bus/src/core/streamingReceiver.ts Outdated Show resolved Hide resolved
sdk/servicebus/service-bus/src/core/streamingReceiver.ts Outdated Show resolved Hide resolved
@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

…ng into a common init() function that handles locking ,etc...
…ing the sending portion (not init) were being "eaten" because the callback passed to the Promise is async.
…sed.

- Also, update some log messages to be a bit more accurate.
@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

I had inadvertantly created an eternal call stack that would never end by causing negotiateClaim to cause continual calls to initLink and closeLink. This isn't even a recovery scenario as all the scenarios would eventually either fail by exhausting retries or because the link does eventually open.

In addition I added in some code and tests for a dead lock scenario that I observed. Basically we could end up with this call stack:

linkEntity.initLink()
  <enter lock>
  linkEntity.negotiateClaim()
    connectionContext.readyToOpenLink()
       refreshConnection() occurs
           calls linkEntity.closeLink()
              <attempts to enter lock and blocks>

The fix to this was two-fold:
1. Check the ready state of the connection before even entering into lock for initLink.
2. Within initLink, before we call negotiateClaim, do a status check to ensure that the connection is "ready". If it is not then go ahead and throw.
@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ramya-rao-a
Copy link
Contributor

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

…not in a restarting state (and more unit tests for it).
@richardpark-msft
Copy link
Member Author

/azp run js - servicebus - tests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

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.

[service-bus] Further initLink()/closeLink() consolidation
2 participants