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

[UNDERTOW-2303] Introduced a new, faster utility for routing path templates #1566

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

dirkroets
Copy link

@dirkroets dirkroets commented Mar 8, 2024

Objective

Improve the performance of routing path templates to target handlers.

I started working on this code after I had seen this comment by Stuart Douglas on io.undertow.util.PathTemplateMatcher:

TODO: we can probably do this faster using a trie type structure, but I think the current impl should perform ok most of the time

The new path template router does incorporate a tree, but also numerous other performance enhancements. There are rudimentary performance benchmarks in io.undertow.util.PathTemplateRouterTest. The @Test annotation must be uncommented for public void comparePerformance() in order to run the comparison - in which case the results will be written to /tmp/path-template-router-performance.txt in CSV format. The attached chart
is based on numerous runs of comparePerformance and even though the benchmarks are admittedly rudimentary, it does show a very significant improvement in performance. The new utility routes approximately 3x more requests in the same amount of time as the previous utility, therefore a 200% increase in performance. Complexity should be O(log n) for number of path templates added to the router:

performance-chart

Jira

UNDERTOW-2303

Tests

  1. io.undertow.util.PathTemplateRouterTest contains tests to verify that requests are routed correctly based on different combinations of path templates, including wildcards. Some of these tests were specifically written during the development of io.undertow.util.PathTemplateRouter, but many of the assertions have been copied from io.undertow.util.PathTemplateTestCase to verify consistency against the previous implementation.
  2. io.undertow.server.handlers.PathTemplateHandlerTestCase was left untouched and verifies that io.undertow.server.handlers.PathTemplateHandler (which now uses the new router under the hood) routes requests in a way that is consistent with the previous implementation.
  3. io.undertow.server.handlers.RoutingHandlerTestCase was left untouched and verifies that io.undertow.server.RoutingHandler (which now uses the new router under the hood) routes requests in a way that is consistent with the previous implementation.

…plates. Updated existing path template based routing handlers to use the new utility.
@fl4via fl4via added the enhancement Enhances existing behaviour or code label Mar 13, 2024
@baranowb baranowb added under verification Currently being verified (running tests, reviewing) before posting a review to contributor failed CI Introduced new regession(s) during CI check waiting peer review PRs that edit core classes might require an extra review labels Mar 14, 2024
@baranowb
Copy link
Contributor

@dirkroets its failing with:
Error: Medium: Dead store to pathTemplate in io.undertow.server.handlers.PathTemplateRouterHandler.handleRequest(HttpServerExchange) [io.undertow.server.handlers.PathTemplateRouterHandler] At PathTemplateRouterHandler.java:[line 62] DLS_DEAD_LOCAL_STORE
Error: Medium: Unread field: io.undertow.util.PathTemplateRouter$RouterFactory.currentSegment [io.undertow.util.PathTemplateRouter$RouterFactory] At PathTemplateRouter.java:[line 1439] URF_UNREAD_FIELD
Error: High: Non-virtual method call in io.undertow.util.PathTemplateRouter$SimpleBuilder.newBuilder() passes null for non-null parameter of newBuilder(Object) [io.undertow.util.PathTemplateRouter$SimpleBuilder] At PathTemplateRouter.java:[line 2087] NP_NULL_PARAM_DEREF_NONVIRTUAL

This means that spotbugs has a problem with it. Enable it locally with "-Dfindbugs".

Copy link
Contributor

@baranowb baranowb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look at rest of the code once I get some free time.

Objects.requireNonNull(uriTemplate);
Objects.requireNonNull(handler);

// Router builders are not thread-safe, so we need to synchronize.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a quick glance:
1.Why would the need to be?
2. in which cases this would be needed?
3. Im not sure if such design of builder is optimal. AFAIR in other builders are context one-offs
4. AFAIR, in general, if there is no need to sync, we dont do it, rather rely on local var/single failure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The short answer is for backwards compatibility. The original PathTemplateHandler class (also PathTemplateRouter) provided synchronised mutation of the underlying routes.

The longer answer:

  1. The underlying router itself is immutable and therefore thread-safe. The builder that creates the router is not thread-safe as it is intended to be used from a single thread to instantiate a router. For most use cases that I can think of the routes (path templates) should be discovered/added during start-up of a service. Once discovered, a router can be built and then used to serve many many requests. Therefore, I believe that in most services instantiating a router is a once-off process / invocation vs probably millions of invocations of the route method. For this reason I believe that overall performance is served well by a slightly more expensive (computationally) instantiation process vs a very cheap routing process. Yet, this does not mean that calling the builder must be synchronised.... in my opinion most use cases must instantiate a router and pass it to an immutable handler such as the new PathTemplateRouterHandler class - which I provided as an example. We can add/offer builders for handlers - for convenience sake - that do the same thing as PathTemplateHandler and PathTemplateRouter, but that create immutable instances of those handlers instead of the current implementations that support mutating the underlying routers. This would however be a breaking change for developers who use and mutate the current implementations, so my recommendation would be to leave the current implementations as they are - for backwards compatibility - to deprecate them and to offer the new pattern as new, immutable handler classes that developers can switch to.
  2. I believe there are very very few use cases that require synchronised mutation of the routing handlers. For those use cases, developers should implement their own synchronised mutation of underlying handlers. As I have mentioned before, I just implemented the synchronised mutation to be consistent with the previous implementations in order to avoid introducing breaking changes.
  3. I agree that this is not optimal, but I am not sure if we are prepared to introduce this as a breaking change?
  4. Agreed. In this case there should be no need to sync for 99%+ of use cases.

As a last note - in case it is not that obvious from the code and in case we want to keep the backwards compatibility - the synchronisation only happens when the underlying routers are modified, so when new path templates are added. It only synchronises the mutations amongst multiple threads trying to mutate the routes concurrently. The actual routing of requests are never synchronised - not even when other threads are busy mutating the routers. For this reason I believe that it is okay to leave the synchronisation in order to maintain backwards compatibility. And then perhaps to deprecate and offer alternative classes in a next PR?

if (paths.size() == 1) {
return "path-template( " + paths.toArray()[0] + " )";
final List<PathTemplateRouter.PatternEqualsAdapter<PathTemplateRouter.Template<Supplier<HttpHandler>>>> templates;
synchronized (lock) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toString impeding normal operation is not ideal.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I have updated this. I believe that this toString method is probably only used for debugging purposes due to the size of the string produced (Consistent with the original implementation). This may now produce results that aren't entirely consistent when called concurrently with routes being mutated, but that is also consistent with how the original implementation worked.

@@ -0,0 +1,72 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, 2014, looks like we are traveling back in time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I just copied and pasted the header from another class and missed the instruction to update the dates. Will keep this in mind in future. Will be fixed when I update the PR

* A handler that matches URI templates.
*
* @author Dirk Roets [email protected]
* @since 2023-07-20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we are supposed to be so pedantic to require bump on this as well. @fl4via will know.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dirkroets @baranowb because it will be merged in 2024, I think we should either bump it or just omit it, keeping in mind that we are going to have 2024 in the copyright header above.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fl4via @baranowb , I will remove it from the new classes. The since tags are only there because my IDE adds it for some other projects that I'm working on.

@fl4via
Copy link
Member

fl4via commented Mar 15, 2024

@dirkroets Just FYI, to fully verify CI in your machine run:
mvn clean package -Pproxy -Dmaven.test.failure.ignore=true -DfailIfNoTests=false -fae > output.txt
You will notice that it is running the spotbugs plugin, and you will also be able to see any errors that can arise in the different test modes.

@fl4via fl4via added the waiting PR update Awaiting PR update(s) from contributor before merging label Mar 15, 2024
@fl4via
Copy link
Member

fl4via commented Mar 15, 2024

@dirkroets Just FYI, to fully verify CI in your machine run: mvn clean package -Pproxy -Dmaven.test.failure.ignore=true -DfailIfNoTests=false -fae > output.txt You will notice that it is running the spotbugs plugin, and you will also be able to see any errors that can arise in modes.

I stand corrected, to really fully verify CI in your machine you will also need to run the tests with IPv6 option, however, you need to do this only if your fix editted something related to ipv6, which usually is not the case:
mvn clean package -Pproxy -Dmaven.test.failure.ignore=true -DfailIfNoTests=false -fae -Dtest.ipv6=true > outputIpv6.txt

…eaders to 2024. Removed synchronisation for toString(). Fixed Spotbugs issues.
@dirkroets
Copy link
Author

@fl4via @baranowb I have added a second commit to this PR that fixes the CI issues and with some documentation improvements. According to the documentation one can edit the previous commit - provided that the previous commit was not a big commit. I am not sure what qualifies as a big commit, so I played it safe and added a second commit.

@baranowb baranowb removed the failed CI Introduced new regession(s) during CI check label Apr 3, 2024
@baranowb
Copy link
Contributor

baranowb commented Apr 3, 2024

@dirkroets Cool. I will try to reserve some time to crunch through this change.

@dirkroets
Copy link
Author

Thanks, @baranowb . Let me know if you have any questions or if there is anything I can assist with.

@baranowb
Copy link
Contributor

I slowly make progress with this. I will most likely have bigger window to go through bulk of it in ~2weeks.
@dirkroets ^^

@baranowb
Copy link
Contributor

baranowb commented May 7, 2024

Hey. Sorry for delay, I wasnt able to login last week. Anyway. Pretty neat design. Im going to add general comment here and some inline with review. I did not copy/paste comments when it either was done above or is part of general review.
So:

  1. code formatting and xml editor stuff --- https://github.com/wildfly/wildfly-core/tree/main/ide-configs/eclipse
  2. router.apply - is there a hidden meaning behind method name? why not "match" ? (or just backward compat/sentiment). Im fairly sure XML meta-description should be purged?

Maintaintability: 
2. TODO: jdoc and some rudimentary description - example what is template in RoutingHandler.add ? Especially given warning  at start of PathTemplateRouter

2a)  Example values, concepts need to be explained, ie for PathTemplateRouter.Template + usage/expected results

  1. add description to map/stream ops - usually those are "well known" during design, but later on it becaomse hasle to maintain without hint - example  createAllMethodsRouter

  2. To add to above difference parametrization and difference between invocation of parseTemplate in getOrAddMethodRoutingMatchBuilder and createAddTemplateIfAbsentConsumer - seems like Supplier is just used as non null ref when actual path/routing has been not defined.

  3. typos :) "Leave" -> "Leaf" ?

  4. generally by the time "Leave" typo comes into play, hefty man page would be a good idea.7. PathTemplateRouter should possibly be split into package level classes if its supposed to be hermetic? 

@baranowb baranowb self-requested a review May 7, 2024 05:42
* was specifically to provide something that is very fast even at the expense of maintainable code. The router
* does a very simple thing and there should arguably be no need to constantly work on this code.
*/
public class PathTemplateRouter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusing declaration, there is inteface called Router, yet, PathTemplateRouter does not implement it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I have made several structural changes in the next update along with improvements to documentation.

//<editor-fold defaultstate="collapsed" desc="PatternElement inner class">
/**
* Interface for elements that represent a URL path pattern. The objective of this interface is to provide
* a contract for comparing path patterns. For example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this contract defined?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that this is confusing. I believe it is described better in the update.

*
* @param <T> Type of pattern elements.
*/
public static final class PatternEqualsAdapter<T extends PatternElement> implements
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a need for parametrization?
Also, AFAIR, is used in most of classes here, classes that parameters ( I think) dont relate, this is tad confusing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are essentially two categories of "patterns".

  • The one category is the template itself - that consists of segments.
  • The second category is the different types of segments.

The top level builder/factory methods always expect the adapter to contain templates, but there is code in the RouterFactory inner class that builds the matcher trees that expects to only work with types of segments - extensions of AbstractTemplateSegment. One can remove the parameter, but would then have to add a few more "instance of" checks or depend on future developers knowing which types of patterns are supported in which areas of the code. Parametrization seems like the best of the three options?

*
* Extensions of this class must be immutable.
*/
private abstract static class TemplateSegment implements PatternElement {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. examples, relations.
  2. TemplateSegment vs PatternElement - most likely some explanation would suffice? naming scheme just does not fall into place?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I have made several naming changes and added more descriptions in the next update for this PR.

/**
* Index for the segment inside of the template.
*/
protected final int segmentIdx;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is it? why must be greater than 0 ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added comments in the code for the next update to the PR. It is an index into the array that contains the segments of a requested URL path, so it must be 0 or more.


/**
* A simple router that routes paths containing static segments or parameters. Specifically this router has
* an optimisation - based on the segment counts of requests - that do not support wild cards.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to explain said optimization?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional comments added in the update to the PR


@Override
public String toString() {
return "SimpleRouter{" + '}';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an IDE generated toString that I use(d) for debugging. I removed the concatenation :D

*
* @param <T> Target type.
*/
private static class MatcherLeaveArterfacts<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 'Leaf' ?
  2. explanation/visualization? This, as few other defs are key innerowking classes, it has to be described in way that will allow maintenance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Would like to say it was a typo, but just my English that let me down :D
  2. Added more comments in the next update.

private Matcher[] matchers;
private Matcher[] wildCardMatchers;

private RouterFactory(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here and most likely any other code below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added more comments in the next update.

*
* @return Reference to the builder.
*/
public Builder<S, T> removeTemplate(final String pathTemplate) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not ideal to parse again. Possibly add method to remove by reference?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add a map for the path template string -> adapter instance, then look up the key and remove it directly from the "templates" map by reference. However, there are two things to consider:

  1. This is part of the "setup phase" of the routers that typically happens only once when a service starts up. So the overhead of parsing again has a very small impact on the overall performance. I have personally never seen someone add a path template and then remove it again. I have added this method to support the "remove" method that already existed in PathTemplateHandler - so basically for backwards compatibility. In all of our projects we create new routers using new builders if we do want to mutate the routes, so I suspect that this will almost never be used and for that reason the overhead is probably okay if you consider the next point.
  2. Consider the following two template strings /books/{bookId}/chapters and /books/{id}/chapters These two strings are not equal, but the patterns represented by the templates are equal. Since one can't have "duplicate" patterns in a router, I would argue that the intention of removing the template is to remove the pattern associated with it so that you can potentially replace it with another template that uses a different parameter name - for example. So if we were to implement that map to remove by reference and we can't find the exact string in the map, then we would have to parse the string again anyway in order to be sure that it has been removed.

@dirkroets
Copy link
Author

Hi @baranowb

A general question from my side... what would be the best way to respond to requests for clarification? I.e.

  1. Clarify by submitting responses to comments here in the PR; or
  2. Clarify by adding additional comments in the code and updating the PR; or
  3. Clarify by creating and updating a separate man page. If this is the preferred option, then I would appreciate some advice on the best format and where to put it.
  4. Combination of the above

Thanks for all your effort with this PR!

@dirkroets
Copy link
Author

Just a note. I have started work to rename some classes, use more package level classes and to have a lot more documentation in JDOC and as comments. Will probably push more commits by the weekend

@baranowb
Copy link
Contributor

Cool. Generally at least good explanation in code should be enough. This code should be maintained by community members, so they have to be able to navigate/understand it relatively easy. As to other type of documentation, I will have to ask devs.

@dirkroets
Copy link
Author

Just a quick update. I'm still busy restructuring the classes and updating the documentation. I'm moving as much of the documentation as possible into JavaDoc. I'm quite busy during the week at the moment, but will try to finish these changes this coming weekend then.

@dirkroets
Copy link
Author

I'm pushing a few commits now that contains a lot of structural (+naming) improvements and improvements to documentation - i.e. JavaDoc and comments. I have also replied to the existing comments on the PR, but I'm not sure how useful those will be once the structural changes have been pushed. Therefore I believe that it is necessary to provide a summary of the changes here as well:

  1. Reformatted code using https://github.com/wildfly/wildfly-core/tree/main/ide-configs:
    1. io.undertow.server.RoutingHandler
    2. io.undertow.server.handlers.PathTemplateHandler
    3. io.undertow.server.handlers.PathTemplateRouterHandler
    4. io.undertow.util.PathTemplateParser
    5. io.undertow.util.PathTemplateRouteResult
    6. io.undertow.util.PathTemplateRouter
    7. io.undertow.util.PathTemplateRouterFactory
    8. io.undertow.util.PathTemplateUtil
    9. io.undertow.util.PathTemplateRouterTest
  2. Restructured classes according to specific concerns - for clarity - and to reduce the amount of code in any one class:
    1. io.undertow.util.PathTemplateParser: Concerned with parsing formatted strings into URL path templates. Contains inner classes for the the model of URL path templates. Since neither the parser nor the router factory supports exentsions of these classes, the classes are implemented as inner classes with private constructors to be hermetic.
    2. io.undertow.util.PathTemplateRouterResult: Closely related to PathTemplateRouter and contains documentation (JavaDoc) that describes the use of the target type parameter. This is the result object for requests to route URL paths.
    3. io.undertow.util.PathTemplateRouter: Concerned with routing requested URL paths to underlying URL path templates. This is the main interface for URL path template routers and contain a fair bit of documentation regarding the routing methodology, phases of processing etc.
    4. io.undertow.util.PathTemplateRouterFactory: Concerned with the creation of routers from URL path templates. Contains inner classes that are meant to be hermetic as several of these classes contain optimisations that depend on guarantees made by other inner classes.
    5. io.undertow.util.PathTemplateUtil: Contains utility methods that are used by more than one of the other top-level classes.
  3. Renamed classes for clarity and consistency:
    1. PathTemplateRouter.RouteResult -> PathTemplaterRouteResult
    2. PathTemplateRouter -> PathTemplateRouterFactory
    3. PathTemplateRouter.Router -> PathTemplateRouter
    4. PathTemplateRouterFactory.PatternElement -> PathTemplateParser.PathTemplatePattern
    5. PathTemplateRouterFactory.TemplateSegment -> PathTemplateParser.AbstractTemplateSegment
    6. PathTemplateRouterFactory.TemplateStaticSegment -> PathTemplateParser.StaticTemplateSegment
    7. PathTemplateRouterFactory.TemplateParamSegment -> PathTemplateParser.ParamTemplateSegment
    8. PathTemplateRouterFactory.TemplateWildCardSegment -> PathTemplateParser.WildCardTemplateSegment
    9. PathTemplateRouterFactory.MatcherLeaveArterfacts -> PathTemplateRouterFactory.MatcherLeafArterfacts
    10. PathTemplateRouterFactory.CompositeMatcher -> PathTemplateRouterFactory.SimpleCompositeMatcher
    11. PathTemplateRouterFactory.BinarySearchRouterMatcher -> PathTemplateRouterFactory.BinarySearchCompositeMatcher
    12. PathTemplateRouterFactory.CreateSimpleResultMatcher -> PathTemplateRouterFactory.SimpleTerminalMatcher
    13. PathTemplateRouterFactory.CreateResultWithParamsMatcher -> PathTemplateRouterFactory.ParameterisedTerminalMatcher
    14. PathTemplateRouterFactory.CreateSimpleWildCardResultMatcher -> PathTemplateRouterFactory.SimpleWildcardTerminalMatcher
    15. PathTemplateRouterFactory.CreateWildCardWithParamsResultMatcher -> PathTemplateRouterFactory.ParameterisedWildcardTerminalMatcher
  4. Removed java.util.function.Function as a super class of:
    1. PathTemplateRouter and renamed the previously inherited ‘apply’ method to ‘route’.
    2. PathTemplateRouterFactory.Matcher and renamed the previously inherited ‘apply’ method to ‘match’.
  5. Removed Comparable as an implemented interface from PathTemplatePatternEqualsAdapter. The ordering of segments for matching/routing is considered to be internal to the router instances created by the router factory and is therefore now encapsulated in PathTemplateRouterFactory.
  6. Improved documentation:
    1. Added additional detail, including example, as JavaDoc on interfaces, classes and methods. The JavaDoc is best viewed inside of a browser.
    2. Added comment sections for design decisions and implementation notes in PathTemplateParser and PathTemplateRouter
    3. Added comments to all streams operations.
    4. Added additional JavaDoc and comments to io.undertow.server.RoutingHandler to clarify how the underlying router instances are created. I.e. createAddTemplateIfAbsentConsumer and getOrAddMethodRoutingMatchBuilder.
  7. Added PathTemplateRouterFactory.AbstractRouter with additional abstract methods to slightly optimise the performance of PathTemplateRouterFactory.CompositeRouter.

@baranowb baranowb requested review from fl4via and baranowb July 11, 2024 08:51
@baranowb
Copy link
Contributor

baranowb commented Jul 11, 2024

Im slowly looking at it again. Generally good work with explaining stuff, some minor cracks so far.
@dirkroets ^^

@dirkroets
Copy link
Author

Thanks, @baranowb . Let me know if there is anything I can update so long.

@baranowb
Copy link
Contributor

baranowb commented Sep 4, 2024

@dirkroets hey, so far I did not find anything bad, aside things Ive mentioned. Im still waiting for second review as well.
Though it looks like github somehow glitched my recent review. Im going to try to figure it out.

public interface PathTemplateRouter<T> {

/**
* @return The default target for requests that do no match any specific routes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*not?

* underlying URL path templates, then result will contain {@link #getDefaultTarget() } as the target and will contain an
* empty Optional in {@link PathTemplateRouteResult#getPathTemplate() }.
*/
PathTemplateRouteResult<T> route(String path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure how old code handled that, but method name and description hint nothing more should be done as "route" is very specific action. So Id wager it could be confusing, maybe add something about that?

* <li>It is assumed that most services that use routing based on path templates will setup a router once (when the service
* starts) using a single thread and will then use that router to route millions of inbound requests using multiple concurrent
* threads. Perhaps the setup will not happen exactly once, but the mutation of routes happen very few times when compared to
* the number of times that requests are routed. For this reason this factory is heavily biased towards optimising the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"this factory" - this is interface?
Generally explanations are quite good, though sometimes off topic. Which not necessarily bad, if done properly. Here its tad confusing? Especially that its repetition of PathTemplateRouter last paragraph?
Also, PathTemplateRouter actually describes overall design, so there is no need to duplicate what is done there, unless its needed for extension in each class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: I might have had this class open twice( will have to check) so "repetition" comment might not be correct.

@baranowb
Copy link
Contributor

baranowb commented Sep 4, 2024

done... Im going to bring this PR up on call today.

@baranowb baranowb added the new feature/API change New feature to be introduced or a change to the API (non suitable to minor releases) label Sep 4, 2024
@dirkroets
Copy link
Author

Thanks, @baranowb . I'm travelling for work until 30 September, so time is very limited on my side. I will make a few changes to the documentation again from the 30th of September.

Any more feedback after last week's call?

@baranowb
Copy link
Contributor

@dirkroets hey, sorry I missed notification. I did bring it up and its on devs TODO list, which got delayed due to conference and some "issues on a deadline".

@dirkroets
Copy link
Author

@baranowb , thanks for the feedback. I've added a commit with the javadoc improvements that you suggested on the 4th of September. Please let me know if there is anything else that I can assist with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhances existing behaviour or code new feature/API change New feature to be introduced or a change to the API (non suitable to minor releases) under verification Currently being verified (running tests, reviewing) before posting a review to contributor waiting peer review PRs that edit core classes might require an extra review waiting PR update Awaiting PR update(s) from contributor before merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants