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

3.0 tracking issue - rewriting source generation #98

Open
4 of 9 tasks
martinothamar opened this issue Jun 21, 2023 · 21 comments
Open
4 of 9 tasks

3.0 tracking issue - rewriting source generation #98

martinothamar opened this issue Jun 21, 2023 · 21 comments
Milestone

Comments

@martinothamar
Copy link
Owner

martinothamar commented Jun 21, 2023

Things I want to solve/merge in 3.0.

To solve these I'll be rewriting the source generation process. I will be starting out in an experimental branch
and seek feedback before bringing it into main (which is targeting 3.0 preview).

The task list is sorted from most difficult to least difficult (assumed).

@martinothamar martinothamar added this to the 3.0 milestone Jun 21, 2023
@martinothamar
Copy link
Owner Author

Another thing I've considered: should this library be renamed? "Mediator" is kind of plain/vanilla. It's basically a working title that I never changed. Feel free to drop suggestions and feedback..

@TimothyMakkison
Copy link
Contributor

Improve performance for large number of messages #440

Have you looked at using liquid instead of scriban? Fluid appears to be more performant than scriban. Not sure if liquid supports all your requirements

@martinothamar
Copy link
Owner Author

Not considered it yet, but open to it! Would be fairly easy to migrate I think. I'd like to hold off on that until the top 4 issues are completed though, since there will be significant changes in the source generator

@TimothyMakkison
Copy link
Contributor

TimothyMakkison commented Jun 27, 2023

I'm not sure how much scriban affects performance tbh. Perhaps parsing the template once and reusing it could help, although I'm not sure if source generators allow this.

I'd like to hold off on that until the top 4 issues are completed though, since there will be significant changes in the source generator

Looking forward to seeing your changes, this project has been super helpful when wokring on Mapperly.

@ejsmith
Copy link

ejsmith commented Jun 30, 2023

This project looks awesome! I'm interested in a conventional handler approach either on top of this library or as an additional source generator. Something that decouples the handlers from the messaging library like this: https://wolverine.netlify.app/guide/handlers/ It would just discover handlers by convention and generate the concrete handler that implements your IRequestHandler and friends interfaces. Any interest in this?

@martinothamar
Copy link
Owner Author

So that would only affect handlers right? The requests/notifications would still use the appropriate interface?

Related: one thing I like a lot about Wolverine (and Marten) is that there is support for static functions as handlers. The typical case for request/notification handlers is that they are stateless, so it feels silly allocating an object simply to invoke a method. There are often injected services, but they can be injected as parameters to the function as well.. Seeing as this is a performance oriented library, that's something I would like to explore in the future. ASP.NET Core minimal APIs is kind of also going in that direction, having static functions as handlers, and we can now have static abstract methods in interfaces.. Might be something there.

So yes there is some interest there from my side for sure (taking inspiration from the Wolverine approach in general), but I'm not sure how it could be integrated into this library. I'll think some more about this while refactoring the source generator.

Btw, a challenge with source generators is that they don't compose at all, so I don't think this is solvable as an additional source generator (the Mediator source generator wouldn't have access to code generated by another source generator)

@ejsmith
Copy link

ejsmith commented Jul 1, 2023

Yes, this would only affect the handlers and not sending the messages.

Yeah, it really sucks that source generators can't simply be ordered by a priority with same priority using the same compilation model, but any subsequent ones would get an updated compilation model and be able to inspect code from previous priorities.

@ejsmith
Copy link

ejsmith commented Jul 7, 2023

Was just looking at dotnet/aspnetcore#48817 and thinking how doing something similar would make an amazing mediator implementation.

@martinothamar
Copy link
Owner Author

Yea it's on our radar for sure. @Tornhoof also brought it up here: #7 (comment)

Since they are bringing it into ASP.NET Core atm I'm assuming the interceptors proposal is basically approved for .NET 8/C# 12? 😄
I am very tempted to go all in on .NET 8 SDK requirement and using interceptors. I haven't been able to come up with a design for 3.0 that solves all the issues in the OP (while keeping the perf that is), but with interceptors everything becomes a lot simpler

@ejsmith
Copy link

ejsmith commented Jul 8, 2023

Yeah, interceptors was merged into main.

@TimothyMakkison
Copy link
Contributor

TimothyMakkison commented Jul 8, 2023

It might be better to wait for these changes, but will you be adding support for incremental pipeline caching? The output from CompilationAnalyzer could be turned into an Equatable friendly type.

I'd be willing to have a go at this.

@KennethHoff
Copy link

Since they are bringing it into ASP.NET Core atm I'm assuming the interceptors proposal is basically approved for .NET 8/C# 12? 😄

Most likely, but one thing I've realized about the dotnet codebases is that they'll update everything the moment it's available to be done. It's really quite interesting. They rewrote practically every instance they did null checks for parameters with the !! proposal a few years back before that was reverted. Same with ArgumentNullException.ThrowIfNull(param), and they've said they will with primary Constructors whenever that spec gets finalized.

So while it most likely will pass, I wouldn't go all-in just yet, especially since they've repeatedly said that it is a preview feature that likely will get changed or maybe even removed (although I highly doubt the latter due to just how important it is for the AoT story they're going all-in on)

@ejsmith
Copy link

ejsmith commented Jul 13, 2023

They are somewhat committed to it because of the AOT story and they are going to be using it a lot (already has multiple PRs accepted) to generate code that supports that. They would need to rewrite a lot of their code as well. Not to mention that this will be a pretty straight forward thing to replace if they come up with a different similar approach.

@TimothyMakkison
Copy link
Contributor

TimothyMakkison commented Sep 20, 2023

I am very tempted to go all in on .NET 8 SDK requirement and using interceptors.

#7 (comment)

It's already possible to create a pseudo-interceptor in all versions of .NET. By using the caller line number and caller file path, it is possible to differentiate each caller and respond appropiately.

public static void AddMediator(.... parameters go here, [CallerLineNumber] line = 0, [CallerFilePath] file = "")
{
    // an efficient condition can be built using the line number, file path length and varying chars in the file path
    // not sure how much the compiler will do
    return (line, path) switch
    {
        (0, _) => Mediator1.AddMediator(services),
        (42, { Length: 15 }) => Mediator2.AddMediator(services),
        (42, { Length: 21 }) => Mediator3.AddMediator(services),
        _ => throw new ArgumentOutOfRangeException()
    }
}

public static TResponse Send<TRequest, TResponse>(.... parameters go here, [CallerLineNumber] line = 0, [CallerFilePath] file = "")
{
    ...
}

Note that this may not work if the same method is called repeatedly on the same line. This is very unlikely to occur for Send or AddMediator; however, a check and diagnostic could be used to prevent this.

@dev-anton-ko
Copy link

Speaking about "Support generic messages".
Is this including support of generic Queries/Requests/Commands?

@martinothamar
Copy link
Owner Author

Yes, thats not possible currently, and requires rewriting the source generation of the IMediator implementation

@KANekT
Copy link

KANekT commented Nov 22, 2023

@martinothamar Project is frozen or is there a plan and date for the new version ?

@martinothamar
Copy link
Owner Author

Not fozen, but there is no date/deadline either. How much time I get on this depend on dayjob, personal life etc. Next steps for me is going over and merging the great stuff @TimothyMakkison has been doing, then see what version 3.0 actually becomes

@KANekT
Copy link

KANekT commented Nov 22, 2023

ok, Thanks. I'm currently using version 3 in my project. Therefore, I am interested in the further fate of the package.

@JohnGalt1717
Copy link

My personal request is for integrations with Redis/RabbitMQ/Kafka etc. to incrementally take this into doing distributed requests and requests/responses.

I'd love to have a library that does mediator first and then transparently goes up the chain to distributed requests automatically.

@KANekT
Copy link

KANekT commented Dec 22, 2023

My personal request is for integrations with Redis/RabbitMQ/Kafka etc. to incrementally take this into doing distributed requests and requests/responses.

I'd love to have a library that does mediator first and then transparently goes up the chain to distributed requests automatically.

I think you need to do this in your code yourself. If it is possible to make an example for this package in https://github.com/martinothamar/Mediator/tree/main/samples

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

No branches or pull requests

7 participants