-
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move to cron based caching strategy
- Loading branch information
1 parent
8b2e6e3
commit f89a926
Showing
21 changed files
with
305 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { DateTime } from 'luxon' | ||
import { BaseModel, column } from '@adonisjs/lucid/orm' | ||
|
||
export default class PackageStats extends BaseModel { | ||
@column({ isPrimary: true }) declare id: number | ||
|
||
@column() declare packageName: string | ||
@column() declare weeklyDownloads: number | ||
@column() declare githubStars: number | ||
@column.dateTime() declare firstReleaseAt: DateTime | null | ||
@column.dateTime() declare lastReleaseAt: DateTime | null | ||
|
||
@column.dateTime({ autoCreate: true }) declare createdAt: DateTime | ||
@column.dateTime({ autoCreate: true, autoUpdate: true }) declare updatedAt: DateTime | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import pLimit from 'p-limit' | ||
import { DateTime } from 'luxon' | ||
import logger from '@adonisjs/core/services/logger' | ||
|
||
import type { PackageInfo } from '#types/main' | ||
import PackageStats from '#models/package_stats' | ||
import type { PackageFetcher } from './package_fetcher.js' | ||
|
||
export class PackagesDataRefresher { | ||
constructor( | ||
protected packageFetcher: PackageFetcher, | ||
protected packagesList: PackageInfo[], | ||
) {} | ||
|
||
/** | ||
* Get the first and last release dates from cache or fetch it from npm | ||
*/ | ||
async #getReleasesDates(pkg: PackageInfo) { | ||
if (!pkg.npm) return { firstReleaseAt: '', lastReleaseAt: '' } | ||
|
||
return this.packageFetcher.fetchReleaseDates(pkg.npm!).catch((err) => { | ||
logger.error({ err }, `Cannot fetch releases dates for ${pkg.npm}`) | ||
return { firstReleaseAt: '', lastReleaseAt: '' } | ||
}) | ||
} | ||
|
||
/** | ||
* Get the package downloads from cache or fetch it from npm | ||
*/ | ||
async #getPackageDownloads(pkg: PackageInfo) { | ||
if (!pkg.npm) return { downloads: 0 } | ||
|
||
return this.packageFetcher.fetchPackageDownloads(pkg.npm!).catch((err) => { | ||
logger.error({ err }, `Cannot fetch npm info for ${pkg.npm}`) | ||
return { downloads: 0 } | ||
}) | ||
} | ||
|
||
/** | ||
* Get the github stars from cache or fetch it from github | ||
*/ | ||
async #getGithubStars(pkg: PackageInfo) { | ||
if (!pkg.repo) return { stars: 0 } | ||
|
||
return this.packageFetcher.fetchGithubStars(pkg.repo).catch((err) => { | ||
logger.error({ err }, `Cannot fetch github repo info for ${pkg.repo}`) | ||
return { stars: 0 } | ||
}) | ||
} | ||
|
||
/** | ||
* Get stats about a single package | ||
*/ | ||
async #fetchPackageStats(pkg: PackageInfo) { | ||
logger.debug(`Fetching stats for ${pkg.name}`) | ||
|
||
const [npmStats, ghStats, releases] = await Promise.all([ | ||
this.#getPackageDownloads(pkg), | ||
this.#getGithubStars(pkg), | ||
this.#getReleasesDates(pkg), | ||
]) | ||
|
||
pkg.downloads = npmStats.downloads | ||
pkg.stars = ghStats.stars | ||
pkg.firstReleaseAt = releases.firstReleaseAt | ||
pkg.lastReleaseAt = releases.lastReleaseAt | ||
|
||
return pkg | ||
} | ||
|
||
/** | ||
* Fetch stats for all packages, either from cache or from npm/github | ||
*/ | ||
async refresh() { | ||
logger.debug('Refreshing packages stats') | ||
|
||
const limit = pLimit(10) | ||
let packages = [...this.packagesList] | ||
|
||
packages = await Promise.all(packages.map((pkg) => limit(() => this.#fetchPackageStats(pkg)))) | ||
|
||
await PackageStats.updateOrCreateMany( | ||
'packageName', | ||
packages.map((pkg) => ({ | ||
packageName: pkg.name, | ||
githubStars: pkg.stars, | ||
weeklyDownloads: pkg.downloads, | ||
firstReleaseAt: pkg.firstReleaseAt ? DateTime.fromISO(pkg.firstReleaseAt) : null, | ||
lastReleaseAt: pkg.lastReleaseAt ? DateTime.fromISO(pkg.lastReleaseAt) : null, | ||
})), | ||
) | ||
|
||
logger.debug('Packages stats refreshed') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.