diff --git a/lib/modules/datasource/github-releases/cache/cache-base.spec.ts b/lib/modules/datasource/github-releases/cache/cache-base.spec.ts index c36ffccd4002b3837faef0553fcc07938d488482..640fcdcc7f2b785acc53d6e804324281cc229872 100644 --- a/lib/modules/datasource/github-releases/cache/cache-base.spec.ts +++ b/lib/modules/datasource/github-releases/cache/cache-base.spec.ts @@ -251,12 +251,10 @@ describe('modules/datasource/github-releases/cache/cache-base', () => { ]; const cache = new TestCache(http, { resetDeltaMinutes: 0 }); - const res = await cache.getItems({ packageName: 'foo/bar' }); - - expect(sortItems(res)).toMatchObject([ - { version: 'v1', bar: 'aaa' }, - { version: 'v2', bar: 'bbb' }, - { version: 'v3', bar: 'ccc' }, - ]); + await expect(cache.getItems({ packageName: 'foo/bar' })).rejects.toThrow( + 'Unknown error' + ); + expect(packageCache.get).toHaveBeenCalled(); + expect(packageCache.set).not.toHaveBeenCalled(); }); }); diff --git a/lib/modules/datasource/github-releases/cache/cache-base.ts b/lib/modules/datasource/github-releases/cache/cache-base.ts index 8e8ee6ae172e7d76c123289eb44783c3563175d9..3a846a31998ee1f6c7c4914f24a2aa76fd2cd7d5 100644 --- a/lib/modules/datasource/github-releases/cache/cache-base.ts +++ b/lib/modules/datasource/github-releases/cache/cache-base.ts @@ -1,5 +1,4 @@ import { DateTime, DurationLikeObject } from 'luxon'; -import { logger } from '../../../../logger'; import * as packageCache from '../../../../util/cache/package'; import type { GithubGraphqlResponse, @@ -177,115 +176,102 @@ export abstract class AbstractGithubDatasourceCache< cacheUpdatedAt = cache.updatedAt; } - try { - if (isExpired(now, cacheUpdatedAt, this.updateDuration)) { - const variables: GithubQueryParams = { - owner, - name, - cursor: null, - count: cacheDoesExist - ? this.itemsPerUpdatePage - : this.itemsPerPrefetchPage, - }; - - // Collect version values to determine deleted items - const checkedVersions = new Set<string>(); - - // Page-by-page update loop - let pagesRemained = cacheDoesExist - ? this.maxUpdatePages - : this.maxPrefetchPages; - let stopIteration = false; - while (pagesRemained > 0 && !stopIteration) { - const graphqlRes = await this.http.postJson< - GithubGraphqlResponse<QueryResponse<FetchedItem>> - >('/graphql', { - baseUrl, - body: { query: this.graphqlQuery, variables }, - }); - pagesRemained -= 1; - - const data = graphqlRes.body.data; - if (data) { - const { - nodes: fetchedItems, - pageInfo: { hasNextPage, endCursor }, - } = data.repository.payload; - - if (hasNextPage) { - variables.cursor = endCursor; - } else { - stopIteration = true; - } + if (isExpired(now, cacheUpdatedAt, this.updateDuration)) { + const variables: GithubQueryParams = { + owner, + name, + cursor: null, + count: cacheDoesExist + ? this.itemsPerUpdatePage + : this.itemsPerPrefetchPage, + }; + + // Collect version values to determine deleted items + const checkedVersions = new Set<string>(); + + // Page-by-page update loop + let pagesRemained = cacheDoesExist + ? this.maxUpdatePages + : this.maxPrefetchPages; + let stopIteration = false; + while (pagesRemained > 0 && !stopIteration) { + const graphqlRes = await this.http.postJson< + GithubGraphqlResponse<QueryResponse<FetchedItem>> + >('/graphql', { + baseUrl, + body: { query: this.graphqlQuery, variables }, + }); + pagesRemained -= 1; + + const data = graphqlRes.body.data; + if (data) { + const { + nodes: fetchedItems, + pageInfo: { hasNextPage, endCursor }, + } = data.repository.payload; + + if (hasNextPage) { + variables.cursor = endCursor; + } else { + stopIteration = true; + } - for (const item of fetchedItems) { - const newStoredItem = this.coerceFetched(item); - if (newStoredItem) { - const { version } = newStoredItem; - - // Stop earlier if the stored item have reached stability, - // which means `unstableDays` period have passed - const oldStoredItem = cacheItems[version]; - if ( - oldStoredItem && - isExpired( - now, - oldStoredItem.releaseTimestamp, - this.stabilityDuration - ) - ) { - stopIteration = true; - break; - } - - cacheItems[version] = newStoredItem; - checkedVersions.add(version); + for (const item of fetchedItems) { + const newStoredItem = this.coerceFetched(item); + if (newStoredItem) { + const { version } = newStoredItem; + + // Stop earlier if the stored item have reached stability, + // which means `unstableDays` period have passed + const oldStoredItem = cacheItems[version]; + if ( + oldStoredItem && + isExpired( + now, + oldStoredItem.releaseTimestamp, + this.stabilityDuration + ) + ) { + stopIteration = true; + break; } - } - } - } - // Detect removed items - for (const [version, item] of Object.entries(cacheItems)) { - if ( - !isExpired(now, item.releaseTimestamp, this.stabilityDuration) && - !checkedVersions.has(version) - ) { - delete cacheItems[version]; + cacheItems[version] = newStoredItem; + checkedVersions.add(version); + } } } + } - // Store cache - const expiry = DateTime.fromISO(cacheCreatedAt).plus( - this.resetDuration - ); - const { minutes: ttlMinutes } = expiry - .diff(now, ['minutes']) - .toObject(); - if (ttlMinutes && ttlMinutes > 0) { - const cacheValue: GithubDatasourceCache<StoredItem> = { - items: cacheItems, - createdAt: cacheCreatedAt, - updatedAt: now.toISO(), - }; - await packageCache.set( - this.cacheNs, - cacheKey, - cacheValue, - ttlMinutes - ); + // Detect removed items + for (const [version, item] of Object.entries(cacheItems)) { + if ( + !isExpired(now, item.releaseTimestamp, this.stabilityDuration) && + !checkedVersions.has(version) + ) { + delete cacheItems[version]; } } - } catch (err) { - logger.debug( - { err }, - `GitHub datasource: error fetching cacheable GraphQL data` - ); - // On errors, return previous value (if valid) - if (cacheDoesExist) { - const cachedItems = Object.values(cache.items); - return cachedItems; + // Store cache + const expiry = DateTime.fromISO(cacheCreatedAt).plus( + this.resetDuration + ); + const { minutes: ttlMinutes } = expiry + .diff(now, ['minutes']) + .toObject(); + if (ttlMinutes && ttlMinutes > 0) { + const cacheValue: GithubDatasourceCache<StoredItem> = { + items: cacheItems, + createdAt: cacheCreatedAt, + updatedAt: now.toISO(), + }; + await packageCache.set( + this.cacheNs, + cacheKey, + cacheValue, + ttlMinutes + ); } } }