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

New Feature - Advanced Request Aggregation #298

Closed
maartenmensink opened this issue Mar 30, 2018 · 7 comments
Closed

New Feature - Advanced Request Aggregation #298

maartenmensink opened this issue Mar 30, 2018 · 7 comments
Labels
feature A new feature help wanted Not actively being worked on. If you plan to contribute, please drop a note. large effort Likely over a week of development effort

Comments

@maartenmensink
Copy link

First of all thanks for the effort you guys put in the awesome project!

New Feature: Advanced Request Aggregation

A more advanced version of the Request Aggregation Feature to allow smarter composition of multiple request and or subsequent request.

Motivation for New Feautre

One of the problems developers face when developing applications that talks to microservices is that you will get a chatty client(lots of little request). By using a [api gateway(http://microservices.io/patterns/apigateway.html) we can work towards a optimized api for each client. To further support the effort for getting a optimized a api gateway should have a feature as API Composition which you guys made in to the awesome feature of Request Aggregation

Proposal

Currently there is support for creating a aggregate route by defining keys on routes and aggregating the keys into on route. It would be awesome if we could provide more intelligence to the processing of the route.

Perhaps a way of adding a config option to the aggregate route that will instantiate a instance of a IAggregateRouteComposer. Which would get the input params of the route

public interface IAggregateRouteComposer
{
    Task<object> Process(object input);
}

public class CustomAggregateRouteComposer : IAggregateRouteComposer
{
    public Task<object> Process(object input)
    {
        //compose response
     }
}
{
    "ReRoutes": [
        {
            "DownstreamPathTemplate": "/customer",
            "UpstreamPathTemplate": "/customer/{customerId}",
            "UpstreamHttpMethod": [
                "Get"
            ],
            "DownstreamScheme": "http",
            "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 51881
                }
            ],
            "Key": "Customer"
        },
        {
            "DownstreamPathTemplate": "/orders",
            "UpstreamPathTemplate": "/orders",
            "UpstreamHttpMethod": [
                "Get"
            ],
            "DownstreamScheme": "http",
            "DownstreamHostAndPorts": [
                {
                    "Host": "localhost",
                    "Port": 51882
                }
            ],
            "Key": "Orders"
        }
    ],
    "Aggregates": [
        {
            "Composer": "CustomAggregateRouteComposer",
            "UpstreamPathTemplate": "/product-detail/{productId}"
        }
    ]
}
@TomPallister TomPallister changed the title Advanced Request Aggregation New Feature - Advanced Request Aggregation Mar 30, 2018
@TomPallister TomPallister added feature A new feature help wanted Not actively being worked on. If you plan to contribute, please drop a note. medium effort Likely a few days of development effort labels Mar 30, 2018
@TomPallister
Copy link
Member

@maartenmensink thank you very much for your interest in the project.

I agree with you, we need a better / smarter way to do request aggregation.

I like your approach so let's leave this issue open and I will get to it at some point. If you would like to have a go yourself I am very happy to accept PRs and support / advise in the implementation.

Once again thank you very much! 😄

@TomPallister TomPallister added large effort Likely over a week of development effort and removed medium effort Likely a few days of development effort labels Mar 30, 2018
@TomPallister
Copy link
Member

I think I will make it so you have to configure the aggregates and reroutes but you will be able to provide the implementation that maps the reroutes into the reponse. Interface might be something like..

public Task<HttpResponseMessage> Map(List<HttpResponseMessage> originalResponses)
{
        //do stuff with original responses
       return new HttpResponseMessage() { Content = asdf };
}

This means you can even aggregate the headers you want returning etc...

@maartenmensink
Copy link
Author

maartenmensink commented Apr 9, 2018

I think if we have a way to configure all scenario's this would be a great way to quickly expand the gateway api. If we could support scenarios like the following scenario.

Customer is placing a order at webshop. Customer retrieves the basket and you want to return product suggestions for all the products in the current basket.

/basket

gives you the current basket

{
	"lines":[{
		"productId": 1
	},
	{
		"productId": 2
	}]
}

/suggestions?productId=1&productId2

gives you the suggestion for the your basket.

{
	"suggestions":[{
		"productId": 1
	},
	{
		"productId": 2
	}]
}

We would need a way of expressing output params and be able to provide them as input params

/basket => productIds = lines.Select(p => p.productId)
/suggestions <= productIds

@TomPallister
Copy link
Member

Ive started hacking around in #310 will try make this nicer...it would allow you to do the scenario above but is clunky...for me there is tradeoff between clunky + what a user needs to hand roll themselves vs cleaner, less hand roll, less functionality.

TomPallister pushed a commit that referenced this issue Apr 11, 2018
TomPallister added a commit that referenced this issue Apr 12, 2018
TomPallister added a commit that referenced this issue Apr 12, 2018
TomPallister added a commit that referenced this issue Apr 12, 2018
TomPallister added a commit that referenced this issue Apr 12, 2018
* #298 initial hacking around better aggregation

* #298 bit more hacking around

* #298 abstraction over httpresponsemessage

* #298 tidying up

* #298 docs

* #298 missed this
@TomPallister TomPallister reopened this Apr 12, 2018
TomPallister added a commit that referenced this issue Apr 12, 2018
* #298 initial hacking around better aggregation

* #298 bit more hacking around

* #298 abstraction over httpresponsemessage

* #298 tidying up

* #298 docs

* #298 missed this

* #306 example of how to do GraphQL
@TomPallister
Copy link
Member

TomPallister commented Apr 12, 2018

@maartenmensink I have thought about the feature you need and can't think of a better way to implement it that GraphQL.

To clarify in your scenario you want to retrieve the customers basket and use the products in the basket offer them suggestions.

Ocelot doesn't really have a concept of proper types, it just pushes http (strings) around really. In order for Ocelot to be able to get the basket, parse it, then get the suggestions would require a major change in Philosophy. I just want Ocelot to be a reverse proxy with a few extra features. GraphQL is doing a much better job than I could do for that :)

Anyway I recently added a sample to show how you can easily integrate GraphQL with Ocelot and this might help you out, it is here.

In addition to this Microsoft are looking into this problem in their eShopOnContainers project, the branch is here. The approach is to use Ocelot as an API gateway to handle cross cutting concerns but pass the request on to an aggregating service that would handle the basket / suggestions logic above.

I hope this makes sense and I would like to close the issue now! Please let me know if you have an idea and we can reopen.

@adamlepkowski
Copy link

@maartenmensink How did you solve your problem with basket and suggestions? I have similar issue right now.

@maartenmensink
Copy link
Author

maartenmensink commented Jul 8, 2019

@adamlepkowski At this moment we have dedicated WebApi Controllers that handle request that handle data composition. This way we can handle complex cases and later on create the right plumbing to handle it genericly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new feature help wanted Not actively being worked on. If you plan to contribute, please drop a note. large effort Likely over a week of development effort
Projects
None yet
Development

No branches or pull requests

3 participants