Skip to content

Commit 9a1c059

Browse files
committed
sort dynamic route list on first resolve
1 parent 3624460 commit 9a1c059

File tree

1 file changed

+20
-49
lines changed

1 file changed

+20
-49
lines changed

packages/event-handler/src/rest/RouteHandlerRegistry.ts

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ import {
1717

1818
class RouteHandlerRegistry {
1919
readonly #staticRoutes: Map<string, Route> = new Map();
20-
readonly #dynamicRoutesIndexMap: Map<string, number> = new Map();
20+
readonly #dynamicRoutesSet: Set<string> = new Set();
2121
readonly #dynamicRoutes: DynamicRoute[] = [];
2222
readonly #routesByMethod: Map<string, Route[]> = new Map();
23+
#shouldSort = true;
2324

2425
readonly #logger: Pick<GenericLogger, 'debug' | 'warn' | 'error'>;
2526

@@ -49,43 +50,6 @@ class RouteHandlerRegistry {
4950

5051
return bSegments - aSegments;
5152
}
52-
/**
53-
* Finds the correct insertion index using binary search to maintain sorted order.
54-
* @param route - The route to find insertion point for
55-
* @returns The index where the route should be inserted
56-
*/
57-
#binarySearchInsertIndex(route: DynamicRoute): number {
58-
let left = 0;
59-
let right = this.#dynamicRoutes.length;
60-
61-
while (left < right) {
62-
const mid = Math.floor((left + right) / 2);
63-
const comparison = this.#compareRouteSpecificity(
64-
route,
65-
this.#dynamicRoutes[mid]
66-
);
67-
68-
if (comparison < 0) {
69-
right = mid;
70-
} else {
71-
left = mid + 1;
72-
}
73-
}
74-
75-
return left;
76-
}
77-
/**
78-
* Adds a dynamic route to the registry, ensuring that the dynamic
79-
* routes array says sorted in ascending order of specificity.
80-
* @param route - The dynamic route to add
81-
* @returns The index in the specific routes array where the route was stored
82-
*/
83-
#addDynamicRoute(route: DynamicRoute): number {
84-
const index = this.#binarySearchInsertIndex(route);
85-
this.#dynamicRoutes.splice(index, 0, route);
86-
return index;
87-
}
88-
8953
/**
9054
* Registers a route in the registry after validating its path pattern.
9155
*
@@ -96,6 +60,7 @@ class RouteHandlerRegistry {
9660
* @param route - The route to register
9761
*/
9862
public register(route: Route): void {
63+
this.#shouldSort = true;
9964
const { isValid, issues } = validatePathPattern(route.path);
10065
if (!isValid) {
10166
for (const issue of issues) {
@@ -107,23 +72,25 @@ class RouteHandlerRegistry {
10772
const compiled = compilePath(route.path);
10873

10974
if (compiled.isDynamic) {
110-
let routeIndex = this.#dynamicRoutesIndexMap.get(route.id) ?? -1;
111-
if (routeIndex >= 0) {
75+
const dynamicRoute = {
76+
...route,
77+
...compiled,
78+
};
79+
if (this.#dynamicRoutesSet.has(route.id)) {
11280
this.#logger.warn(
11381
`Handler for method: ${route.method} and path: ${route.path} already exists. The previous handler will be replaced.`
11482
);
11583
// as dynamic routes are stored in an array, we can't rely on
11684
// overwriting a key in a map like with static routes so have
117-
// to manually manage deleting them
118-
this.#dynamicRoutes.splice(routeIndex, 1);
85+
// to manually manage overwriting them
86+
const i = this.#dynamicRoutes.findIndex(
87+
(oldRoute) => oldRoute.id === route.id
88+
);
89+
this.#dynamicRoutes[i] = dynamicRoute;
90+
} else {
91+
this.#dynamicRoutes.push(dynamicRoute);
11992
}
120-
121-
routeIndex = this.#addDynamicRoute({
122-
...route,
123-
...compiled,
124-
});
125-
126-
this.#dynamicRoutesIndexMap.set(route.id, routeIndex);
93+
this.#dynamicRoutesSet.add(route.id);
12794
} else {
12895
if (this.#staticRoutes.has(route.id)) {
12996
this.#logger.warn(
@@ -158,6 +125,10 @@ class RouteHandlerRegistry {
158125
* @returns Route handler options or null if no match found
159126
*/
160127
public resolve(method: HttpMethod, path: Path): RouteHandlerOptions | null {
128+
if (this.#shouldSort) {
129+
this.#dynamicRoutes.sort(this.#compareRouteSpecificity);
130+
this.#shouldSort = false;
131+
}
161132
const routeId = `${method}:${path}`;
162133

163134
const staticRoute = this.#staticRoutes.get(routeId);

0 commit comments

Comments
 (0)