From ad44f0875a10a41bd5c64de9b567c4b6228720f5 Mon Sep 17 00:00:00 2001 From: wangsijie Date: Mon, 19 Jun 2023 15:45:42 +0900 Subject: [PATCH] fix(core): update domain cache (#4017) --- packages/core/src/libraries/domain.test.ts | 12 ++++++++++++ packages/core/src/libraries/domain.ts | 10 ++++++++-- packages/core/src/utils/tenant.ts | 16 ++++++++++------ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/core/src/libraries/domain.test.ts b/packages/core/src/libraries/domain.test.ts index d397bd57d..9a8a41d24 100644 --- a/packages/core/src/libraries/domain.test.ts +++ b/packages/core/src/libraries/domain.test.ts @@ -25,6 +25,10 @@ const { getCustomHostname, createCustomHostname, deleteCustomHostname } = mockEs }) ); +const { clearCustomDomainCache } = mockEsm('#src/utils/tenant.js', () => ({ + clearCustomDomainCache: jest.fn(), +})); + const { MockQueries } = await import('#src/test-utils/tenant.js'); const { createDomainLibrary } = await import('./domain.js'); @@ -49,11 +53,16 @@ afterAll(() => { SystemContext.shared.hostnameProviderConfig = undefined; }); +afterEach(() => { + clearCustomDomainCache.mockClear(); +}); + describe('addDomain()', () => { it('should call createCustomHostname and return cloudflare data', async () => { const response = await addDomain(mockDomain.domain); expect(createCustomHostname).toBeCalledTimes(1); expect(insertDomain).toBeCalledTimes(1); + expect(clearCustomDomainCache).toBeCalledTimes(1); expect(response.cloudflareData).toMatchObject(mockCloudflareData); expect(response.dnsRecords).toContainEqual({ type: 'CNAME', @@ -76,6 +85,7 @@ describe('syncDomainStatus()', () => { cloudflareData: mockCloudflareDataPendingSSL, }); expect(getCustomHostname).toBeCalledTimes(1); + expect(clearCustomDomainCache).toBeCalledTimes(1); expect(response.cloudflareData).toMatchObject(mockCloudflareData); }); @@ -128,6 +138,7 @@ describe('deleteDomain()', () => { findDomainById.mockResolvedValueOnce(mockDomainWithCloudflareData); await deleteDomain(mockDomain.id); expect(deleteCustomHostname).toBeCalledTimes(1); + expect(clearCustomDomainCache).toBeCalledTimes(1); expect(deleteDomainById).toBeCalledTimes(1); }); @@ -135,6 +146,7 @@ describe('deleteDomain()', () => { findDomainById.mockResolvedValueOnce(mockDomain); await deleteDomain(mockDomain.id); expect(deleteCustomHostname).not.toBeCalled(); + expect(clearCustomDomainCache).toBeCalledTimes(1); expect(deleteDomainById).toBeCalledTimes(1); }); }); diff --git a/packages/core/src/libraries/domain.ts b/packages/core/src/libraries/domain.ts index 5541fa9bf..c20241b1f 100644 --- a/packages/core/src/libraries/domain.ts +++ b/packages/core/src/libraries/domain.ts @@ -10,6 +10,7 @@ import { deleteCustomHostname, getFallbackOrigin, } from '#src/utils/cloudflare/index.js'; +import { clearCustomDomainCache } from '#src/utils/tenant.js'; export type DomainLibrary = ReturnType; @@ -60,7 +61,9 @@ export const createDomainLibrary = (queries: Queries) => { domain.cloudflareData.id ); - return syncDomainStatusFromCloudflareData(domain, cloudflareData); + const updatedDomain = await syncDomainStatusFromCloudflareData(domain, cloudflareData); + await clearCustomDomainCache(domain.domain); + return updatedDomain; }; const addDomain = async (hostname: string): Promise => { @@ -72,7 +75,7 @@ export const createDomainLibrary = (queries: Queries) => { createCustomHostname(hostnameProviderConfig, hostname), ]); - return insertDomain({ + const insertedDomain = await insertDomain({ domain: hostname, id: generateStandardId(), cloudflareData, @@ -85,6 +88,8 @@ export const createDomainLibrary = (queries: Queries) => { }, ], }); + await clearCustomDomainCache(hostname); + return insertedDomain; }; const deleteDomain = async (id: string) => { @@ -98,6 +103,7 @@ export const createDomainLibrary = (queries: Queries) => { } await deleteDomainById(id); + await clearCustomDomainCache(domain.domain); }; return { diff --git a/packages/core/src/utils/tenant.ts b/packages/core/src/utils/tenant.ts index 75c790944..d33c66e42 100644 --- a/packages/core/src/utils/tenant.ts +++ b/packages/core/src/utils/tenant.ts @@ -46,8 +46,12 @@ const matchPathBasedTenantId = (urlSet: UrlSet, url: URL) => { }; const cacheKey = 'custom-domain'; -const notFoundValue = 'not-found'; -const getDomainCacheKey = (url: URL) => `${cacheKey}:${url.hostname}`; +const getDomainCacheKey = (url: URL | string) => + `${cacheKey}:${typeof url === 'string' ? url : url.hostname}`; + +export const clearCustomDomainCache = async (url: URL | string) => { + await trySafe(async () => redisCache.delete(getDomainCacheKey(url))); +}; const getTenantIdFromCustomDomain = async ( url: URL, @@ -56,16 +60,16 @@ const getTenantIdFromCustomDomain = async ( const cachedValue = await trySafe(async () => redisCache.get(getDomainCacheKey(url))); if (cachedValue) { - return cachedValue === notFoundValue ? undefined : cachedValue; + return cachedValue; } const { findActiveDomain } = createDomainsQueries(pool); const domain = await findActiveDomain(url.hostname); - await trySafe(async () => - redisCache.set(getDomainCacheKey(url), domain?.tenantId ?? notFoundValue, 60) - ); + if (domain?.tenantId) { + await trySafe(async () => redisCache.set(getDomainCacheKey(url), domain.tenantId)); + } return domain?.tenantId; };