From 2a29ea374d8f36e9b2e77ac1aaa2be37f8f51885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=94=E7=8E=8B=E5=B0=91=E5=B9=B4?= Date: Sun, 27 Oct 2024 02:10:34 +0800 Subject: [PATCH] fix: injected services should not be re-evaluated within the request scope --- src/dependency.test.ts | 21 +++++++++++++++++++++ src/dependency.ts | 16 ++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/dependency.test.ts b/src/dependency.test.ts index 1d05fcd..0555691 100644 --- a/src/dependency.test.ts +++ b/src/dependency.test.ts @@ -92,6 +92,27 @@ describe("Dependency", () => { expect(createCount).toBe(2); }); + it("injected service will not be re-evaluated on request scope", async () => { + const dep = new Dependency(() => new TestService("foo"), { + scope: "request", + }); + const app = new Hono() + .use(dep.middleware("service")) + .get("/", (c) => c.text(c.var.service.name)); + + dep.injection(new TestService("bar")); + + const res1 = await app.request("/"); + expect(res1.status).toBe(200); + const data1 = await res1.text(); + expect(data1).toBe("bar"); + + const res2 = await app.request("/"); + expect(res2.status).toBe(200); + const data2 = await res2.text(); + expect(data2).toBe("bar"); + }); + it("clear injected service", async () => { const dep = new Dependency(() => new TestService("foo")); const app = new Hono() diff --git a/src/dependency.ts b/src/dependency.ts index 46db98a..8399d85 100644 --- a/src/dependency.ts +++ b/src/dependency.ts @@ -21,8 +21,8 @@ export class Dependency { }, ) {} - // service cache - private service?: Service; + private serviceInjected?: Service; + private serviceCached?: Service; // used as a basis for caching when evaluating the request scope private lastRequest?: Request; @@ -30,7 +30,7 @@ export class Dependency { * Injects a service instance directly. Useful for overriding the default service. */ injection(service: Service): this { - this.service = service; + this.serviceInjected = service; return this; } @@ -38,7 +38,7 @@ export class Dependency { * Clear injected service. */ clearInjected(): this { - this.service = undefined; + this.serviceInjected = undefined; return this; } @@ -46,13 +46,17 @@ export class Dependency { * Resolve service. */ async resolve(c: Context): Promise { + if (this.serviceInjected) { + return this.serviceInjected; + } + // evaluate and clear the cache when handling the request scope if (this.opts?.scope === "request" && this.lastRequest !== c.req.raw) { - this.service = undefined; + this.serviceCached = undefined; this.lastRequest = c.req.raw; } - const service = (this.service ??= await this.serviceInitializer(c)); + const service = (this.serviceCached ??= await this.serviceInitializer(c)); return service; }