Skip to content

Commit

Permalink
refactor: Better Result class implementation (#23335)
Browse files Browse the repository at this point in the history
  • Loading branch information
zharinov committed Jul 19, 2023
1 parent 433464d commit b641ec2
Show file tree
Hide file tree
Showing 6 changed files with 832 additions and 162 deletions.
32 changes: 18 additions & 14 deletions lib/modules/datasource/rubygems/index.ts
Expand Up @@ -2,6 +2,7 @@ import { Marshal } from '@qnighy/marshal';
import { logger } from '../../../logger';
import { cache } from '../../../util/cache/package/decorator';
import { HttpError } from '../../../util/http';
import { Result } from '../../../util/result';
import { getQueryString, joinUrlParts, parseUrl } from '../../../util/url';
import * as rubyVersioning from '../../versioning/ruby';
import { Datasource } from '../datasource';
Expand Down Expand Up @@ -40,23 +41,26 @@ export class RubyGemsDatasource extends Datasource {
return null;
}

try {
const { res: versionsResult } =
await this.versionsEndpointCache.getVersions(registryUrl, packageName);

if (versionsResult.success) {
const { value: versions } = versionsResult;
const result = await this.metadataCache.getRelease(
registryUrl,
packageName,
versions
);
return result;
}
const { val: rubygemsResult, err: rubygemsError } = await Result.wrap(
this.versionsEndpointCache.getVersions(registryUrl, packageName)
)
.transform((versions) =>
this.metadataCache.getRelease(registryUrl, packageName, versions)
)
.unwrap();

// istanbul ignore else: will be removed soon
if (rubygemsResult) {
return rubygemsResult;
} else if (rubygemsError instanceof Error) {
this.handleGenericErrors(rubygemsError);
}

try {
const registryHostname = parseUrl(registryUrl)?.hostname;

if (
versionsResult.error === 'unsupported-api' &&
rubygemsError === 'unsupported-api' &&
registryHostname !== 'rubygems.org'
) {
if (
Expand Down
44 changes: 22 additions & 22 deletions lib/modules/datasource/rubygems/versions-endpoint-cache.spec.ts
Expand Up @@ -30,12 +30,12 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
const baz = await rubygems.getVersions(registryUrl, 'baz');
const qux = await rubygems.getVersions(registryUrl, 'qux');

expect(foo.value).toEqual(['1.1.1']);
expect(bar.value).toEqual(['2.2.2']);
expect(baz.value).toEqual(['3.3.3']);
expect(qux.error).toBe('package-not-found');
expect(foo.unwrap().val).toEqual(['1.1.1']);
expect(bar.unwrap().val).toEqual(['2.2.2']);
expect(baz.unwrap().val).toEqual(['3.3.3']);
expect(qux.unwrap().err).toBe('package-not-found');

expect(memCache.get('https://rubygems.org')?.value).toMatchObject({
expect(memCache.get('https://rubygems.org')?.unwrap().val).toMatchObject({
contentTail: '33333333333333333333333333333333\n',
});
});
Expand All @@ -49,19 +49,19 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
rubygems.getVersions(registryUrl, 'baz'),
]);

expect(foo.value).toEqual(['1.1.1']);
expect(bar.value).toEqual(['2.2.2']);
expect(baz.value).toEqual(['3.3.3']);
expect(foo.unwrap().val).toEqual(['1.1.1']);
expect(bar.unwrap().val).toEqual(['2.2.2']);
expect(baz.unwrap().val).toEqual(['3.3.3']);
});

it('handles 404', async () => {
httpMock.scope(registryUrl).get('/versions').reply(404);

const res1 = await rubygems.getVersions(registryUrl, 'foo');
expect(res1.error).toBe('unsupported-api');
expect(res1.unwrap().err).toBe('unsupported-api');

const res2 = await rubygems.getVersions(registryUrl, 'foo');
expect(res2.error).toBe('unsupported-api');
expect(res2.unwrap().err).toBe('unsupported-api');

expect(memCache.size).toBe(1);
});
Expand Down Expand Up @@ -92,7 +92,7 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
httpMock.scope(registryUrl).get('/versions').reply(200, fullBody);

const res1 = await rubygems.getVersions(registryUrl, 'foo');
expect(res1.value).toEqual(['1.1.1']);
expect(res1.unwrap().val).toEqual(['1.1.1']);

jest.advanceTimersByTime(15 * 60 * 1000);
httpMock
Expand All @@ -107,9 +107,9 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
);

const res2 = await rubygems.getVersions(registryUrl, 'foo');
expect(res2.value).toEqual(['1.2.3']);
expect(res2.unwrap().val).toEqual(['1.2.3']);

expect(memCache.get('https://rubygems.org')?.value).toMatchObject({
expect(memCache.get('https://rubygems.org')?.unwrap().val).toMatchObject({
contentTail: '44444444444444444444444444444444\n',
});
});
Expand All @@ -118,7 +118,7 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
httpMock.scope(registryUrl).get('/versions').reply(200, fullBody);

const res1 = await rubygems.getVersions(registryUrl, 'foo');
expect(res1.value).toEqual(['1.1.1']);
expect(res1.unwrap().val).toEqual(['1.1.1']);

jest.advanceTimersByTime(15 * 60 * 1000);
httpMock
Expand All @@ -144,9 +144,9 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
);

const res2 = await rubygems.getVersions(registryUrl, 'foo');
expect(res2.value).toEqual(['1.2.3']);
expect(res2.unwrap().val).toEqual(['1.2.3']);

expect(memCache.get('https://rubygems.org')?.value).toMatchObject({
expect(memCache.get('https://rubygems.org')?.unwrap().val).toMatchObject({
contentTail: '01010101010101010101010101010101\n',
});
});
Expand All @@ -155,7 +155,7 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
httpMock.scope(registryUrl).get('/versions').reply(200, fullBody);

const res1 = await rubygems.getVersions(registryUrl, 'foo');
expect(res1.value).toEqual(['1.1.1']);
expect(res1.unwrap().val).toEqual(['1.1.1']);

jest.advanceTimersByTime(15 * 60 * 1000);
httpMock
Expand All @@ -167,9 +167,9 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
);

const res2 = await rubygems.getVersions(registryUrl, 'foo');
expect(res2.value).toEqual(['1.2.3']);
expect(res2.unwrap().val).toEqual(['1.2.3']);

expect(memCache.get('https://rubygems.org')?.value).toMatchObject({
expect(memCache.get('https://rubygems.org')?.unwrap().val).toMatchObject({
contentTail: '44444444444444444444444444444444\n',
});
});
Expand All @@ -187,10 +187,10 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {
httpMock.scope(registryUrl).get('/versions').reply(404);

const res1 = await rubygems.getVersions(registryUrl, 'foo');
expect(res1.error).toBe('unsupported-api');
expect(res1.unwrap().err).toBe('unsupported-api');

const res2 = await rubygems.getVersions(registryUrl, 'foo');
expect(res2.error).toBe('unsupported-api');
expect(res2.unwrap().err).toBe('unsupported-api');
});

it('handles 416', async () => {
Expand All @@ -210,7 +210,7 @@ describe('modules/datasource/rubygems/versions-endpoint-cache', () => {

const res = await rubygems.getVersions(registryUrl, 'foo');

expect(res.value).toEqual(['9.9.9']);
expect(res.unwrap().val).toEqual(['9.9.9']);
});

it('handles unknown errors', async () => {
Expand Down
14 changes: 7 additions & 7 deletions lib/modules/datasource/rubygems/versions-endpoint-cache.ts
Expand Up @@ -143,20 +143,20 @@ export class VersionsEndpointCache {
*/
private async getCache(registryUrl: string): Promise<VersionsEndpointResult> {
const oldResult = memCache.get(registryUrl);

if (!oldResult) {
const newResult = await this.fullSync(registryUrl);
cacheResult(registryUrl, newResult);
return newResult;
}

if (!oldResult.res.success) {
const { val: data } = oldResult.unwrap();
if (!data) {
return oldResult;
}

if (isStale(oldResult.res.value)) {
if (isStale(data)) {
memCache.delete(registryUrl); // If no error is thrown, we'll re-set the cache
const newResult = await this.deltaSync(oldResult.res.value, registryUrl);
const newResult = await this.deltaSync(data, registryUrl);
cacheResult(registryUrl, newResult);
return newResult;
}
Expand All @@ -182,17 +182,17 @@ export class VersionsEndpointCache {
} finally {
this.cacheRequests.delete(registryUrl);
}
const { res } = cachedResult;

if (!res.success) {
const { val: cachedData } = cachedResult.unwrap();
if (!cachedData) {
logger.debug(
{ packageName, registryUrl },
'Rubygems: endpoint not supported'
);
return Result.err('unsupported-api');
}

const versions = res.value.packageVersions.get(packageName);
const versions = cachedData.packageVersions.get(packageName);
if (!versions?.length) {
logger.debug(
{ packageName, registryUrl },
Expand Down

0 comments on commit b641ec2

Please sign in to comment.