vert-x3 / vertx-web

HTTP web applications for Vert.x
Apache License 2.0
1.11k stars 531 forks source link

Option to prevent route more than once in the same RoutingContext #2109

Open glassfox opened 2 years ago

glassfox commented 2 years ago

In case of reroute, routing flow occurred more than once. This behavior will affect on process time and add extra activity in handlers. As in handler alternative, @pmlopes propose to add the following:

router.route().handler(ctx -> {
  if (ctx.data().get("my-handler-visited", false)) {
    ctx.put("my-handler-visited", true);
    // the code here will execute once...
  }
  ctx.next();
});

In case of 3rd-party handlers this option more complex but available. I propose to add this logic as part of route. something like:

router.route().onceEachContext().handler(ctx -> {
  ...
  ctx.next();
});

and for dynamic condition something like:

router.route().handler(ctx -> {
  if(!ctx.isVisited()){
  ...
  }
  ctx.next();
});
pmlopes commented 2 years ago

Internally we already have the concept of:

https://github.com/vert-x3/vertx-web/blob/master/vertx-web/src/main/java/io/vertx/ext/web/impl/RoutingContextInternal.java#L30-L46

It could be possible to promote this internal API to be public and define the rules for the id. To keep the current implementation fast, it assumes that there is a long value in the context and the ids are just bit positions, so we can use up to 64 unique ids with low memory impact and fast lookups.

If we reserve the first 4? for vertx specific handlers and let the remaining 60 for user, we could have this feature available with almost no impact in terms of performance.

We could have a simple sugar to the API to look like this:

router.route()
  .handler(
    once(USER_HANDLER_1, ctx -> {
      ... 
}));

Where once can be defined as:

public static Handler<RoutingContext> once(int userHandlerId, Handler<RoutingContext> handler) {
  return ctx -> {
    RoutingContextInternal ctx0 = (RoutingContextInternal) ctx;
    if (!ctx0.seenHandler(userHandlerId)) {
      ctx0.visitHandler(userHandlerId);
      handler.handle(ctx);
    } else {
      ctx.next();
    }
  };
});
glassfox commented 2 years ago

How I able to help to engage the develop process ?