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

Refactor request invocation to be extensible. #641

Conversation

NTaylorMullen
Copy link
Contributor

  • The initial motivation for this change spawned from an investigation in the Razor language server where transitioning from Parallel -> Serial tasks would wait on Parallel work to finish. In scenarios when that parallel work took a long time this could result in significant editor delays in completion where you'd have Parallel (long) -> Serial -> Parallel (completion, short). I played around with changing the System.Reactive bits to have an option to not "wait" for the parallel stacks but System.Reatcive as a library wasn't truly built to handle that type of "change your mind after-the-fact" flow.
  • Prior to this change the routing & scheduling aspects of the JsonRpc stack are bound to our ProcessScheduler & InputHandler.RouteRequest & InputHandler.RouteNotification endspoints. This change allows that entire stack to be extensible so consumers can plug & play.
  • Added a RequestInvoker type which represents the core logic of how the framework invokes a handler for a request. This encapsulates the control flow for invoking, scheduling and handling fallout from invoking a handler.
  • Added a RequestInvokerOptions type to represent what sort of settings should be applied for the request invoker paradigm.
  • Expanded InputHandler & Connection to have two new constructors that take in a request invoker and obsoleted the old ones. Updated tests to account for this.
  • Registered the default request invoker type (the one that uses System.Reactive) if a request invoker was not already registered.

Make existing request response types fully public

  • For consumers who are creating their own RequestInvoker they need to manually construct many of our response types. Therefore, the constructors need to also be puclic.

- The initial motivation for this change spawned from an investigation in the Razor language server where transitioning from Parallel -> Serial tasks would wait on Parallel work to finish. In scenarios when that parallel work took a long time this could result in significant editor delays in completion where you'd have Parallel (long) -> Serial -> Parallel (completion, short). I played around with changing the System.Reactive bits to have an option to not "wait" for the parallel stacks but System.Reatcive as a library wasn't truly built to handle that type of "change your mind after-the-fact" flow.
- Prior to this change the routing & scheduling aspects of the JsonRpc stack are bound to our ProcessScheduler & InputHandler.RouteRequest & InputHandler.RouteNotification endspoints. This change allows that entire stack to be extensible so consumers can plug & play.
- Added a `RequestInvoker` type which represents the core logic of how the framework invokes a handler for a request. This encapsulates the control flow for invoking, scheduling and handling fallout from invoking a handler.
- Added a `RequestInvokerOptions` type to represent what sort of settings should be applied for the request invoker paradigm.
- Expanded `InputHandler` & `Connection` to have two new constructors that take in a request invoker and obsoleted the old ones. Updated tests to account for this.
- Registered the default request invoker type (the one that uses System.Reactive) if a request invoker was not already registered.
- For consumers who are creating their own `RequestInvoker` they need to manually construct many of our response types. Therefore, the constructors need to also be puclic.
@codecov
Copy link

codecov bot commented Aug 23, 2021

Codecov Report

Merging #641 (903ca76) into master (89a97d1) will increase coverage by 0.01%.
The diff coverage is 93.48%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #641      +/-   ##
==========================================
+ Coverage   69.41%   69.43%   +0.01%     
==========================================
  Files         257      260       +3     
  Lines       12580    12624      +44     
  Branches      848      853       +5     
==========================================
+ Hits         8732     8765      +33     
- Misses       3578     3584       +6     
- Partials      270      275       +5     
Impacted Files Coverage Δ
src/JsonRpc/TimeLoggerExtensions.cs 52.38% <ø> (ø)
src/JsonRpc/ContentModified.cs 50.00% <50.00%> (ø)
src/JsonRpc/RequestCancelled.cs 50.00% <50.00%> (ø)
src/JsonRpc/RequestInvocationHandle.cs 75.00% <75.00%> (ø)
src/JsonRpc/RequestInvokerOptions.cs 88.88% <88.88%> (ø)
src/JsonRpc/InputHandler.cs 80.83% <92.85%> (-5.24%) ⬇️
src/JsonRpc/DefaultRequestInvoker.cs 95.62% <95.62%> (ø)
src/JsonRpc/Connection.cs 100.00% <100.00%> (+2.56%) ⬆️
...sonRpc/JsonRpcServerServiceCollectionExtensions.cs 83.33% <100.00%> (+0.94%) ⬆️
src/Client/LspClientOutputFilter.cs 52.94% <0.00%> (-29.42%) ⬇️
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 89a97d1...903ca76. Read the comment docs.

Observable.Create<ErrorResponse>(
observer => {
// ITS A RACE!
var sub = Observable.Amb(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All this is verbatim from the original RouteRequest method in InputHandler.

NTaylorMullen added a commit to dotnet/razor that referenced this pull request Aug 24, 2021
- With the latest OmniSharp upgrade there were a few high profile changes:
    - Most DTO's are records now which makes them immutable. You'll see throughout the codebase that we now have to use `with {...}` to translate one type to another.
    - `ServerCapabilities` are expandable by default. This means we no longer need our `ExtendableServerCapabilities` type.
    - Getting client and server capabilities in each of our endpoints are now a single method call. This resulted in lots of deleted code.
    - O# upgraded its LSP version to 3.17 which means semantic tokens are no longer proposed. This resulted in a lot of warnings/obsolete bits getting removed. We now also have code action resolution as part of this upgrade so we could remove our old code action resolution endpoint (it's in VSCode now too).
- This changeset is in preparation for another O# release where we'll replace the [O# request invoker](OmniSharp/csharp-language-server-protocol#641) to get some pretty massive perf wins!

Fixes dotnet/aspnetcore#35622
NTaylorMullen added a commit to dotnet/razor that referenced this pull request Aug 24, 2021
- With the latest OmniSharp upgrade there were a few high profile changes:
    - Most DTO's are records now which makes them immutable. You'll see throughout the codebase that we now have to use `with {...}` to translate one type to another.
    - `ServerCapabilities` are expandable by default. This means we no longer need our `ExtendableServerCapabilities` type.
    - Getting client and server capabilities in each of our endpoints are now a single method call. This resulted in lots of deleted code.
    - O# upgraded its LSP version to 3.17 which means semantic tokens are no longer proposed. This resulted in a lot of warnings/obsolete bits getting removed. We now also have code action resolution as part of this upgrade so we could remove our old code action resolution endpoint (it's in VSCode now too).
    - The way the O# serializer gets construed now is different and extendable. Because of this we now have a primary method to add all of our converters to an O# serializer.
    - O# embraced the optional vs. required text document identifiers. This makes it super clear whenever we're expected to provided a document version or not. Probably one of my favorite changes in the upgrade.
    - A new dependency of `System.Threading.Channels` was introduced so we had to make sure that was included in our VS scenarios.
- This changeset is in preparation for another O# release where we'll replace the [O# request invoker](OmniSharp/csharp-language-server-protocol#641) to get some pretty massive perf wins!

Fixes dotnet/aspnetcore#35622
Copy link
Member

@david-driscoll david-driscoll left a comment

Choose a reason for hiding this comment

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

LGTM -- Just the one issue with the input scheduler, and then it should be GTG.


if (!container.IsRegistered<RequestInvoker>())
{
container.Register<RequestInvoker, DefaultRequestInvoker>(Reuse.Singleton);
Copy link
Member

Choose a reason for hiding this comment

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

This is missing .Type<IScheduler>(serviceKey: nameof(options.InputScheduler))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ooo, out of curiosity why not have that be registered by default?

@NTaylorMullen
Copy link
Contributor Author

🆙 📅

@github-actions github-actions bot added this to the v0.19.5 milestone Aug 24, 2021
ghost pushed a commit to dotnet/razor that referenced this pull request Aug 24, 2021
* Upgrade OmniSharp to 0.19.4.

- With the latest OmniSharp upgrade there were a few high profile changes:
    - Most DTO's are records now which makes them immutable. You'll see throughout the codebase that we now have to use `with {...}` to translate one type to another.
    - `ServerCapabilities` are expandable by default. This means we no longer need our `ExtendableServerCapabilities` type.
    - Getting client and server capabilities in each of our endpoints are now a single method call. This resulted in lots of deleted code.
    - O# upgraded its LSP version to 3.17 which means semantic tokens are no longer proposed. This resulted in a lot of warnings/obsolete bits getting removed. We now also have code action resolution as part of this upgrade so we could remove our old code action resolution endpoint (it's in VSCode now too).
    - The way the O# serializer gets construed now is different and extendable. Because of this we now have a primary method to add all of our converters to an O# serializer.
    - O# embraced the optional vs. required text document identifiers. This makes it super clear whenever we're expected to provided a document version or not. Probably one of my favorite changes in the upgrade.
    - A new dependency of `System.Threading.Channels` was introduced so we had to make sure that was included in our VS scenarios.
- This changeset is in preparation for another O# release where we'll replace the [O# request invoker](OmniSharp/csharp-language-server-protocol#641) to get some pretty massive perf wins!

Fixes dotnet/aspnetcore#35622

* Addressed code review comments

- Set => Init
- Removal of semantic token legend endpoint
- Some refactoring in our serializer extensions
- Test fixups
@david-driscoll david-driscoll enabled auto-merge (squash) August 27, 2021 13:45
@david-driscoll david-driscoll merged commit a361160 into OmniSharp:master Aug 27, 2021
@github-actions github-actions bot added the mysterious We forgot to label this label Aug 27, 2021
@NTaylorMullen
Copy link
Contributor Author

Dopeness! Thank you @david-driscoll! Would it be possible to publish another version of the langauge server with this?

@NTaylorMullen NTaylorMullen deleted the nimullen/refactor.requestinvocation branch August 27, 2021 18:48
@andyleejordan
Copy link
Contributor

Very cool work here!

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

Successfully merging this pull request may close these issues.

3 participants