-
Notifications
You must be signed in to change notification settings - Fork 6
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
grpc over http/2 poc #26
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,38 @@ | ||
package com.flipkart.varadhi; | ||
|
||
import com.flipkart.varadhi.exceptions.InvalidStateException; | ||
import com.flipkart.varadhi.web.Extensions; | ||
import com.flipkart.varadhi.web.FailureHandler; | ||
import com.flipkart.varadhi.web.routes.RouteBehaviour; | ||
import com.flipkart.varadhi.web.routes.RouteBehaviourProvider; | ||
import com.flipkart.varadhi.web.routes.RouteConfigurator; | ||
import com.flipkart.varadhi.web.routes.RouteDefinition; | ||
import com.flipkart.varadhi.web.v1.proto.MessageProducerGrpc; | ||
import com.flipkart.varadhi.web.v1.proto.SingleMessageResponse; | ||
import io.vertx.core.AbstractVerticle; | ||
import io.vertx.core.Promise; | ||
import io.vertx.core.http.HttpMethod; | ||
import io.vertx.core.http.HttpServer; | ||
import io.vertx.core.http.HttpServerOptions; | ||
import io.vertx.core.http.HttpVersion; | ||
import io.vertx.ext.web.Route; | ||
import io.vertx.ext.web.Router; | ||
import io.vertx.grpc.common.GrpcStatus; | ||
import io.vertx.grpc.server.GrpcServer; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
@Slf4j | ||
public class RestVerticle extends AbstractVerticle { | ||
private final List<RouteDefinition> apiRoutes; | ||
private final Map<RouteBehaviour, RouteBehaviourProvider> behaviorProviders; | ||
private final Map<RouteBehaviour, RouteConfigurator> behaviorProviders; | ||
|
||
private HttpServer httpServer; | ||
|
||
public RestVerticle( | ||
List<RouteDefinition> apiRoutes, Map<RouteBehaviour, RouteBehaviourProvider> behaviorProviders | ||
List<RouteDefinition> apiRoutes, Map<RouteBehaviour, RouteConfigurator> behaviorProviders | ||
) { | ||
this.apiRoutes = apiRoutes; | ||
this.behaviorProviders = behaviorProviders; | ||
|
@@ -36,11 +44,32 @@ public void start(Promise<Void> startPromise) { | |
log.info("HttpServer Starting."); | ||
Router router = Router.router(vertx); | ||
|
||
// grpc | ||
GrpcServer grpcServer = GrpcServer.server(vertx); | ||
|
||
grpcServer.callHandler(MessageProducerGrpc.getProduceMethod(), request -> { | ||
request.response().status(GrpcStatus.OK).statusMessage("OK") | ||
.end(SingleMessageResponse.newBuilder().setOffset("0001").build()); | ||
}); | ||
|
||
router.route() | ||
.consumes("application/grpc") | ||
.produces("application/grpc") | ||
.handler(req -> grpcServer.handle(req.request())); | ||
|
||
router.route() | ||
.consumes("application/json") | ||
.produces("application/json") | ||
.path("/topics/produce") | ||
.method(HttpMethod.POST) | ||
.handler(rc -> Extensions.RoutingContextExtension.endRequestWithResponse(rc, 200, "0001")); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Planning to keep it or move it appropriately to ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ya. its a TODO, will fix it in this PR. |
||
// http | ||
FailureHandler failureHandler = new FailureHandler(); | ||
for (RouteDefinition def : apiRoutes) { | ||
Route route = router.route().method(def.method()).path(def.path()); | ||
def.behaviours().forEach(behaviour -> { | ||
RouteBehaviourProvider behaviorProvider = behaviorProviders.getOrDefault(behaviour, null); | ||
RouteConfigurator behaviorProvider = behaviorProviders.getOrDefault(behaviour, null); | ||
if (null != behaviorProvider) { | ||
behaviorProvider.configure(route, def); | ||
} else { | ||
|
@@ -58,6 +87,8 @@ public void start(Promise<Void> startPromise) { | |
HttpServerOptions options = new HttpServerOptions(); | ||
// TODO: why? | ||
options.setDecompressionSupported(false); | ||
options.setAlpnVersions(Arrays.asList(HttpVersion.HTTP_2, HttpVersion.HTTP_1_1)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DEFAULT_ALPN_VERSIONS constant ? |
||
options.setUseAlpn(true); | ||
|
||
// TODO: create config for http server | ||
httpServer = vertx.createHttpServer(options).requestHandler(router).listen(8080, h -> { | ||
|
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.flipkart.varadhi.web; | ||
|
||
import com.flipkart.varadhi.utils.JsonMapper; | ||
import io.netty.handler.codec.http.HttpHeaderValues; | ||
import io.vertx.core.http.HttpHeaders; | ||
import io.vertx.core.http.HttpServerRequest; | ||
import io.vertx.ext.web.RequestBody; | ||
import io.vertx.ext.web.RoutingContext; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
public class Extensions { | ||
|
||
public static class RequestBodyExtension { | ||
|
||
/* | ||
Extension method for vertx RequestBody. | ||
builtin asPojo() method is not working because of jackson issues i.e. | ||
it needs default constructor and none final fields. | ||
|
||
Extending RequestBody to have asPojo() custom deserializer to convert requestBody to appropriate Pojo. | ||
*/ | ||
public static <T> T asPojo(RequestBody body, Class<T> clazz) { | ||
return JsonMapper.jsonDeserialize(body.asString(), clazz); | ||
} | ||
} | ||
|
||
@Slf4j | ||
public static class RoutingContextExtension { | ||
public static <T> void endRequestWithResponse(RoutingContext ctx, T response) { | ||
String responseBody = JsonMapper.jsonSerialize(response); | ||
ctx.response().putHeader(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON); | ||
ctx.response().putHeader(HttpHeaders.CONTENT_ENCODING, "utf-8"); | ||
ctx.response().end(responseBody, (r) -> { | ||
HttpServerRequest request = ctx.request(); | ||
if (r.succeeded()) { | ||
log.debug("Request {}:{} completed successfully.", request.method(), request.path()); | ||
} else { | ||
log.error("Request {}:{} Failed to send response: {}", request.method(), request.path(), r.cause()); | ||
} | ||
}); | ||
} | ||
|
||
public static <T> void endRequestWithResponse(RoutingContext ctx, int status, T response) { | ||
ctx.response().setStatusCode(status); | ||
endRequestWithResponse(ctx, response); | ||
} | ||
|
||
public static void todo(RoutingContext context) { | ||
context.response().setStatusCode(500).setStatusMessage("Not Implemented").end(); | ||
} | ||
} | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any thoughts for removing logging ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logging error and then throwing the same leads to redundant logs.
For eg:
Before
After
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I try to follow the rule for error logs which says:
Don't log if you are throwing. can log if you are handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally I tend to follow log at source of the event to capture all data along that leads to exception.
But I guess, we can avoid exception logging from that and keep only data part and leave exception logging to either default exception handler at base or log where it is being handled ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can still capture what we want to capture in the "exception" that we are throwing.