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

Abstraction of ServiceProvider, Improving Akka.DependencyInjection #4814

Merged

Conversation

SamEmber
Copy link
Contributor

@SamEmber SamEmber commented Mar 6, 2021

Hi Guys,

I started using the new Akka.DependencyInjection library for MS-DI recently and I have run across a few issues that I would like to address.

The initial problem I faced was the tight coupling of the actor system DI to IServiceProvider. My team have a testing library where we substitute child actors for test probes, previously we did this via AddDependencyResolver however this has now been removed. Currently this coupling is making it very hard to achieve the previous functionality.

I propose a change to the ServiceProvider where instead of passing in an IServiceProvider we instead pass in a IDependencyResolver interface, by default this IDependencyResolver will be a SeriveProviderDependencyResolver that uses the IServiceProvider to resolve any DI dependencies. This will allow others to create their own implementations of the IDependencyResolver for testing.

I want to make it clear that I don't want to change the functionality of the current DI service resolution, its still extremely important that users manage the lifetime of their dependencies and this change will not effect that.

Secondly I have added the ability to resolve actor props from a Type param, this should make it easier to create actors dynamically.

I am very open to any feedback. I have not properly commented the code yet as I want to make sure this is a reasonable proposal from the community before I spent more time to complete this.

Thanks,

Sam

@SamEmber SamEmber changed the title Abstraction of ServiceProvider Abstraction of ServiceProvider, Improving Akka.DependencyInjection Mar 6, 2021
@Aaronontheweb Aaronontheweb self-requested a review March 8, 2021 15:13
@Aaronontheweb
Copy link
Member

Thanks @SamEmber - we'll take a look at this soon

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

So I approve of the concept and the changes, but we need to introduce these in a more backwards-compatible way - along with the changes we're making to the ServiceProviderProps in a separate PR.

I'll help make this happen as part of the 1.4.18 release.

///
/// The constructor is internal. Please use <see cref="Create"/> to create a new instance.
/// </summary>
public class DependencyResolverSetup : Setup
Copy link
Member

Choose a reason for hiding this comment

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

It would be far better if we kept the ServiceProvider setup so we can avoid breaking the public API.

/// Provides users with immediate access to the <see cref="IDependencyResolver"/> bound to
/// this <see cref="ActorSystem"/>, if any.
/// </summary>
public sealed class DependencyResolver : IExtension
Copy link
Member

Choose a reason for hiding this comment

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

We probably shouldn't rename the extension here, for API compatibility reasons


namespace Akka.DependencyInjection
{
public interface IDependencyResolver
Copy link
Member

Choose a reason for hiding this comment

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

So I'm supportive of adding this abstraction, after discussing it with @to11mtm and reviewing some of Mark Seeman's advice here: https://blog.ploeh.dk/2014/05/19/di-friendly-framework/

We've already run into "conforming container" problems with Microsoft.Extensions.DependencyInjection 3.0 vs. 5.0 - so an abstraction like yours would be helpful for users who need to roll-forward before the library itself can.

///
/// Relies on having an active <see cref="IServiceProvider"/> implementation available
/// </summary>
internal class ServiceProviderProps : Props
Copy link
Member

Choose a reason for hiding this comment

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

We're going to remove this concept altogether in #4853 and replace it with an IIndirectActorProducer, similar to what we did in the original Akka.DI.Core library.

We should probably merge that PR in first once it gets submitted, then rebase this on top of it.

IDependencyResolver Resolver { get; }
}

public class ServiceProviderScope : IResolverScope
Copy link
Member

Choose a reason for hiding this comment

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

Fine with this abstraction too

@SamEmber
Copy link
Contributor Author

Thanks for taking the time to look at this Aaron, these all sound like sensible changes to me. Pleased that my suggestion will be taken into account, please let me know if there is anything I can do to help out.

@Aaronontheweb
Copy link
Member

Thanks @SamEmber - we'll be discussing these changes at our community standup today: #4856 - my hope is to get them rolled up and out soon

@Aaronontheweb
Copy link
Member

Need to get this one merged and approved into dev first, then we can integrate this PR: #4858

@Aaronontheweb Aaronontheweb modified the milestones: 1.4.18, 1.4.19 Mar 18, 2021
@Aaronontheweb Aaronontheweb self-assigned this Apr 14, 2021
@SamEmber
Copy link
Contributor Author

Hey @Aaronontheweb, was this ever integrated?

@Aaronontheweb
Copy link
Member

@SamEmber not yet - was up to my neck in Akka.Cluster issues over the past month. We will probably bump this to 1.4.20

@Aaronontheweb Aaronontheweb modified the milestones: 1.4.19, 1.4.20 Apr 28, 2021
@Aaronontheweb Aaronontheweb modified the milestones: 1.4.20, 1.4.21 May 12, 2021
@chris-sung
Copy link

chris-sung commented May 25, 2021

Secondly I have added the ability to resolve actor props from a Type param, this should make it easier to create actors dynamically.

I thought we need this too. there's no easy way to dynamically create an actor with ServiceProvider and that is my pain point writing test with ServiceProvider

Also, I've been writing using ServiceProvider = Akka.DependencyInjection.ServiceProvider; everywhere I use ServiceProvider due to conflicting class name and is quite a pain, could we mark the old class obsolete and let it sit backward compatible way and moving on?

@Aaronontheweb
Copy link
Member

Also, I've been writing using ServiceProvider = Akka.DependencyInjection.ServiceProvider; everywhere I use ServiceProvider due to conflicting class name and is quite a pain, could we mark the old class obsolete and let it sit backward compatible way and moving on?

We'll give it our best shot.

@Aaronontheweb Aaronontheweb force-pushed the 4813-abstraction-of-serviceprovider-in-a branch from ded7717 to 7815c96 Compare May 25, 2021 02:34
@Aaronontheweb
Copy link
Member

Ok, just introduced my non-breaking API implementation version of this - but someone else (@chris-sung @SamEmber included) will have to review it before we can merge it.

  • Old APIs should be marked as obsolete
  • Should offer type-checking (i.e. generics) all the way down the stack up until we reach Props if wanted
  • New APIs should be painless to switch to
  • Documentation should feature new APIs
  • No breaking API changes if we can absolutely help it

Pretty sure I did all of that, but need the review to verify.

@Aaronontheweb Aaronontheweb self-requested a review May 25, 2021 02:37
Copy link
Contributor

@Arkatufus Arkatufus left a comment

Choose a reason for hiding this comment

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

Everything looks fine, I just have a little suggestion for one of the methods.

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

LGTM

@Aaronontheweb Aaronontheweb requested a review from Arkatufus May 26, 2021 20:57
@SamEmber
Copy link
Contributor Author

Awesome, this looks great @Aaronontheweb. Thanks for taking the time to make the required changes.

@Aaronontheweb
Copy link
Member

Crap, looks like I broke the build - that's what I get for attempting to edit a PR using the Github editor :p

@Aaronontheweb Aaronontheweb dismissed Arkatufus’s stale review May 26, 2021 21:41

Implemented his suggestions

@Aaronontheweb Aaronontheweb enabled auto-merge (squash) May 26, 2021 21:41
@Aaronontheweb
Copy link
Member

No problem @SamEmber - thank you for your contribution and sorry it took me so long to get around to this. Didn't take me long to implement the changes we discussed at all, just had a full plate up until this week.

@Aaronontheweb Aaronontheweb merged commit c663bc2 into akkadotnet:dev May 26, 2021
@christallire
Copy link

Fantastic. Thanks for the quick resolution

Aaronontheweb added a commit to Aaronontheweb/akka.net that referenced this pull request May 28, 2021
Abstraction of ServiceProvider, Improving Akka.DependencyInjection (akkadotnet#4814)

* Abstraction of ServiceProvider

* introduced non-breaking Akka.DependencyInjection API changes

* fixed unit tests / Props bug

* fixed up DelegateInjectionSpecs

* Added type checking for `Props(Type type, params object[] args)`

* fixed non-generic `Props()` method

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

completed work on ActorPath parsing
Aaronontheweb added a commit that referenced this pull request May 28, 2021
* `Span<char>`-ifying ActorPath and Address parsing

Abstraction of ServiceProvider, Improving Akka.DependencyInjection (#4814)

* Abstraction of ServiceProvider

* introduced non-breaking Akka.DependencyInjection API changes

* fixed unit tests / Props bug

* fixed up DelegateInjectionSpecs

* Added type checking for `Props(Type type, params object[] args)`

* fixed non-generic `Props()` method

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

completed work on ActorPath parsing

* restore Parse performance to ActorPath.Parse

* fixed `ActorPath.ToString()`
This was referenced Jun 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants