renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
114 lines (113 loc) • 3.61 kB
JavaScript
import { isDateExpired } from "../util.js";
import { dequal } from "dequal";
import { DateTime } from "luxon";
//#region lib/util/github/graphql/cache-strategies/abstract-cache-strategy.ts
/**
* Cache strategy handles the caching Github GraphQL items
* and reconciling them with newly obtained ones from paginated queries.
*/
var AbstractGithubGraphqlCacheStrategy = class AbstractGithubGraphqlCacheStrategy {
/**
* Time period after which a cache record is considered expired.
*/
static cacheTTLDays = 30;
/**
* The time which is used during single cache access cycle.
*/
now = DateTime.now().toUTC();
/**
* Set of all versions which were reconciled
* during the current cache access cycle.
*/
reconciledVersions;
/**
* These fields will be persisted.
*/
items;
createdAt = this.now;
/**
* This flag indicates whether there is any new or updated items
*/
hasNovelty = false;
cacheNs;
cacheKey;
skipStabilization;
constructor(cacheNs, cacheKey, skipStabilization = false) {
this.cacheNs = cacheNs;
this.cacheKey = cacheKey;
this.skipStabilization = skipStabilization;
}
/**
* Load data previously persisted by this strategy
* for given `cacheNs` and `cacheKey`.
*/
async getItems() {
if (this.items) return this.items;
let result = {
items: {},
createdAt: this.createdAt.toISO()
};
const storedData = await this.load();
if (storedData) {
const cacheTTLDuration = { hours: AbstractGithubGraphqlCacheStrategy.cacheTTLDays * 24 };
if (!isDateExpired(this.now, storedData.createdAt, cacheTTLDuration)) result = storedData;
}
this.createdAt = DateTime.fromISO(result.createdAt).toUTC();
this.items = result.items;
return this.items;
}
/**
* If package release exists longer than this cache can exist,
* we assume it won't updated/removed on the Github side.
*/
isStabilized(item) {
const unstableDuration = { hours: AbstractGithubGraphqlCacheStrategy.cacheTTLDays * 24 };
return isDateExpired(this.now, item.releaseTimestamp, unstableDuration);
}
/**
* Process items received from GraphQL page
* ordered by `releaseTimestamp` in descending order
* (fresh versions go first).
*/
async reconcile(items) {
const cachedItems = await this.getItems();
let isPaginationDone = false;
for (const item of items) {
const { version } = item;
const oldItem = cachedItems[version];
if (!this.skipStabilization && oldItem && this.isStabilized(oldItem)) isPaginationDone = true;
if (!oldItem || !dequal(oldItem, item)) this.hasNovelty = true;
cachedItems[version] = item;
this.reconciledVersions ??= /* @__PURE__ */ new Set();
this.reconciledVersions.add(version);
}
this.items = cachedItems;
return isPaginationDone;
}
/**
* Handle removed items for packages that are not stabilized
* and return the list of all items.
*/
async finalizeAndReturn() {
const cachedItems = await this.getItems();
let resultItems;
let hasDeletedItems = false;
if (this.reconciledVersions) {
resultItems = {};
for (const [version, item] of Object.entries(cachedItems)) if (this.reconciledVersions.has(version) || this.isStabilized(item)) resultItems[version] = item;
else hasDeletedItems = true;
} else resultItems = cachedItems;
if (this.hasNovelty || hasDeletedItems) await this.store(resultItems);
return Object.values(resultItems);
}
async store(cachedItems) {
const cacheRecord = {
items: cachedItems,
createdAt: this.createdAt.toISO()
};
await this.persist(cacheRecord);
}
};
//#endregion
export { AbstractGithubGraphqlCacheStrategy };
//# sourceMappingURL=abstract-cache-strategy.js.map