-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Support Microsoft.Extensions.Hosting.Abstractions #4702
Comments
There is an open question about API style:
Top-level builderAttach all configuration methods to hostBuilder
.AddOrleans()
.UseLocalhostClustering()
.AddMemoryGrainStorage("MemoryStore"); Pro: It's more obvious that there is a single DI container Sub-builderCreate a new type, hostBuilder.AddOrleans(builder =>
builder
.UseLocalhostClustering()
.AddMemoryGrainStorage("MemoryStore")); Pro: It's clear that those methods belong to Orleans and they will appear via intellisense in the correct context. As a potential workaround for that con, we can create a new builder type which makes the relationship to public interface IOrleansBuilder
{
IHostBuilder HostBuilder { get; }
} This can then be implemented explicitly to hide public class OrleansBuilder : IOrleansBuilder
{
private readonly IHostBuilder builder;
public OrleansBuilder(IHostBuilder builder) => this.builder = builder;
IHostBuilder IOrleansBuilder.HostBuilder => this.builder;
} That helps to hide the At the same time, extension writers see Extension methods will look like this: public static class OrleansBuilderExtensions
{
public static TBuilder ConfigureThingy<TBuilder>(
this TBuilder builder,
Action<OptionsBuilder<ThingyOptions>> configure) where TBuilder : IOrleansBuilder
{
// Do something with HostBuilder, like configure services.
return builder;
}
} Then we can expose the public static IHostBuilder AddOrleans(
this IHostBuilder hostBuilder,
Action<OrleansBuilder> configure)
{
configure(new OrleansBuilder(hostBuilder));
return hostBuilder;
} This way, the end-user can use extension methods defined against I believe that the proposed pattern with the sub-builder presents a better user experience to the top-level builder. We could consider similar changes for the client builder, but I don't have a well-formed opinion on that yet. Suggestions welcome 😊 xref: aspnet/Hosting#1279 |
My vote is for option 2 (sub builder). We talked and tried many things with option 1 and variants of 2, but we concluded that configuring in the context of an Orleans builder is very important. There are already a few things that work in that way in the Microsoft.Extensions namespace, such as when you configure Logging or use Also, all the temporary hosting work we did today in Orleans 2.0 would make that option straightforward for our users to move to (albeit some minor tweaking of 1 or 2 lines of code in their setup). In fact, the team agreed to remove all the duplicate extension methods that configure I'm not too convinced about hiding |
Some examples for the syntax of variant 1: But variant 1 would just return the subbuilder |
While my views on this are still quite malleable, atm, I also advocate a sub-builder. I see an Orleans silo as a hosted service, and would prefer to configure it as such using an ISiloBuilder. The move to IHostBuilder should not necessarily deprecate ISiloHostBuilder, as silo host builder can be maintained as a façade over IHostBuilder to support the common configuration pattern of a host with a single Orleans silo. |
@SebastianStehle the thing is, ASP.NET is in a transition and is still evolving. Those patterns were created for the Startup Class configuration model, which predates the Generic Host work. ASP.NET folks have said in the past that they want to get rid of that model since it has problems. For example it requires a temporary container and doesn't play well with hosting (eg, how do you pass context from Service Fabric to it?). We deprecated the Startup Class with the 2.0 transition and are already on a model very similar to the Generic Host. Now we need to consider what the .NET ecosystem is going to look like once others make the transition. The issue with The sub-builder model is more consistent. Still, it's important to align with whatever the rest of the ecosystem is moving towards, so I'm fine with whatever that ends up being. |
Thx for the long explanation. Was not aware of that |
Generally the sub-builder is a better way to go IMHO. In real world that builder could be a no-op, without a Build method just a marker interface to stuff the extension methods on, a'la Logging and MVCs builder. For non-breaking change I'd suggest to make the method public which registers the internal Orleans things and have that on IServiceCollection instead of ISiloHostBuilder. This has multiple positive outcomes:
Extensions are also affected, did not check (because we've a lot), but I suspect that none or at least not to many of them registering internal classes in extension methods attached to the ISiloHostBuilder interface, if they're a modification also needed there. Which again would not be breaking anyone. Regarding the opening up of that internal method: It could be moved into an Internal namespace within the current one, but be public. ASP.NET team also follows this pattern for things that can change in the future. It would be good to see it in 2.1. |
If we put methods on |
We've also landed on the sub builder design. It's time to wake this thread up! 😄 |
Thanks, @davidfowl - I think we're on the same page. To enable this earlier than 3.0, we can follow this plan:
For 3.0, we can clean up:
This would be a breaking change, but I think the end result is better than having two entirely separate interfaces. There's only minor ease-of-upgrade benefit in keeping a separate The key interface: public interface ISiloBuilder
{
IDictionary<string, object> Properties { get; }
ISiloBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate);
} Both methods just forward their counterparts on As an alternative to removing ISiloBuilder AddMyProvider(this ISiloBuilder builder, ...) to T AddMyProvider<T>(this T builder, ...) where T : ISiloBuilder so that users don't lose the ability to write var silo = new SiloHostBuilder().AddMyProvider(...).Build(); (since otherwise It might be worth going with this approach so that we can support adding a silo to the host builder in its own, separate container in the future, which would likely involve adding a new interface derived from |
Working on a PR aligned to @ReubenBond description... |
cc @glennc |
Can you not keep the ISiloHostBuilder, so that extension projects do not need an update to support GenericHost? |
@SebastianStehle better to break then extensions than break the runtime directly IMHO |
Yes, I had a second look to this interface and I also do not see and option to keep it. |
I assume that this proposal works for everyone. @galvesribeiro's PR looks good to me |
Using the existing ISiloHostBuilder, I make use of UseServiceProviderFactory, however this does not seem to be possible when using the UseOrleans extension method. Am I missing something please? |
@matthewgrimagig instead of using that to configure the container on Orleans directly, check the Configuring Generic Host Container here. |
thanks @galvesribeiro, no idea how I didn't think about that. Any idea when 2.3.0 will be released? |
Dunno. @ReubenBond perhaps have a clue. |
We can release it as early as next week. Just waiting for people to try 2.3.0-rc1 to see if we missed something. |
In Orleans 2.0, we added
SiloHostBuilder
, which was designed to align withIHostBuilder
from theMicrosoft.Extensions.Hosting.Abstractions
package (which wasn't yet released).The intention was that
SiloHostBuilder
would be temporary and we would add support for the generic host once it became available.It's available now, so we can consider adding support for it.
ASP.NET folks have a similar issue opened for
WebHostBuilder
: https://github.com/aspnet/Hosting/issues/1421. They've scheduled it for 3.0.0, so I imagine it will be a year or more before they move over.I have a PoC for this on a branch here: master...ReubenBond:feature-generic-host
cc @galvesribeiro & @attilah who asked for this today
The text was updated successfully, but these errors were encountered: