|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
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 ILogger<IGithubApiCache> logger;
|
|
|
|
private readonly TimeSpan cacheDuration = TimeSpan.FromMinutes(15);
|
|
|
|
|
|
|
|
public GithubApiCache(
|
|
|
|
ILiteDbContext dbContext,
|
|
|
|
IGitHubClient githubApi,
|
|
|
|
ILogger<IGithubApiCache> logger
|
|
|
|
)
|
|
|
|
{
|
|
|
|
this.dbContext = dbContext;
|
|
|
|
this.githubApi = githubApi;
|
|
|
|
this.logger = logger;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task<IEnumerable<Release>> GetAllReleases(string username, string repository)
|
|
|
|
{
|
|
|
|
var cacheKey = $"Releases-{username}-{repository}";
|
|
|
|
var cacheEntry = await dbContext.GetGithubCacheEntry(cacheKey).ConfigureAwait(false);
|
|
|
|
if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated))
|
|
|
|
{
|
|
|
|
return cacheEntry.AllReleases.OrderByDescending(x => x.CreatedAt);
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var allReleases = await githubApi.Repository.Release
|
|
|
|
.GetAll(username, repository)
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
if (allReleases == null)
|
|
|
|
{
|
|
|
|
return new List<Release>();
|
|
|
|
}
|
|
|
|
|
|
|
|
var newCacheEntry = new GithubCacheEntry
|
|
|
|
{
|
|
|
|
CacheKey = cacheKey,
|
|
|
|
AllReleases = allReleases.OrderByDescending(x => x.CreatedAt)
|
|
|
|
};
|
|
|
|
await dbContext.UpsertGithubCacheEntry(newCacheEntry).ConfigureAwait(false);
|
|
|
|
|
|
|
|
return newCacheEntry.AllReleases;
|
|
|
|
}
|
|
|
|
catch (ApiException ex)
|
|
|
|
{
|
|
|
|
logger.LogWarning(ex, "Failed to get releases from Github API.");
|
|
|
|
return cacheEntry?.AllReleases.OrderByDescending(x => x.CreatedAt)
|
|
|
|
?? Enumerable.Empty<Release>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task<IEnumerable<Branch>> GetAllBranches(string username, string repository)
|
|
|
|
{
|
|
|
|
var cacheKey = $"Branches-{username}-{repository}";
|
|
|
|
var cacheEntry = await dbContext.GetGithubCacheEntry(cacheKey).ConfigureAwait(false);
|
|
|
|
if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated))
|
|
|
|
{
|
|
|
|
return cacheEntry.Branches;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var branches = await githubApi.Repository.Branch
|
|
|
|
.GetAll(username, repository)
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
if (branches == null)
|
|
|
|
{
|
|
|
|
return new List<Branch>();
|
|
|
|
}
|
|
|
|
|
|
|
|
var newCacheEntry = new GithubCacheEntry { CacheKey = cacheKey, Branches = branches };
|
|
|
|
await dbContext.UpsertGithubCacheEntry(newCacheEntry).ConfigureAwait(false);
|
|
|
|
|
|
|
|
return newCacheEntry.Branches;
|
|
|
|
}
|
|
|
|
catch (ApiException ex)
|
|
|
|
{
|
|
|
|
logger.LogWarning(ex, "Failed to get branches from Github API.");
|
|
|
|
return cacheEntry?.Branches ?? Enumerable.Empty<Branch>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task<IEnumerable<GitCommit>?> 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).ConfigureAwait(false);
|
|
|
|
if (cacheEntry != null && !IsCacheExpired(cacheEntry.LastUpdated))
|
|
|
|
{
|
|
|
|
return cacheEntry.Commits;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var commits = await githubApi.Repository.Commit
|
|
|
|
.GetAll(
|
|
|
|
username,
|
|
|
|
repository,
|
|
|
|
new CommitRequest { Sha = branch },
|
|
|
|
new ApiOptions
|
|
|
|
{
|
|
|
|
PageCount = page,
|
|
|
|
PageSize = perPage,
|
|
|
|
StartPage = page
|
|
|
|
}
|
|
|
|
)
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
|
|
|
|
if (commits == null)
|
|
|
|
{
|
|
|
|
return new List<GitCommit>();
|
|
|
|
}
|
|
|
|
|
|
|
|
var newCacheEntry = new GithubCacheEntry
|
|
|
|
{
|
|
|
|
CacheKey = cacheKey,
|
|
|
|
Commits = commits.Select(x => new GitCommit { Sha = x.Sha })
|
|
|
|
};
|
|
|
|
await dbContext.UpsertGithubCacheEntry(newCacheEntry).ConfigureAwait(false);
|
|
|
|
|
|
|
|
return newCacheEntry.Commits;
|
|
|
|
}
|
|
|
|
catch (ApiException ex)
|
|
|
|
{
|
|
|
|
logger.LogWarning(ex, "Failed to get commits from Github API.");
|
|
|
|
return cacheEntry?.Commits ?? Enumerable.Empty<GitCommit>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool IsCacheExpired(DateTimeOffset expiration) =>
|
|
|
|
expiration.Add(cacheDuration) < DateTimeOffset.UtcNow;
|
|
|
|
}
|