Skip to content

Commit

Permalink
fix: generating routes in parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydw committed May 22, 2023
1 parent 505d5f0 commit 3a5b019
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 17 deletions.
15 changes: 10 additions & 5 deletions packages/amagaki/src/router.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ExecutionContext} from 'ava';
import {Pod} from './pod';
import { Route } from './router';
import {Route} from './router';
import {Server} from './server';
import getPort from 'get-port';
import test from 'ava';
Expand Down Expand Up @@ -49,17 +49,17 @@ test('Changing static files alters the router', async (t: ExecutionContext) => {

test('AddRoute', async (t: ExecutionContext) => {
const pod = new Pod('./fixtures/sampleRouteProvider/');
pod.router.addRoutes('default', async (provider) => {
pod.router.addRoutes('default', async provider => {
provider.addRoute({
urlPath: '/foo/bar/',
build: async () => '<title>foo</title>',
})
});
});
pod.router.addRoutes('custom', async (provider) => {
pod.router.addRoutes('custom', async provider => {
provider.addRoute({
urlPath: '/foo/custom/',
build: async () => '<title>custom</title>',
})
});
});
for (const [path, content] of [
['/foo/bar/', '<title>foo</title>'],
Expand All @@ -70,3 +70,8 @@ test('AddRoute', async (t: ExecutionContext) => {
t.deepEqual(content, html);
}
});

test('Parallel route building', async (t: ExecutionContext) => {
const pod = new Pod('./fixtures/sampleRouteProvider/');
await Promise.all([pod.warmup(), pod.warmup()]);
});
33 changes: 21 additions & 12 deletions packages/amagaki/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export interface RouteOptions {
fields?: Record<string, any>;
}


export type RouteBuilder = (provider: RouteProvider) => Promise<void>;

export class Router {
Expand Down Expand Up @@ -89,25 +88,33 @@ export class Router {
if (this.pod.cache.routes.length) {
return this.pod.cache.routes;
}
const routes = new Map<string, Route>();
for (const providers of Object.values(this.providers)) {
for (const provider of providers) {
const routes = await provider.routes();
for (const route of routes) {
const routeUrl = route.url.path;
if (routeUrl in this.pod.cache.routeMap) {
// Reset the cache so subsequent requests continue to error until
// the problem is resolved.
const foundRoute = this.pod.cache.routeMap[routeUrl];
const providerRoutes = await provider.routes();
for (const route of providerRoutes) {
const urlPath = route.url.path;
if (routes.has(urlPath)) {
// Reset the cache so subsequent requests to the dev server continue
// to show an error until the problem is resolved.
this.pod.cache.reset();
const existingRoute = routes[urlPath];
throw Error(
`Two routes share the same URL path (${route.url.path}): ${foundRoute} and ${route}. This probably means you have set the value for "$path" to the same thing for two different documents, or two locales of the same document. Ensure every route has a unique URL path by changing one of the "$path" values.`
`Two routes share the same URL path (${urlPath}): ${route} and ${existingRoute}. This probably means you have set the value for "$path" to the same thing for two different documents, or two locales of the same document. Ensure every route has a unique URL path by changing one of the "$path" values.`
);
}
this.pod.cache.routes.push(route);
this.pod.cache.routeMap[route.url.path] = route;
routes.set(urlPath, route);
}
}
}
this.pod.cache.routes = [
...this.pod.cache.routes,
...Array.from(routes.values()),
];
this.pod.cache.routeMap = {
...this.pod.cache.routeMap,
...Object.fromEntries(routes),
};
return this.pod.cache.routes;
}

Expand Down Expand Up @@ -182,7 +189,9 @@ export class RouteProvider {
return this._routes;
}
// Build all routes, then clear the route builders so they are not built again.
await Promise.all(this._routeBuilders.map(async (builder) => await builder(this)));
await Promise.all(
this._routeBuilders.map(async builder => await builder(this))
);
return this._routes;
}

Expand Down

0 comments on commit 3a5b019

Please sign in to comment.