0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

fix(core): update domain cache (#4017)

This commit is contained in:
wangsijie 2023-06-19 15:45:42 +09:00 committed by GitHub
parent 8f78515976
commit ad44f0875a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 8 deletions

View file

@ -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 { MockQueries } = await import('#src/test-utils/tenant.js');
const { createDomainLibrary } = await import('./domain.js'); const { createDomainLibrary } = await import('./domain.js');
@ -49,11 +53,16 @@ afterAll(() => {
SystemContext.shared.hostnameProviderConfig = undefined; SystemContext.shared.hostnameProviderConfig = undefined;
}); });
afterEach(() => {
clearCustomDomainCache.mockClear();
});
describe('addDomain()', () => { describe('addDomain()', () => {
it('should call createCustomHostname and return cloudflare data', async () => { it('should call createCustomHostname and return cloudflare data', async () => {
const response = await addDomain(mockDomain.domain); const response = await addDomain(mockDomain.domain);
expect(createCustomHostname).toBeCalledTimes(1); expect(createCustomHostname).toBeCalledTimes(1);
expect(insertDomain).toBeCalledTimes(1); expect(insertDomain).toBeCalledTimes(1);
expect(clearCustomDomainCache).toBeCalledTimes(1);
expect(response.cloudflareData).toMatchObject(mockCloudflareData); expect(response.cloudflareData).toMatchObject(mockCloudflareData);
expect(response.dnsRecords).toContainEqual({ expect(response.dnsRecords).toContainEqual({
type: 'CNAME', type: 'CNAME',
@ -76,6 +85,7 @@ describe('syncDomainStatus()', () => {
cloudflareData: mockCloudflareDataPendingSSL, cloudflareData: mockCloudflareDataPendingSSL,
}); });
expect(getCustomHostname).toBeCalledTimes(1); expect(getCustomHostname).toBeCalledTimes(1);
expect(clearCustomDomainCache).toBeCalledTimes(1);
expect(response.cloudflareData).toMatchObject(mockCloudflareData); expect(response.cloudflareData).toMatchObject(mockCloudflareData);
}); });
@ -128,6 +138,7 @@ describe('deleteDomain()', () => {
findDomainById.mockResolvedValueOnce(mockDomainWithCloudflareData); findDomainById.mockResolvedValueOnce(mockDomainWithCloudflareData);
await deleteDomain(mockDomain.id); await deleteDomain(mockDomain.id);
expect(deleteCustomHostname).toBeCalledTimes(1); expect(deleteCustomHostname).toBeCalledTimes(1);
expect(clearCustomDomainCache).toBeCalledTimes(1);
expect(deleteDomainById).toBeCalledTimes(1); expect(deleteDomainById).toBeCalledTimes(1);
}); });
@ -135,6 +146,7 @@ describe('deleteDomain()', () => {
findDomainById.mockResolvedValueOnce(mockDomain); findDomainById.mockResolvedValueOnce(mockDomain);
await deleteDomain(mockDomain.id); await deleteDomain(mockDomain.id);
expect(deleteCustomHostname).not.toBeCalled(); expect(deleteCustomHostname).not.toBeCalled();
expect(clearCustomDomainCache).toBeCalledTimes(1);
expect(deleteDomainById).toBeCalledTimes(1); expect(deleteDomainById).toBeCalledTimes(1);
}); });
}); });

View file

@ -10,6 +10,7 @@ import {
deleteCustomHostname, deleteCustomHostname,
getFallbackOrigin, getFallbackOrigin,
} from '#src/utils/cloudflare/index.js'; } from '#src/utils/cloudflare/index.js';
import { clearCustomDomainCache } from '#src/utils/tenant.js';
export type DomainLibrary = ReturnType<typeof createDomainLibrary>; export type DomainLibrary = ReturnType<typeof createDomainLibrary>;
@ -60,7 +61,9 @@ export const createDomainLibrary = (queries: Queries) => {
domain.cloudflareData.id 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<Domain> => { const addDomain = async (hostname: string): Promise<Domain> => {
@ -72,7 +75,7 @@ export const createDomainLibrary = (queries: Queries) => {
createCustomHostname(hostnameProviderConfig, hostname), createCustomHostname(hostnameProviderConfig, hostname),
]); ]);
return insertDomain({ const insertedDomain = await insertDomain({
domain: hostname, domain: hostname,
id: generateStandardId(), id: generateStandardId(),
cloudflareData, cloudflareData,
@ -85,6 +88,8 @@ export const createDomainLibrary = (queries: Queries) => {
}, },
], ],
}); });
await clearCustomDomainCache(hostname);
return insertedDomain;
}; };
const deleteDomain = async (id: string) => { const deleteDomain = async (id: string) => {
@ -98,6 +103,7 @@ export const createDomainLibrary = (queries: Queries) => {
} }
await deleteDomainById(id); await deleteDomainById(id);
await clearCustomDomainCache(domain.domain);
}; };
return { return {

View file

@ -46,8 +46,12 @@ const matchPathBasedTenantId = (urlSet: UrlSet, url: URL) => {
}; };
const cacheKey = 'custom-domain'; const cacheKey = 'custom-domain';
const notFoundValue = 'not-found'; const getDomainCacheKey = (url: URL | string) =>
const getDomainCacheKey = (url: URL) => `${cacheKey}:${url.hostname}`; `${cacheKey}:${typeof url === 'string' ? url : url.hostname}`;
export const clearCustomDomainCache = async (url: URL | string) => {
await trySafe(async () => redisCache.delete(getDomainCacheKey(url)));
};
const getTenantIdFromCustomDomain = async ( const getTenantIdFromCustomDomain = async (
url: URL, url: URL,
@ -56,16 +60,16 @@ const getTenantIdFromCustomDomain = async (
const cachedValue = await trySafe(async () => redisCache.get(getDomainCacheKey(url))); const cachedValue = await trySafe(async () => redisCache.get(getDomainCacheKey(url)));
if (cachedValue) { if (cachedValue) {
return cachedValue === notFoundValue ? undefined : cachedValue; return cachedValue;
} }
const { findActiveDomain } = createDomainsQueries(pool); const { findActiveDomain } = createDomainsQueries(pool);
const domain = await findActiveDomain(url.hostname); const domain = await findActiveDomain(url.hostname);
await trySafe(async () => if (domain?.tenantId) {
redisCache.set(getDomainCacheKey(url), domain?.tenantId ?? notFoundValue, 60) await trySafe(async () => redisCache.set(getDomainCacheKey(url), domain.tenantId));
); }
return domain?.tenantId; return domain?.tenantId;
}; };