mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-27 15:58:48 +00:00
1e6ffa8171
Every datasource that caches its releases hand-wrote the same
`withCache({ namespace: `datasource-${id}`, ... }, () => this._getReleases(config))`
wrapper, repeating the namespace literal and using underscore-prefixed
method names that `docs/development/best-practices.md` discourages.
Add `Datasource.cacheNamespace` (derived from the datasource id) and a
protected `Datasource.cached()` helper that defaults `namespace` to it,
exporting `CachedOptions` from `with-cache.ts`. Migrate 29 datasources
onto the helper, dropping their namespace literals, the static
`cacheNamespace` field in `github-digest`, and renaming the wrapped
`_getX` methods to `fetchX`.
Behaviour change: `golang-version` used the constant cache key `'all'`
while declaring `customRegistrySupport = true`, so a custom registryUrl
shared the cache entry with the default one. The key is now
`${config.registryUrl}`, which invalidates existing entries once.
113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import type { MockInstance } from 'vitest';
|
|
import * as httpMock from '~test/http-mock.ts';
|
|
import { partial } from '~test/util.ts';
|
|
import { EXTERNAL_HOST_ERROR } from '../../constants/error-messages.ts';
|
|
import * as packageCache from '../../util/cache/package/index.ts';
|
|
import { Datasource } from './datasource.ts';
|
|
import type { GetReleasesConfig, ReleaseResult } from './types.ts';
|
|
|
|
const exampleUrl = 'https://example.com/';
|
|
|
|
class TestDatasource extends Datasource {
|
|
constructor() {
|
|
super('test');
|
|
}
|
|
|
|
async getReleases(
|
|
_getReleasesConfig: GetReleasesConfig,
|
|
): Promise<ReleaseResult | null> {
|
|
try {
|
|
await this.http.get(exampleUrl);
|
|
} catch (err) {
|
|
this.handleGenericErrors(err);
|
|
}
|
|
return Promise.resolve(null);
|
|
}
|
|
}
|
|
|
|
class CachedDatasource extends Datasource {
|
|
constructor() {
|
|
super('test');
|
|
}
|
|
|
|
getReleases(config: GetReleasesConfig): Promise<ReleaseResult | null> {
|
|
return this.cached({ key: config.packageName }, () =>
|
|
Promise.resolve<ReleaseResult>({ releases: [{ version: '1.0.0' }] }),
|
|
);
|
|
}
|
|
|
|
getConstantValue(): Promise<string> {
|
|
return this.cached(
|
|
{ namespace: '_test-namespace', key: 'constant' },
|
|
() => 'value',
|
|
);
|
|
}
|
|
}
|
|
|
|
describe('modules/datasource/datasource', () => {
|
|
it('should throw on 429', async () => {
|
|
const testDatasource = new TestDatasource();
|
|
|
|
httpMock.scope(exampleUrl).get('/').reply(429);
|
|
|
|
await expect(
|
|
testDatasource.getReleases(partial<GetReleasesConfig>()),
|
|
).rejects.toThrow(EXTERNAL_HOST_ERROR);
|
|
});
|
|
|
|
it('should throw on statusCode >=500 && <600', async () => {
|
|
const testDatasource = new TestDatasource();
|
|
|
|
httpMock.scope(exampleUrl).get('/').reply(504);
|
|
|
|
await expect(
|
|
testDatasource.getReleases(partial<GetReleasesConfig>()),
|
|
).rejects.toThrow(EXTERNAL_HOST_ERROR);
|
|
});
|
|
|
|
describe('cached', () => {
|
|
let setCache: MockInstance<typeof packageCache.setWithRawTtl>;
|
|
|
|
beforeEach(() => {
|
|
setCache = vi.spyOn(packageCache, 'setWithRawTtl').mockResolvedValue();
|
|
});
|
|
|
|
afterEach(() => {
|
|
setCache.mockRestore();
|
|
});
|
|
|
|
it('defaults the namespace to the datasource id', async () => {
|
|
const testDatasource = new CachedDatasource();
|
|
|
|
await expect(
|
|
testDatasource.getReleases(
|
|
partial<GetReleasesConfig>({ packageName: 'foo' }),
|
|
),
|
|
).resolves.toEqual({ releases: [{ version: '1.0.0' }] });
|
|
|
|
expect(setCache).toHaveBeenCalledExactlyOnceWith(
|
|
'datasource-test',
|
|
'cache-decorator:foo',
|
|
{
|
|
cachedAt: expect.any(String),
|
|
value: { releases: [{ version: '1.0.0' }] },
|
|
},
|
|
30,
|
|
);
|
|
});
|
|
|
|
it('supports overriding the namespace', async () => {
|
|
const testDatasource = new CachedDatasource();
|
|
|
|
await expect(testDatasource.getConstantValue()).resolves.toBe('value');
|
|
|
|
expect(setCache).toHaveBeenCalledExactlyOnceWith(
|
|
'_test-namespace',
|
|
'cache-decorator:constant',
|
|
{ cachedAt: expect.any(String), value: 'value' },
|
|
30,
|
|
);
|
|
});
|
|
});
|
|
});
|