Merge remote-tracking branch 'origin/master'

This commit is contained in:
Connor Drahoss 2022-09-10 11:37:23 -07:00
commit b64c34f8bd
23 changed files with 487 additions and 97 deletions

40
EPS.SDK/Caching/Cache.cs Normal file
View File

@ -0,0 +1,40 @@
using ExtensiblePortfolioSite.SDK.Resources;
using System;
using System.Collections.Generic;
namespace ExtensiblePortfolioSite.SDK.Caching
{
/// <summary>
/// Global Item Cache
/// </summary>
public static class Cache
{
internal static TimeSpan GitUserLifetime = TimeSpan.FromMinutes(1440);
internal static TimeSpan GitRepositoryLifetime = TimeSpan.FromMinutes(120);
private static readonly SortedDictionary<String, GitServiceCache> CacheLookup = new();
/// <summary>
/// Retrives the specified <see cref="GitServiceCache"/> for the given provider
/// </summary>
/// <param name="ServiceProvider">Git Service Provider Name</param>
/// <returns>Git Service Cache</returns>
public static GitServiceCache GetGitServiceCache(String ServiceProvider)
{
if (CacheLookup.TryGetValue(ServiceProvider, out GitServiceCache? cache))
return cache;
lock (CacheLookup)
{
if (CacheLookup.TryGetValue(ServiceProvider, out cache))
return cache;
ServiceProvider = string.Intern(ServiceProvider);
cache = new GitServiceCache(ServiceProvider);
CacheLookup.Add(ServiceProvider, cache);
return cache;
}
}
}
}

View File

@ -0,0 +1,16 @@
using ExtensiblePortfolioSite.SDK.Git;
using System;
namespace ExtensiblePortfolioSite.SDK.Caching
{
internal sealed class CacheRepo : GitCacheItemBase<IRepository>
{
private readonly Uri Repository;
internal CacheRepo(GitServiceCache Parent, Uri Repository) : base(Parent) => this.Repository = Repository;
protected override TimeSpan Lifetime => Cache.GitRepositoryLifetime;
protected override IRepository RetriveValue() => this.Parent.ServiceProvider.GetRepository(this.Repository);
}
}

View File

@ -0,0 +1,16 @@
using ExtensiblePortfolioSite.SDK.Git;
using System;
namespace ExtensiblePortfolioSite.SDK.Caching
{
internal sealed class CacheUser : GitCacheItemBase<IUser>
{
private readonly Uri User;
internal CacheUser(GitServiceCache Parent, Uri User) : base(Parent) => this.User = User;
protected override TimeSpan Lifetime => Cache.GitRepositoryLifetime;
protected override IUser RetriveValue() => this.Parent.ServiceProvider.GetUser(this.User);
}
}

View File

@ -0,0 +1,80 @@
using System;
namespace ExtensiblePortfolioSite.SDK.Caching
{
/// <summary>
/// Base Git Cache Item Class
/// </summary>
public abstract class GitCacheItemBase : IDisposable, ICacheItem
{
/// <summary>
/// the <see cref="GitServiceCache"/> this Item is bound to
/// </summary>
protected readonly GitServiceCache Parent;
/// <inheritdoc cref="GitCacheItemBase"/>
/// <param name="Parent"><see cref="GitServiceCache"/> that this Item is boud to</param>
public GitCacheItemBase(GitServiceCache Parent)
{
this.Parent = Parent;
Parent.Register(this);
}
///
~GitCacheItemBase() => this.Disposing();
/// <inheritdoc cref="ICacheItem.Invalidate"/>
public abstract void Invalidate();
/// <inheritdoc cref="IDisposable.Dispose"/>
public void Dispose()
{
GC.SuppressFinalize(this);
this.Disposing();
}
private void Disposing() => this.Parent.Unregister(this);
}
/// <summary>
/// Base Git Cache Item Class
/// </summary>
/// <typeparam name="T">Cache </typeparam>
public abstract class GitCacheItemBase<T> : GitCacheItemBase, ICacheItem<T>
{
private T CacheValue;
private DateTime RetrivedTime;
internal GitCacheItemBase(GitServiceCache Parent) : base(Parent)
{
this.RetrivedTime = DateTime.MinValue;
this.CacheValue = default!;
}
/// <inheritdoc cref="GitCacheItemBase.Invalidate"/>
public override void Invalidate()
{
this.CacheValue = default!;
this.RetrivedTime = DateTime.MinValue;
}
/// <inheritdoc cref="ICacheItem{T}.GetValue"/>
public T GetValue()
{
if (DateTime.Now - this.RetrivedTime > this.Lifetime)
{
this.CacheValue = RetriveValue();
this.RetrivedTime = DateTime.Now;
}
return this.CacheValue!;
}
/// <summary>
/// Get Expected Cache Item Lifetime
/// </summary>
protected abstract TimeSpan Lifetime { get; }
/// <summary>
/// Retrive the Cache Item
/// </summary>
/// <returns>Cache Item</returns>
protected abstract T RetriveValue();
}
}

View File

@ -0,0 +1,107 @@
using ExtensiblePortfolioSite.SDK.Git;
using System;
using System.Collections.Generic;
namespace ExtensiblePortfolioSite.SDK.Caching
{
/// <summary>
/// Git Service Cache Provider
/// </summary>
public sealed class GitServiceCache : IGitCacheProvider, IDisposable
{
/// <inheritdoc cref="IGitCacheProvider.ServiceProvider"/>
public GitService ServiceProvider { get; }
private readonly LinkedList<GitCacheItemBase> CacheItems = new();
private Boolean _disposing = false;
internal GitServiceCache(String Provider) : this(GitManager.GetService(Provider)) { }
internal GitServiceCache(GitService ServiceProvider)
{
this.ServiceProvider = ServiceProvider;
this.ServiceProvider.OnChange += ServiceProvider_OnChange;
}
private void ServiceProvider_OnChange(GitService Git)
{
lock(this.CacheItems)
{
foreach (GitCacheItemBase Item in this.CacheItems)
Item.Invalidate();
}
}
private readonly SortedDictionary<String, GitCacheItemBase<IUser>> UserCaches = new();
private readonly SortedDictionary<String, GitCacheItemBase<IRepository>> RepositoryCaches = new();
/// <inheritdoc cref="IGitCacheProvider.GetUser(Uri)"/>
public GitCacheItemBase<IUser> GetUser(Uri UserProfile)
{
String url = UserProfile.ToString();
if (UserCaches.TryGetValue(url, out GitCacheItemBase<IUser>? cache))
return cache;
lock (UserCaches)
{
if (UserCaches.TryGetValue(url, out cache))
return cache;
cache = new CacheUser(this, UserProfile);
UserCaches.Add(url, cache);
return cache;
}
}
/// <inheritdoc cref="IGitCacheProvider.GetRepository(Uri)"/>
public GitCacheItemBase<IRepository> GetRepository(Uri RepositoryURL)
{
String url = RepositoryURL.ToString();
if (RepositoryCaches.TryGetValue(url, out GitCacheItemBase<IRepository>? cache))
return cache;
lock (RepositoryCaches)
{
if (RepositoryCaches.TryGetValue(url, out cache))
return cache;
cache = new CacheRepo(this, RepositoryURL);
RepositoryCaches.Add(url, cache);
return cache;
}
}
/// <inheritdoc cref="ICacheProvider{GitCacheItemBase}.Register(GitCacheItemBase)"/>
public void Register(GitCacheItemBase CacheItem)
{
if (!_disposing)
lock (CacheItems)
{
this.CacheItems.AddFirst(CacheItem);
}
}
/// <inheritdoc cref="ICacheProvider{GitCacheItemBase}.Unregister(GitCacheItemBase)"/>
public void Unregister(GitCacheItemBase CacheItem)
{
if (!_disposing)
lock (CacheItems)
if (this.CacheItems.Remove(CacheItem)) ;
}
/// <inheritdoc cref="IDisposable"/>
public void Dispose()
{
_disposing = true;
lock (CacheItems)
{
this.ServiceProvider.OnChange -= ServiceProvider_OnChange;
this.RepositoryCaches.Clear();
this.UserCaches.Clear();
foreach (GitCacheItemBase Item in CacheItems)
Item.Dispose();
}
}
}
}

View File

@ -0,0 +1,79 @@
using ExtensiblePortfolioSite.SDK.Git;
using System;
namespace ExtensiblePortfolioSite.SDK.Caching
{
/// <summary>
/// Represents a Cache Item Provider
/// </summary>
/// <typeparam name="TCacheItemType">Cache Item Base Type</typeparam>
public interface ICacheProvider<TCacheItemType> where TCacheItemType : ICacheItem
{
/// <summary>
/// Registers a Cache Item
/// </summary>
/// <param name="Item"></param>
void Register(TCacheItemType Item);
/// <summary>
/// Unregisters a Cache Item
/// </summary>
/// <param name="Item"></param>
void Unregister(TCacheItemType Item);
}
/// <summary>
/// Represents a Cache Item
/// </summary>
public interface ICacheItem
{
/// <summary>
/// Invalidates the Cache Item
/// </summary>
void Invalidate();
}
/// <summary>
/// Represents a Cache Item of Type <typeparamref name="T"/>
/// </summary>
/// <typeparam name="T">Cache Item Type</typeparam>
public interface ICacheItem<T> : ICacheItem
{
/// <summary>
/// Gets the Requested Cache Item
/// </summary>
/// <returns></returns>
T GetValue();
}
/// <summary>
/// Git Cache Invalidate or Changed Delegate Callback
/// </summary>
public delegate void GitCacheInvalidateDelegate();
/// <summary>
/// A Git Cache Provider
/// </summary>
public interface IGitCacheProvider : ICacheProvider<GitCacheItemBase>
{
/// <summary>
/// The Service Provider tied to this Cache
/// </summary>
public GitService ServiceProvider { get; }
/// <summary>
/// Get a User by its URL
/// </summary>
/// <param name="UserProfile">User Profile URL</param>
/// <returns></returns>
public GitCacheItemBase<IUser> GetUser(Uri UserProfile);
/// <summary>
/// Get a Repositroy by its URL
/// </summary>
/// <param name="RepositoryURL">Repository URL</param>
/// <returns></returns>
public GitCacheItemBase<IRepository> GetRepository(Uri RepositoryURL);
}
}

View File

@ -1,4 +1,6 @@
using System; using ExtensiblePortfolioSite.SDK.Plugins;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace ExtensiblePortfolioSite.SDK.Git namespace ExtensiblePortfolioSite.SDK.Git
@ -7,34 +9,6 @@ namespace ExtensiblePortfolioSite.SDK.Git
{ {
private static readonly SortedDictionary<String, GitService> Providers = new(); private static readonly SortedDictionary<String, GitService> Providers = new();
public static void Register(String Service, IGitProvider Provider)
{
Console.WriteLine($"Registering service {Service}");
if (Providers.TryGetValue(Service, out GitService? GitService))
{
GitService.addProvider(Provider);
return;
}
lock (Providers)
{
if (Providers.TryGetValue(Service, out GitService))
{
GitService.addProvider(Provider);
return;
}
GitService = new GitService(Service);
GitService.addProvider(Provider);
Providers.Add(Service, GitService);
}
}
public static void Unregister(String Service, IGitProvider Provider)
{
if (Providers.TryGetValue(Service, out GitService? GitService))
GitService.removeProvider(Provider);
}
public static GitService GetService(String Website) => Providers[Website]; public static GitService GetService(String Website) => Providers[Website];
} }
} }

View File

@ -1,54 +1,99 @@
using System; using ExtensiblePortfolioSite.SDK.Caching;
using ExtensiblePortfolioSite.SDK.Plugins;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensiblePortfolioSite.SDK.Git namespace ExtensiblePortfolioSite.SDK.Git
{ {
internal class GitService /// <summary>
/// Git Service Changed Delegate/Callback
/// </summary>
/// <param name="Git">Sender</param>
public delegate void GitServiceChangedDelegate(GitService Git);
/// <summary>
/// Git Service
/// </summary>
public sealed class GitService
{ {
/// <summary>
/// Git Service Name
/// </summary>
public String Service { get; } public String Service { get; }
public GitService(String Service) /// <summary>
{ /// OnChanged Event Callback
this.Service = Service; /// </summary>
} public event GitServiceChangedDelegate? OnChange;
private readonly List<IGitProvider> Providers = new(); internal GitService(String Service) => this.Service = Service;
internal void removeProvider(IGitProvider provider) private readonly SortedDictionary<String, IGitProvider> Providers = new();
internal void I_RemoveProvider(Plugin FromPlugin, IGitProvider provider)
{ {
lock (this.Providers) lock (this.Providers)
this.Providers.Remove(provider); this.Providers.Add(FromPlugin.Info.Name, provider);
OnChange?.Invoke(this);
} }
internal void addProvider(IGitProvider provider) internal void I_AddProvider(Plugin FromPlugin, IGitProvider provider)
{ {
lock (this.Providers) lock (this.Providers)
this.Providers.Add(provider); this.Providers.Add(FromPlugin.Info.Name, provider);
OnChange?.Invoke(this);
} }
public IUser GetUser(Uri Path) private GitServiceCache? ServiceCache;
/// <summary>
/// Gets the Service Cache
/// </summary>
/// <returns></returns>
public GitServiceCache GetCache() => this.ServiceCache ??= Cache.GetGitServiceCache(this.Service);
/// <summary>
/// Attempt to Retrive a GitProvider by its PluginName
/// </summary>
/// <param name="PluginName"></param>
/// <param name="Provider"></param>
/// <returns></returns>
public void TryGetProviderByPlugin(String PluginName, out IGitProvider? Provider) => this.Providers.TryGetValue(PluginName, out Provider);
/// <summary>
/// Retrives a Specified User by URL
/// </summary>
/// <param name="URL"></param>
/// <returns></returns>
/// <exception cref="GitObjectNotFoundException"></exception>
public IUser GetUser(Uri URL)
{ {
lock (this.Providers) lock (this.Providers)
{ foreach (IGitProvider Provider in this.Providers.Values)
foreach(IGitProvider Provider in this.Providers) if (Provider.TryGetUserByURL(URL, out IUser? User))
if (Provider.TryGetUserByURL(Path, out IUser? User))
return User!; return User!;
throw new GitObjectNotFoundException(GitReferenceKind.User, Path); throw new GitObjectNotFoundException(GitReferenceKind.User, URL);
} }
}
public IRepository GetRepository(Uri Path) /// <summary>
/// Retrives a Specified Repository by URL
/// </summary>
/// <param name="URL"></param>
/// <returns></returns>
/// <exception cref="GitObjectNotFoundException"></exception>
public IRepository GetRepository(Uri URL)
{ {
lock (this.Providers) lock (this.Providers)
{ foreach (IGitProvider Provider in this.Providers.Values)
foreach (IGitProvider Provider in this.Providers) if (Provider.TryGetRepositoryByURL(URL, out IRepository? Repository))
if (Provider.TryGetRepositoryByURL(Path, out IRepository? Repository))
return Repository!; return Repository!;
throw new GitObjectNotFoundException(GitReferenceKind.User, Path); throw new GitObjectNotFoundException(GitReferenceKind.Repository, URL);
}
} }
} }
} }

View File

@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExtensiblePortfolioSite.SDK.Git namespace ExtensiblePortfolioSite.SDK.Git
{ {
@ -30,19 +26,19 @@ namespace ExtensiblePortfolioSite.SDK.Git
/// <summary> /// <summary>
/// Attempts to Get a User Profile by its Website URL /// Attempts to Get a User Profile by its Website URL
/// </summary> /// </summary>
public Boolean TryGetRepositoryByURL(Uri UserProfile, out IRepository? Repository); public Boolean TryGetRepositoryByURL(Uri URL, out IRepository? Repository);
/// <summary> /// <summary>
/// Get a User Profile by its Website URL /// Get a User Profile by its Website URL
/// </summary> /// </summary>
public IUser GetUserByURL(Uri UserProfile) => public IUser GetUserByURL(Uri URL) =>
TryGetUserByURL(UserProfile, out IUser? user) TryGetUserByURL(URL, out IUser? user)
? user! ? user!
: throw new GitObjectNotFoundException(GitReferenceKind.User, UserProfile); : throw new GitObjectNotFoundException(GitReferenceKind.User, URL);
/// <summary> /// <summary>
/// Attempts to Get a User Profile by its Website URL /// Attempts to Get a User Profile by its Website URL
/// </summary> /// </summary>
public Boolean TryGetUserByURL(Uri UserProfile, out IUser? User); public Boolean TryGetUserByURL(Uri URL, out IUser? User);
} }
} }

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Threading; using System.Threading;

View File

@ -9,6 +9,7 @@ using System.Text.Json.Serialization;
namespace ExtensiblePortfolioSite.SDK.Plugins namespace ExtensiblePortfolioSite.SDK.Plugins
{ {
internal delegate void PluginUnloadDelegate(Plugin plugin);
internal class Plugin : IPluginManagedLibrary internal class Plugin : IPluginManagedLibrary
{ {
private class PluginLoadContext : AssemblyLoadContext private class PluginLoadContext : AssemblyLoadContext
@ -42,6 +43,8 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
public Assembly Assembly { get; private set; } public Assembly Assembly { get; private set; }
public EPSPluginAttribute Info { get; private set; } public EPSPluginAttribute Info { get; private set; }
public event PluginUnloadDelegate? OnUnloading;
public IList<IPluginLibrary> Dependents { get; } = new List<IPluginLibrary>(); public IList<IPluginLibrary> Dependents { get; } = new List<IPluginLibrary>();
IReadOnlyList<IPluginLibrary> IPluginLibrary.References => References.AsReadOnly(); IReadOnlyList<IPluginLibrary> IPluginLibrary.References => References.AsReadOnly();
public List<IPluginLibrary> References = new(); public List<IPluginLibrary> References = new();
@ -58,8 +61,8 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
} }
private readonly List<JsonConverter> JsonConverters = new(); private readonly List<JsonConverter> JsonConverters = new();
private readonly List<KeyValuePair<Type, String[]>> ResourceContainers = new(); private readonly Dictionary<Type, String[]> ResourceContainers = new();
private readonly List<KeyValuePair<String, IGitProvider>> GitProviders = new(); private readonly Dictionary<GitService, IGitProvider> GitProviders = new();
public void Init() public void Init()
{ {
if (Initialized) if (Initialized)
@ -76,8 +79,9 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
if (t.IsAssignableTo(typeof(IGitProvider)) && t.GetConstructor(Type.EmptyTypes) != null) if (t.IsAssignableTo(typeof(IGitProvider)) && t.GetConstructor(Type.EmptyTypes) != null)
if (Activator.CreateInstance(t, true) is IGitProvider Provider) if (Activator.CreateInstance(t, true) is IGitProvider Provider)
{ {
GitManager.Register(GitProviderAttr.ServiceName, Provider); GitService Service = GitManager.GetService(GitProviderAttr.ServiceName);
GitProviders.Add(new(GitProviderAttr.ServiceName, Provider)); GitProviders.Add(Service, Provider);
Service.I_AddProvider(this, Provider);
} }
else else
PluginManager.LogMessage(PluginErrorSeverity.Error, this, "Failed to Instantiate GitProvider", t, null); PluginManager.LogMessage(PluginErrorSeverity.Error, this, "Failed to Instantiate GitProvider", t, null);
@ -105,13 +109,14 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
{ {
try try
{ {
ResourceContainers.Add(t, ResourceContainerAttr.Schemes);
ResourceManager.Register(t, ResourceContainerAttr.Schemes); ResourceManager.Register(t, ResourceContainerAttr.Schemes);
ResourceContainers.Add(new(t, ResourceContainerAttr.Schemes));
} }
catch (Exception ex) catch (Exception ex)
{ {
PluginManager.LogMessage(PluginErrorSeverity.Fatal, this, "Faield to Create ResoruceContainer Factory", t, ex); PluginManager.LogMessage(PluginErrorSeverity.Fatal, this, "Failed to Create ResoruceContainer Factory", t, ex);
throw new Exception("Runtime Unstable!", ex); Console.Error.WriteLine("Runtime Unstable, Exitting!");
Environment.Exit(5);
} }
} }
else else
@ -122,8 +127,10 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
public void Disposing() public void Disposing()
{ {
foreach (KeyValuePair<String, IGitProvider> provider in GitProviders) OnUnloading?.Invoke(this);
GitManager.Unregister(provider.Key, provider.Value);
foreach (KeyValuePair<GitService, IGitProvider> provider in GitProviders)
provider.Key.I_RemoveProvider(this, provider.Value);
this.GitProviders.Clear(); this.GitProviders.Clear();
foreach (KeyValuePair<Type, String[]> resourceContainer in ResourceContainers) foreach (KeyValuePair<Type, String[]> resourceContainer in ResourceContainers)

View File

@ -55,10 +55,8 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
Directory.CreateDirectory(RootPath); Directory.CreateDirectory(RootPath);
LibraryPaths.Add(RootPath); LibraryPaths.Add(RootPath);
foreach (String Dll in Directory.EnumerateFiles(RootPath, "*.dll", SearchOption.TopDirectoryOnly)) foreach (String Dll in Directory.EnumerateFiles(RootPath, "*.dll", SearchOption.TopDirectoryOnly))
{
TryLoadPlugin(Path.GetFullPath(Dll, RootPath), out Plugin? _); TryLoadPlugin(Path.GetFullPath(Dll, RootPath), out Plugin? _);
} }
}
public static Boolean TryLoadPlugin(string AsmPath, out Plugin? plugin) public static Boolean TryLoadPlugin(string AsmPath, out Plugin? plugin)
{ {
if (!File.Exists(AsmPath)) goto error; if (!File.Exists(AsmPath)) goto error;
@ -380,5 +378,15 @@ namespace ExtensiblePortfolioSite.SDK.Plugins
// we want to throw when its trying to load something we don't explicitly allow! // we want to throw when its trying to load something we don't explicitly allow!
throw new FileNotFoundException($"Unable to Load Assembly '{Name}'"); throw new FileNotFoundException($"Unable to Load Assembly '{Name}'");
} }
internal static Plugin? ResolveTypeToPlugin(Type type)
{
String fname = type.Assembly.GetName().FullName;
lock (_plugins)
foreach (Plugin plugin in _plugins)
if (plugin.Assembly.GetName().FullName == fname)
return plugin;
return null;
}
} }
} }

View File

@ -1,6 +1,7 @@
using ExtensiblePortfolioSite.SDK; using ExtensiblePortfolioSite.SDK;
using ExtensiblePortfolioSite.SDK.Caching;
using ExtensiblePortfolioSite.SDK.Git;
using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace ExtensiblePortfolioSite namespace ExtensiblePortfolioSite
@ -111,6 +112,8 @@ namespace ExtensiblePortfolioSite
if (Repository == null) throw new Exception("GitRepo Repository missing!"); if (Repository == null) throw new Exception("GitRepo Repository missing!");
if (Description == null) throw new Exception("GitRepo Description missing!"); if (Description == null) throw new Exception("GitRepo Description missing!");
} }
public IRepository Resolve() => GitManager.GetService(this.ServiceProvider).GetRepository(this.Repository);
} }
[Serializable] [Serializable]
@ -138,10 +141,6 @@ namespace ExtensiblePortfolioSite
[Serializable] [Serializable]
public class Cache public class Cache
{ {
[JsonPropertyName("GitCommit")]
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public Int32 GitCommit = 30;
[JsonPropertyName("GitRepo")] [JsonPropertyName("GitRepo")]
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
public Int32 GitRepo = 120; public Int32 GitRepo = 120;
@ -196,6 +195,10 @@ namespace ExtensiblePortfolioSite
Conf = Json.Deserialize<ConfigObject>(File.ReadAllText(ConfigFile)); Conf = Json.Deserialize<ConfigObject>(File.ReadAllText(ConfigFile));
if (Conf == null) if (Conf == null)
throw new Exception("Failed to Load Config!"); throw new Exception("Failed to Load Config!");
// Load Config
Cache.GitUserLifetime = TimeSpan.FromMinutes(Conf.CacheSection.GitUser);
Cache.GitRepositoryLifetime = TimeSpan.FromMinutes(Conf.CacheSection.GitRepo);
} }
} }
} }

View File

@ -27,8 +27,12 @@
<None Include="Pages\Projects\Index.cshtml" /> <None Include="Pages\Projects\Index.cshtml" />
</ItemGroup> </ItemGroup>
<Folder Include="logs\" />
<Folder Include="Plugins\" />
</ItemGroup>
<ItemGroup>
<Target Name="IncludePlugins" BeforeTargets="AfterBuild"> <Target Name="IncludePlugins" BeforeTargets="AfterBuild">
<MSBuild Projects="..\GithubPlugin\GithubPlugin.csproj" BuildInParallel="$(BuildInParallel)" Targets="Build"> <MSBuild Projects="..\GithubPlugin\GithubPlugin.csproj" BuildInParallel="$(BuildInParallel)" Targets="Rebuild">
</MSBuild> </MSBuild>
<Copy SourceFiles="$(SolutionDir)GithubPlugin\bin\$(Configuration)\net6.0\GithubPlugin.dll" DestinationFolder="Plugins/" SkipUnchangedFiles="true" /> <Copy SourceFiles="$(SolutionDir)GithubPlugin\bin\$(Configuration)\net6.0\GithubPlugin.dll" DestinationFolder="Plugins/" SkipUnchangedFiles="true" />
</Target> </Target>

View File

@ -25,14 +25,14 @@ namespace ExtensiblePortfolioSite
{ {
this.Parent = Parent; this.Parent = Parent;
this.Identifier = Identifier; this.Identifier = Identifier;
lock (this.Parent.ScopeStack)
this.Parent.ScopeStack.AddLast(this); this.Parent.ScopeStack.AddLast(this);
} }
public void Dispose() public void Dispose()
{ {
// we shouldn't need this but we evidently do... lock (this.Parent.ScopeStack)
// some form of race condition is causing a null ref Exception this.Parent.ScopeStack.Remove(this);
try { this.Parent.ScopeStack.Remove(this); } catch { }
} }
} }

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ExtensiblePortfolioSite.Pages.About namespace ExtensiblePortfolioSite.Pages.About
{ {
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = false)]
public class AboutModel : PageModel public class AboutModel : PageModel
{ {
public void OnGet() public void OnGet()

View File

@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ExtensiblePortfolioSite.Pages namespace ExtensiblePortfolioSite.Pages
{ {
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = false)]
public class IndexModel : PageModel public class IndexModel : PageModel
{ {
private readonly ILogger<IndexModel> _logger; private readonly ILogger<IndexModel> _logger;

View File

@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ExtensiblePortfolioSite.Pages namespace ExtensiblePortfolioSite.Pages
{ {
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = false)]
public class ProjectsModel : PageModel public class ProjectsModel : PageModel
{ {
private readonly ILogger<IndexModel> _logger; private readonly ILogger<IndexModel> _logger;

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ExtensiblePortfolioSite.Pages.Socials namespace ExtensiblePortfolioSite.Pages.Socials
{ {
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, NoStore = false)]
public class SocialsModel : PageModel public class SocialsModel : PageModel
{ {
public void OnGet() public void OnGet()

View File

@ -93,12 +93,14 @@ namespace ExtensiblePortfolioSite
// TODO: [Plugin] Web Static Files Provider // TODO: [Plugin] Web Static Files Provider
// TODO: [Plugin] Web Hook Provider // TODO: [Plugin] Web Hook Provider
// TODO: [Plugin] API Endpoint Provider // TODO: [Plugin] API Endpoint Provider
// TODO: [Plugin] Standard Cache Provider
// TODO: [Plugin] Reloading/Updating/Disabling // TODO: [Plugin] Reloading/Updating/Disabling
// Add services to the container. // Add services to the container.
builder.Services.AddRazorPages(); builder.Services.AddRazorPages();
// Add Responce Cache
builder.Services.AddResponseCaching();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -115,6 +117,8 @@ namespace ExtensiblePortfolioSite
app.UseRouting(); app.UseRouting();
app.UseResponseCaching();
//app.UseAuthorization(); // not needed //app.UseAuthorization(); // not needed
app.MapRazorPages(); app.MapRazorPages();

View File

@ -7,6 +7,13 @@
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
"applicationUrl": "https://localhost:58428;http://localhost:58429" "applicationUrl": "https://localhost:58428;http://localhost:58429"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
"publishAllPorts": true,
"useSSL": true
} }
} }
} }

View File

@ -78,7 +78,6 @@
// Caching Options // Caching Options
"Cache": { "Cache": {
// Lifetimes given in minutes (0 = disabled) // Lifetimes given in minutes (0 = disabled)
"GitCommit": 30, //30m
"GitRepo": 120, //2h "GitRepo": 120, //2h
"GitUser": 1440 //1d "GitUser": 1440 //1d
} }

View File

@ -147,5 +147,6 @@ namespace GithubPlugin
{ {
return httpClient.GetAsync(resourceLocation).Result; return httpClient.GetAsync(resourceLocation).Result;
} }
} }
} }