using Octokit; using StabilityMatrix.Core.Attributes; using StabilityMatrix.Core.Database; using StabilityMatrix.Core.Models.Database; namespace StabilityMatrix.Core.Helper.Cache; [Singleton(typeof(IGithubApiCache))] public class GithubApiCache : IGithubApiCache { private readonly ILiteDbContext dbContext; private readonly IGitHubClient githubApi; private readonly TimeSpan cacheDuration = TimeSpan.FromMinutes(15); public GithubApiCache(ILiteDbContext dbContext, IGitHubClient githubApi) { this.dbContext = dbContext; this.githubApi = githubApi; } public async Task GetLatestRelease(string username, string repository) { var cacheKey = $"Releases-{username}-{repository}"; var latestRelease = await dbContext.GetGithubCacheEntry(cacheKey); if (latestRelease != null && !IsCacheExpired(latestRelease.LastUpdated)) { return latestRelease.AllReleases.First(); } var allReleases = await githubApi.Repository.Release.GetAll(username, repository); if (allReleases == null) { return null; } var cacheEntry = new GithubCacheEntry { CacheKey = cacheKey, AllReleases = allReleases.OrderByDescending(x => x.CreatedAt) }; await dbContext.UpsertGithubCacheEntry(cacheEntry); return cacheEntry.AllReleases.First(); } public async Task> GetAllReleases(string username, string repository) { var cacheKey = $"Releases-{username}-{repository}"; var cacheEntry = await dbContext.GetGithubCacheEntry(cacheKey); if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated)) { return cacheEntry.AllReleases.OrderByDescending(x => x.CreatedAt); } var allReleases = await githubApi.Repository.Release.GetAll(username, repository); if (allReleases == null) { return new List().OrderByDescending(x => x.CreatedAt); } var newCacheEntry = new GithubCacheEntry { CacheKey = cacheKey, AllReleases = allReleases.OrderByDescending(x => x.CreatedAt) }; await dbContext.UpsertGithubCacheEntry(newCacheEntry); return newCacheEntry.AllReleases; } public async Task> GetAllBranches(string username, string repository) { var cacheKey = $"Branches-{username}-{repository}"; var cacheEntry = await dbContext.GetGithubCacheEntry(cacheKey); if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated)) { return cacheEntry.Branches; } var branches = await githubApi.Repository.Branch.GetAll(username, repository); if (branches == null) { return new List(); } var newCacheEntry = new GithubCacheEntry { CacheKey = cacheKey, Branches = branches }; await dbContext.UpsertGithubCacheEntry(newCacheEntry); return newCacheEntry.Branches; } public async Task?> GetAllCommits( string username, string repository, string branch, int page = 1, int perPage = 10 ) { var cacheKey = $"Commits-{username}-{repository}-{branch}-{page}-{perPage}"; var cacheEntry = await dbContext.GetGithubCacheEntry(cacheKey); if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated)) { return cacheEntry.Commits; } var commits = await githubApi.Repository.Commit.GetAll( username, repository, new CommitRequest { Sha = branch }, new ApiOptions { PageCount = page, PageSize = perPage, StartPage = page } ); if (commits == null) { return new List(); } var newCacheEntry = new GithubCacheEntry { CacheKey = cacheKey, Commits = commits.Select(x => new GitCommit { Sha = x.Sha }) }; await dbContext.UpsertGithubCacheEntry(newCacheEntry); return newCacheEntry.Commits; } private bool IsCacheExpired(DateTimeOffset expiration) => expiration.Add(cacheDuration) < DateTimeOffset.UtcNow; }