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 for request/response streaming? #85

Closed
yfinkelstein opened this issue Jan 13, 2016 · 16 comments
Closed

Support for request/response streaming? #85

yfinkelstein opened this issue Jan 13, 2016 · 16 comments
Assignees
Milestone

Comments

@yfinkelstein
Copy link

I may have misunderstood the scope of the framework. I see that HttpObjectAggregator is unconditionally inserted into the channel pipeline, and http service invocation handler delivers FullHttpRequest all the time. So, what about large requests with multipart encoding or simply chunked encoding that would benefit from stream processing?
Also, gRPC, for example, supports steaming requests and responses as a part of their IDL definition. This makes it possible to extend the basic "message in/message out" RPC with "message in/many messages out" etc model.
Is this completely out of scope for the Armeria, on you can see this being added some time soon?

@trustin
Copy link
Member

trustin commented Jan 14, 2016

You are correct. Armeria does not support streaming request/response at the moment, and we hope to change this before 1.0.

@trustin
Copy link
Member

trustin commented Apr 21, 2016

Thinking of using reactive streams API to implement this.

@yfinkelstein
Copy link
Author

Makes sense. Other options are Observable Api in both rxJava and grpc. And streaming should be 2 way

On Apr 21, 2016, at 02:45, Trustin Lee notifications@github.com wrote:

Thinking of using reactive streams API to implement this.


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub

@trustin
Copy link
Member

trustin commented Apr 22, 2016

@yfinkelstein You mean streaming both requests and responses, right?

@yfinkelstein
Copy link
Author

Yes. One request one response, one req N responses, N requests one response, and N requests N responses - all combinations should be supported.

On Apr 22, 2016, at 4:25 AM, Trustin Lee notifications@github.com wrote:

@yfinkelstein You mean streaming both requests and responses, right?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@trustin
Copy link
Member

trustin commented Apr 24, 2016

@yfinkelstein Could you explain the case of 1:N, N:1, N:M?

@yfinkelstein
Copy link
Author

Consider the use case of client interacting with a server that's fronting a portioned data storage cluster. The client sends a query "select ..".  The server forwards this request to N partitions and merges the results (for simplicity let's say the order does not matter). To avoid buffering the entire response from all partitions the server might prefer to send response to the client in chunks where a chunk can be the response from a single partition or a part of it. This gives is single request from client followed by N chunks (responses) from the server.
Reverse that and imagine that the client is uploading a large data set which it acquires from some source. The client might want to to divide the request in chunks and we get N requests followed by 1 response when the server is done.
NxM is a natural combination of both patterns.
gRPC really nailed this problem. Their API is really slick with Observable used both on the client and server.

On Saturday, April 23, 2016 5:53 PM, Trustin Lee <notifications@github.com> wrote:

@yfinkelstein Could you explain the case of 1:N, N:1, N:M?—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@trustin
Copy link
Member

trustin commented Apr 24, 2016

I see. Aren't they still one request - one response? It's just their contents that are being streamed.

@yfinkelstein
Copy link
Author

Yes, content is split into multiple parts that are sent and received independently

Sent from my iPhone

On Apr 23, 2016, at 21:17, Trustin Lee notifications@github.com wrote:

I see. Aren't they still one request - one response? It's just their contents that are being streamed.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@yfinkelstein
Copy link
Author

Finite streams

Sent from my iPhone

On Apr 23, 2016, at 21:21, Yuri Finkelstein yurif2003@yahoo.com wrote:

Yes, content is split into multiple parts that are sent and received independently

Sent from my iPhone

On Apr 23, 2016, at 21:17, Trustin Lee notifications@github.com wrote:

I see. Aren't they still one request - one response? It's just their contents that are being streamed.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@yfinkelstein
Copy link
Author

Streaming is not the only important feature here. Regular rpc messages can be streamed too if the transport supports it. The main feature here is that stream parts are delivered separately at the api level.

Sent from my iPhone

On Apr 23, 2016, at 21:34, Yuri Finkelstein yurif2003@yahoo.com wrote:

Finite streams

Sent from my iPhone

On Apr 23, 2016, at 21:21, Yuri Finkelstein yurif2003@yahoo.com wrote:

Yes, content is split into multiple parts that are sent and received independently

Sent from my iPhone

On Apr 23, 2016, at 21:17, Trustin Lee notifications@github.com wrote:

I see. Aren't they still one request - one response? It's just their contents that are being streamed.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@trustin
Copy link
Member

trustin commented May 21, 2016

Spent some time this week about this, and here's the idea so far:

@FunctionalInterface
public interface Service<I, O> {
    Publisher<O> apply(RequestPublisher<I> request) throws Exception;
}

public interface RequestPublisher<T> extends Publisher<T> {
    // getters for the information available from the beginning of the stream
    // e.g. initial headers, stream ID, remote/local address
}

public class MyHttp2Service<Http2Object, Http2Object> {
    public Publisher<Http2Object> apply(RequestPublisher<Http2Object> request) {
        Publisher<Http2Object> response = new MyPublisher<Http2Object>();
        request.subscribe(new MySubscriber(response);
        return response;
    }

    private class MySubscriber implements Subscriber<Http2Object> {
        private Subscription subscription;
        public void onSubscribe(Subscription subscription) {
            this.subscription = subscription;
            subscription.request(1);
        }
        public void onNext(Http2Object o) {
            ...
            subscription.request(1);
        }
        public void onComplete() {
            response.publish(someHttp2ResponseObject);
        }
    }
}

public class LoggingService<IN, OUT> extends Service<IN, OUT> {
    private Service delegate;
    public Publisher<OUT> apply(Publisher<IN> request) {
        // *Processor are both a publisher and a subscriber.
        request.subscribe(requestLoggingProcessor);
        Publisher<Object> response = delegate.apply(requestLoggingProcessor);
        response.subscribe(responseLoggingProcessor);
        return responseLoggingProcessor;
    }
}

As you see, ServiceCodec and ServiceInvocationHandler are gone. It is likely that ServiceInvocationContext will require some changes as well. It's a lot of changes, but it seems rational to me. WDYT?

I'm currently focusing on the server-side but the client-side could change similarly. For example, ClientCodec.encodeRequest() would produce a Publisher and decodeResponse() would require a Publisher.

@trustin trustin self-assigned this May 21, 2016
@yfinkelstein
Copy link
Author

I'd like to understand the overall approach first. In gRPC, "stream" is a keyword in their IDL (protobuf based). The author of the RPC interface signals the nature of the message as being being either a single part or a stream of parts. The generated code will then reflect this. Is this your intention as well (with thrift of course)?

The code snippet above looks quite readable and conveys the idea well. What is your approach to back pressure management? It's one of the key issues that always comes with with streaming. The best idea known to me today is that back pressure must be managed explicitly and cooperatively by both sides rather than just rely on TCP back pressure on each side.
Am I reading it right that .request(1) is the back pressure control mechanism and '1' is the number of parts subscriber is asking producer to produce?

@trustin
Copy link
Member

trustin commented May 24, 2016

Am I reading it right that .request(1) is the back pressure control mechanism and '1' is the number of parts subscriber is asking producer to produce?

Yes. Back pressure control considered. :-)

@anuraaga
Copy link
Collaborator

As you say, this is just a step to be able to read HTTP streams partially rather than all up front. That would be enough for a custom HttpService to do streaming if it has a use case, but more interesting will be at that point we can implement a wire protocol to frame arbitrary RPC messages (we'll probably implement the grpc wire protocol initially with other options to increase support to browsers, etc), and then generated code will need to be able to work with the wire protocol. Since thrift would require significant work in the IDL compiler itself, I guess it's more likely the first shining example of streaming in armeria will be protobuf-based.

trustin added a commit to trustin/armeria that referenced this issue Jun 28, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jun 29, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jun 30, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jun 30, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 4, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Add type parameters to Client and Service
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 5, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 5, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 6, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 6, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 7, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 8, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 8, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 11, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 15, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 19, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 19, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    awaitRequestLog() and awaitResponseLog() when all necessary information is
    ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Jul 19, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    requestLogFuture() and responseLogFuture() when all necessary information
    is ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Refactor LoggingClient/Service and MetricCollectingClient/Service
-----------------------------------------------------------------
- Rename MetricConsumer to MessageLogConsumer
- Move the classes in the 'metrics' package to the 'logging' package
- Add LogCollectingClient/Service
- LoggingClient/Service and MetricCollectingClient/Service extends
  LogCollectingClient/Service
- Rename MetricCollectingClient/Service to
  DropwizardMetricCollectingClient/Service because a user can use
  LogCollectingClient/Service to support his/her favorite metric
  collecting library

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
trustin added a commit to trustin/armeria that referenced this issue Aug 1, 2016
Related: line#85

This commit contains a lot of changes. I'll group them into several pairs of
motivations and modifications.

Use the Reactive Streams API to support HTTP content streaming
--------------------------------------------------------------
Motivation:

Reactive Streams API is the de-facto standard API for implementing object
streaming these days; RxJava, gRPC, Akka and Project Reactor are the notable
adoptors.

Modifications:

- Add RichPublisher and its subtypes to provide the foundation for streaming
  HTTP content
  - See the com.linecorp.armeria.common.reactivestreams package, most notably:
    - RichPublisher and Writer
    - QueueBasedPublisher

Decouple the core API from Netty API
------------------------------------
Motivation:

Armeria is meant to be used by an application developer. Exposing too much
detail to him or her is not the best idea.

Modifications:

- Hide all Netty HTTP types under Armeria's own HTTP/2-centric message types
  - HttpObject
  - HttpHeaders
  - HttpData
  - HttpMethod
  - HttpStatus
  - HttpStatusClass
  - HttpHeaderNames
- Introduce HttpRequest and HttpResponse whose content is a RichPublisher, our
  reactive streams API
- Add AggregatedHttpMessage which is the FullHttpMessage counterpart
- Add HttpRequest/ResponseWriter for easier composition of an HTTP message
- Do not expose ByteBuf in the user-facing API
- Use CompletableFuture instead of Netty Future/Promise
- Note that we still use Netty's AsciiString as header names because it's
  generic enough

Redefine Client, Service and their context API
----------------------------------------------
Motivation:

Previously, we shared one context type for both client and server side:
ServiceInvocationContext. This is potentially confusing and both client and
server sides had to shoehorn their models into the common model provided by
ServiceInvocationContext.

Also, ServiceInvocationContext assumed that a request is fully available when
context is created. However, this is not true anymore with content streaming.

Modifications:

- Replace ServiceInvocationContext with RequestContext
  - Add ClientRequestContext and ServiceRequestContext
  - All timeout settings, maximum allowed content length and custom HTTP header
    options are now overridable via the setters of the context.
- Only expose the information that could be available when a request has just
  started rather than when a full request is ready.
  - Add RequestLog and ResponseLog so that a client or a service fills the
    properties as they are available. A user will be notified via
    requestLogFuture() and responseLogFuture() when all necessary information
    is ready.
  - For example, RequestContext.method() property always returns the method at
    the session layer. That is, in a Thrift-over-HTTP call, ctx.method() will
    return "POST" rather than "someThriftMethod". It is because such information
    is available only when the full request has been received. You can get the
    Thrift method name from RequestLog once it's ready.
  - See LoggingClient/Server and MetricCollectingClient/Server for code example
- Remove ClientCodec, RemoteInvoker, ServiceCodec, ServiceInvocationHandler,
  because they are all merged into Client or Service

Overall reorganization of session layer implementation
------------------------------------------------------
Motivation:

Our code layout is too HTTP-centric and this will eventually make it hard to
add other session protocols.

Modifications:

- Move HTTP-specific code to com.linecorp.armeria.{server,client}.http
- Move the internal classes that could be shared between client and server to
  com.linecorp.armeria.internal.*

Implement HTTP content streaming at the session layer
-----------------------------------------------------
Modifications:

- Use Armeria's own HTTP/2 centric streaming-aware API instead of aggregating
  an HTTP/1 or 2 request into a full HTTP/1 request
  - See Http1/2RequestDecoder, HttpResponseSubscriber and HttpServerHandler to
    learn how this works on the server side
    - Start from Http1/2RequestDecoder to HttpServerHandler.handleRequest()
  - See Http1/2ResponseDecoder, HttpRequestSubscriber and HttpSessionHandler to
    learn how this works on the client side
    - Start from HttpSessionHandler.invoke()

Revamp HttpService, ThriftService and other services with the new core API
--------------------------------------------------------------------------
Motivation:

HttpService and ThriftService assumes a request is fully received when it is
invoked, which is not true anymore. Also, they are split into two components,
ServiceCodec and ServiceInvocationHandler, and they are gone now.

Modifications:

- HttpService is now an interface.
  - Add AbstractHttpService which replaces the old HttpService class
- ThriftService is now THttpService.
  - ThriftService is split into two parts: THttpService and ThriftCallService.
    - THttpService translates an HTTP request into a ThriftCall and
      a ThriftReply into an HTTP response. (similar to ServiceCodec)
    - ThriftCallService delegates a ThriftCall to a stub implementation.
      (similar to ServiceInvocationHandler)
  - Deprecate ThriftService
- Other service implementations underwent similar changes to work with the new
  API.

Revamp client-side service composition and decoration
-----------------------------------------------------
Motivation:

Previous client composition and decoration was based on the assumption that
the full request content is available upon its invocation, which isn't true
anymore.

Modifications:

- Replace the option 'DECORATOR' with 'DECORATION' whose value type is
  'ClientDecorations'
  - A user is now expected to specify the type of the request and response he
    or she desires to intercept, and the ClientFactory will apply the decorator
    at the right place in the invocation chain.
    - builder.add(ThriftCall.class, ThriftReply.class, thriftCallDecorator);
    - builder.add(HttpRequest.class, HttpResponse.class, httpDecorator);

Write new HTTP client API
-------------------------
Motivation:

SimpleHttpClient exposes Netty API and it's not powerful enough.

Modifications:

- Add HttpClient which replaces SimpleHttpClient
- Deprecate SimpleHttpClient

Merge ThriftFunction and ThriftMethod
-------------------------------------
Motivation:

They basically do the same job slightly differently.

Modifications:

- Merge them into one implementation and move to the internal package.
  - See com.linecorp.armeria.internal.thrift.{ThriftFunction,ThriftServiceMetadata}

Provide a way to add a decorator to all services
------------------------------------------------
Motivation:

Some decorators are often meant to be added to all services in a server or in a
VirtualHost.

Modifications:

- Add ServerBuilder.decorator() that adds a decorator to all services in a
  server
- Add VirtualHostBuilder.decorator() that adds a decorator too all services in
  a VirtualHost

Rename RemoteInvokerFactory to ClientFactory
--------------------------------------------
Motivation:

RemoteInvoker is now gone. ClientFactory sounds better in my opinion.

Modification:

- Rename/replace RemoteInvoker to/with ClientFactory
- Add HttpClientFactory and ThriftClientFactory
- Add AllInOneClientFactory that supports both HTTP and Thrift-over-HTTP via
  the two ClientFactories above
- Rename RemoveInvokerOption and its related classes to SessionOption

Refactor LoggingClient/Service and MetricCollectingClient/Service
-----------------------------------------------------------------
- Rename MetricConsumer to MessageLogConsumer
- Move the classes in the 'metrics' package to the 'logging' package
- Add LogCollectingClient/Service
- LoggingClient/Service and MetricCollectingClient/Service extends
  LogCollectingClient/Service
- Rename MetricCollectingClient/Service to
  DropwizardMetricCollectingClient/Service because a user can use
  LogCollectingClient/Service to support his/her favorite metric
  collecting library

Result
------
- HTTP content streaming works.
- Frequently used service implementations such as ThriftService, TomcatService,
  JettyService and HttpFileService works without modifying user code.
- Frequently used client implementations such as SimpleHttpClient and usual
  Thrift client stub generation works as before.
@trustin trustin added this to the 0.21.0.Final milestone Oct 19, 2016
@trustin
Copy link
Member

trustin commented Oct 19, 2016

This feature has been implemented long time ago (0.21.0)

@trustin trustin closed this as completed Oct 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants