Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revamp the core API to support HTTP content streaming
Related: #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.
- Loading branch information