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

Support Nested Pipelines #7

Open
ivanpaulovich opened this issue Oct 8, 2019 · 3 comments
Open

Support Nested Pipelines #7

ivanpaulovich opened this issue Oct 8, 2019 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@ivanpaulovich
Copy link
Owner

ivanpaulovich commented Oct 8, 2019

It would be cool if the "Return" operator could start a second pipeline using the "Response" as the Request for the following pipeline.

@ivanpaulovich ivanpaulovich added good first issue Good for newcomers enhancement New feature or request labels Oct 8, 2019
@ivanpaulovich ivanpaulovich changed the title Add Nested Pipelines Support Nested Pipelines Oct 12, 2019
@ivanpaulovich ivanpaulovich removed the good first issue Good for newcomers label Oct 20, 2019
@qpippop
Copy link

qpippop commented Dec 11, 2019

I'm trying to implement this. Here's some code how it may work

services.AddFluentMediator(m =>
{
    m.On<PingRequest>().PipelineAsync()
        .Return<PingResponse, IPingHandler>(
            (handler, req) => handler.MyCustomFooBarAsync(req))
        .WithContinuation<PingResponse>() // returns IPipelineAsyncBuilder<PingResponse>
            .Return<SecondPingResponse, ISecondPingHandler>(
                (ISecondPingHandler handler, PingResponse req) => handler.MySecondFooBarAsync(req));
});
// ... some code ...
var response = await mediator.SendAsync<SecondPingResponse>(ping); // We specify the last type from pipe chain

In Pipeline.cs

// ... some code ...
private readonly IPipelineAsync? _nestedPipe;
// ... some code ...
public Pipeline(IMethodCollection<Method<Func<object, object, Task>>> methods, IDirect? direct, Type requestType, string? name, IPipelineAsync? nestedPipe)
{
    _methods = methods;
    _direct = direct;
    RequestType = requestType;
    Name = name;
    _nestedPipe = nestedPipe;
}

public async Task<TResult> SendAsync<TResult>(GetService getService, object request)
{
    if (_direct is null)
    {
        throw new ReturnFunctionIsNullException("The return function is null. SendAsync<TResult> method not executed.");
    }

    foreach (var handler in _methods.GetMethods())
    {
        var concreteHandler = getService(handler.HandlerType);
        await handler.Action(concreteHandler, request);
    }
    // NOTE: should we return object to avoid InvalidCastException?
    // NOTE: because TResult in our case - result type of the nested pipe
    var result = await _direct.SendAsync<TResult /* replace with non generic SendAsync */>(getService, request!) !;
    if (_nestedPipe is IPipelineAsync)
    {
        return await _nestedPipe.SendAsync<TResult>(getService, result!);
    }

    return result;
}

Am i on the right direction? Should i continue to work on it, not sure i'm competent enough..

@ivanpaulovich
Copy link
Owner Author

Hey @qpippop!

You were narrow on what I'd like to see. To avoid the invalid cast, what if:

if (_nestedPipe is IPipelineAsync)
{
    var result = await _direct.SendAsync<object>(getService, request!) !;
    return await _nestedPipe.SendAsync<TResult>(getService, result!);
}
else
{
    return await _nestedPipe.SendAsync<TResult>(getService, result!);
}

Would that work?

@ivanpaulovich
Copy link
Owner Author

I am looking forward the PR. Hope we could merge it soon ☕️

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

No branches or pull requests

2 participants