Merge pull request #30512 from GabDug/techdocs-durations-config
Techdocs: support HumanDuration for cache config
This commit is contained in:
+16
-3
@@ -14,8 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { assertError, CustomErrorBase } from '@backstage/errors';
|
||||
import { Config } from '@backstage/config';
|
||||
import { Config, readDurationFromConfig } from '@backstage/config';
|
||||
import { CacheService, LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { durationToMilliseconds } from '@backstage/types';
|
||||
|
||||
export class CacheInvalidationError extends CustomErrorBase {}
|
||||
|
||||
@@ -42,8 +43,20 @@ export class TechDocsCache {
|
||||
config: Config,
|
||||
{ cache, logger }: { cache: CacheService; logger: LoggerService },
|
||||
) {
|
||||
const timeout = config.getOptionalNumber('techdocs.cache.readTimeout');
|
||||
const readTimeout = timeout === undefined ? 1000 : timeout;
|
||||
let readTimeout: number;
|
||||
if (config.has('techdocs.cache.readTimeout')) {
|
||||
if (typeof config.get('techdocs.cache.readTimeout') === 'number') {
|
||||
readTimeout = config.getNumber('techdocs.cache.readTimeout');
|
||||
} else {
|
||||
readTimeout = durationToMilliseconds(
|
||||
readDurationFromConfig(config, {
|
||||
key: 'techdocs.cache.readTimeout',
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
readTimeout = 1000;
|
||||
}
|
||||
return new TechDocsCache({ cache, logger, readTimeout });
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,10 @@ import { TechDocsCache } from '../cache';
|
||||
import { mockErrorHandler, mockServices } from '@backstage/backend-test-utils';
|
||||
|
||||
jest.mock('@backstage/catalog-client');
|
||||
jest.mock('@backstage/config');
|
||||
jest.mock('./CachedEntityLoader');
|
||||
jest.mock('./DocsSynchronizer');
|
||||
jest.mock('../cache/TechDocsCache');
|
||||
|
||||
const MockedConfigReader = ConfigReader as jest.MockedClass<
|
||||
typeof ConfigReader
|
||||
>;
|
||||
const MockDocsSynchronizer = DocsSynchronizer as jest.MockedClass<
|
||||
typeof DocsSynchronizer
|
||||
>;
|
||||
@@ -115,7 +111,13 @@ describe('createRouter', () => {
|
||||
preparers,
|
||||
generators,
|
||||
publisher,
|
||||
config: new ConfigReader({}),
|
||||
config: new ConfigReader({
|
||||
techdocs: {
|
||||
cache: {
|
||||
ttl: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
logger: mockServices.logger.mock(),
|
||||
discovery,
|
||||
cache: mockServices.cache.mock(),
|
||||
@@ -143,9 +145,6 @@ describe('createRouter', () => {
|
||||
discovery.getBaseUrl.mockImplementation(async type => {
|
||||
return `http://backstage.local/api/${type}`;
|
||||
});
|
||||
MockedConfigReader.prototype.getOptionalNumber.mockImplementation(key =>
|
||||
key === 'techdocs.cache.ttl' ? 1 : undefined,
|
||||
);
|
||||
MockTechDocsCache.get.mockResolvedValue(undefined);
|
||||
MockTechDocsCache.set.mockResolvedValue();
|
||||
});
|
||||
@@ -326,13 +325,17 @@ data: {"updated":true}
|
||||
});
|
||||
|
||||
it('should check entity access when permissions are enabled', async () => {
|
||||
MockedConfigReader.prototype.getOptionalBoolean.mockImplementation(key =>
|
||||
key === 'permission.enabled' ? true : undefined,
|
||||
);
|
||||
const docsRouter = jest.fn((_req, res) => res.sendStatus(200));
|
||||
publisher.docsRouter.mockReturnValue(docsRouter);
|
||||
|
||||
const app = await createApp(outOfTheBoxOptions);
|
||||
const app = await createApp({
|
||||
...outOfTheBoxOptions,
|
||||
config: new ConfigReader({
|
||||
permission: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
MockCachedEntityLoader.prototype.load.mockResolvedValue(entity);
|
||||
|
||||
@@ -345,11 +348,14 @@ data: {"updated":true}
|
||||
});
|
||||
|
||||
it('should not return assets without corresponding entity access', async () => {
|
||||
MockedConfigReader.prototype.getOptionalBoolean.mockImplementation(key =>
|
||||
key === 'permission.enabled' ? true : undefined,
|
||||
);
|
||||
|
||||
const app = await createApp(outOfTheBoxOptions);
|
||||
const app = await createApp({
|
||||
...outOfTheBoxOptions,
|
||||
config: new ConfigReader({
|
||||
permission: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
MockCachedEntityLoader.prototype.load.mockResolvedValue(undefined);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { CatalogApi, CatalogClient } from '@backstage/catalog-client';
|
||||
import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { Config, readDurationFromConfig } from '@backstage/config';
|
||||
import { NotFoundError } from '@backstage/errors';
|
||||
import {
|
||||
DocsBuildStrategy,
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
HttpAuthService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { durationToMilliseconds } from '@backstage/types';
|
||||
|
||||
/**
|
||||
* Required dependencies for running TechDocs in the "out-of-the-box"
|
||||
@@ -131,9 +132,18 @@ export async function createRouter(
|
||||
|
||||
// Set up a cache client if configured.
|
||||
let cache: TechDocsCache | undefined;
|
||||
const defaultTtl = config.getOptionalNumber('techdocs.cache.ttl');
|
||||
if (defaultTtl) {
|
||||
const cacheClient = options.cache.withOptions({ defaultTtl });
|
||||
if (config.has('techdocs.cache.ttl')) {
|
||||
let ttlMs: number;
|
||||
if (typeof config.get('techdocs.cache.ttl') === 'number') {
|
||||
ttlMs = config.getNumber('techdocs.cache.ttl');
|
||||
} else {
|
||||
ttlMs = durationToMilliseconds(
|
||||
readDurationFromConfig(config, {
|
||||
key: 'techdocs.cache.ttl',
|
||||
}),
|
||||
);
|
||||
}
|
||||
const cacheClient = options.cache.withOptions({ defaultTtl: ttlMs });
|
||||
cache = TechDocsCache.fromConfig(config, { cache: cacheClient, logger });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user