mirror of
https://github.com/sphildreth/roadie
synced 2024-11-10 06:44:12 +00:00
WIP
This commit is contained in:
parent
a4c41e983d
commit
3590f87e43
11 changed files with 185 additions and 47 deletions
|
@ -19,7 +19,7 @@ namespace Roadie.Api.Controllers
|
|||
[Produces("application/json")]
|
||||
[Route("image")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
// [Authorize]
|
||||
public class ImageController : EntityControllerBase
|
||||
{
|
||||
private IImageService ImageService { get; }
|
||||
|
@ -37,29 +37,6 @@ namespace Roadie.Api.Controllers
|
|||
// return Ok(this._RoadieDbContext.Tracks.ProjectToType<models.Image>());
|
||||
//}
|
||||
|
||||
//[HttpGet("{id}")]
|
||||
//[ProducesResponseType(200)]
|
||||
//[ProducesResponseType(404)]
|
||||
//public IActionResult Get(Guid id)
|
||||
//{
|
||||
// var key = id.ToString();
|
||||
// var result = this._cacheManager.Get<models.Image>(key, () =>
|
||||
// {
|
||||
// var d = this._RoadieDbContext.Images.FirstOrDefault(x => x.RoadieId == id);
|
||||
// if (d != null)
|
||||
// {
|
||||
// return d.Adapt<models.Image>();
|
||||
// }
|
||||
// return null;
|
||||
// }, key);
|
||||
// if (result == null)
|
||||
// {
|
||||
// return NotFound();
|
||||
// }
|
||||
// return Ok(result);
|
||||
//}
|
||||
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[ProducesResponseType(200)]
|
||||
[ProducesResponseType(404)]
|
||||
|
@ -77,7 +54,7 @@ namespace Roadie.Api.Controllers
|
|||
}
|
||||
return File(fileContents:result.Data.Bytes,
|
||||
contentType: result.ContentType,
|
||||
fileDownloadName: result.Data.Caption ?? id.ToString(),
|
||||
fileDownloadName: $"{ result.Data.Caption ?? id.ToString()}.jpg",
|
||||
lastModified: result.LastModified,
|
||||
entityTag: result.ETag);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ using Roadie.Library;
|
|||
using Roadie.Library.Caching;
|
||||
using Roadie.Library.Configuration;
|
||||
using Roadie.Library.Encoding;
|
||||
using Roadie.Library.Extensions;
|
||||
using Roadie.Library.Imaging;
|
||||
using Roadie.Library.Models;
|
||||
using Roadie.Library.Utility;
|
||||
using System;
|
||||
|
@ -31,21 +33,25 @@ namespace Roadie.Api.Services
|
|||
public async Task<FileOperationResult<Image>> ImageById(Guid id, int? width, int? height, EntityTagHeaderValue etag = null)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
sw.Start();
|
||||
var cacheKey = string.Format("urn:image_by_id_operation:{0}", id);
|
||||
var result = await this.CacheManager.GetAsync<FileOperationResult<Image>>(cacheKey, async () =>
|
||||
var result = (await this.CacheManager.GetAsync($"urn:image_by_id_operation:{id}", async () =>
|
||||
{
|
||||
return await this.ImageByIdAction(id, etag);
|
||||
}, data.Image.CacheRegionKey(id));
|
||||
|
||||
}, data.Image.CacheRegionKey(id))).Adapt<FileOperationResult<Image>>();
|
||||
if (result.ETag == etag)
|
||||
{
|
||||
return new FileOperationResult<Image>(OperationMessages.NotModified);
|
||||
}
|
||||
if ((width.HasValue || height.HasValue) && result?.Data?.Bytes != null)
|
||||
{
|
||||
result.Data.Bytes = ImageHelper.ResizeImage(result?.Data?.Bytes, width.Value, height.Value);
|
||||
result.ETag = EtagHelper.GenerateETag(this.HttpEncoder, result.Data.Bytes);
|
||||
result.LastModified = DateTime.UtcNow;
|
||||
this.Logger.LogInformation($"ImageById: Resized [{ id }], Width [{ width.Value }], Height [{ height.Value }]");
|
||||
}
|
||||
sw.Stop();
|
||||
return new FileOperationResult<Image>(result.Messages)
|
||||
{
|
||||
Data = result?.Data,
|
||||
Data = result.Data,
|
||||
ETag = result.ETag,
|
||||
LastModified = result.LastModified,
|
||||
ContentType = result.ContentType,
|
||||
|
|
|
@ -61,8 +61,6 @@ namespace Roadie.Api
|
|||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
loggerFactory.AddConsole(LogLevel.Trace);
|
||||
|
||||
app.UseCors("Cors");
|
||||
app.UseAuthentication();
|
||||
//app.UseSwagger();
|
||||
|
@ -93,7 +91,7 @@ namespace Roadie.Api
|
|||
|
||||
services.AddSingleton<IHttpEncoder, HttpEncoder>();
|
||||
|
||||
var cacheManager = new MemoryCacheManager(this._loggerFactory.CreateLogger<MemoryCacheManager>(), new CachePolicy(TimeSpan.FromHours(4)));
|
||||
var cacheManager = new DictionaryCacheManager(this._loggerFactory.CreateLogger<DictionaryCacheManager>(), new CachePolicy(TimeSpan.FromHours(4)));
|
||||
services.AddSingleton<ICacheManager>(cacheManager);
|
||||
|
||||
services.AddDbContextPool<ApplicationUserDbContext>(
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
"IncludeScopes": false,
|
||||
"Console": {
|
||||
"LogLevel": {
|
||||
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
|
||||
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
|
||||
"Microsoft.AspNetCore.Mvc.Razor": "Error",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Microsoft.EntityFrameworkCore": "Warning",
|
||||
"Default": "Trace"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace Roadie.Library.Caching
|
|||
public abstract class CacheManagerBase : ICacheManager
|
||||
{
|
||||
protected readonly CachePolicy _defaultPolicy = null;
|
||||
protected readonly ILogger _logger = null;
|
||||
protected ILogger Logger { get; }
|
||||
protected readonly JsonSerializerSettings _serializerSettings = null;
|
||||
|
||||
public CacheManagerBase(ILogger logger, CachePolicy defaultPolicy)
|
||||
{
|
||||
this._logger = logger;
|
||||
this.Logger = logger;
|
||||
this._defaultPolicy = defaultPolicy;
|
||||
this._serializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ namespace Roadie.Library.Caching
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this._logger.LogError(ex, null, null);
|
||||
this.Logger.LogError(ex, null, null);
|
||||
}
|
||||
return default(TOut);
|
||||
}
|
||||
|
|
119
RoadieLibrary/Caching/DictionaryCacheManager.cs
Normal file
119
RoadieLibrary/Caching/DictionaryCacheManager.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roadie.Library.Caching
|
||||
{
|
||||
public class DictionaryCacheManager : CacheManagerBase
|
||||
{
|
||||
private Dictionary<string, object> Cache { get; }
|
||||
|
||||
public DictionaryCacheManager(ILogger logger, CachePolicy defaultPolicy)
|
||||
: base(logger, defaultPolicy)
|
||||
{
|
||||
this.Cache = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
public override bool Add<TCacheValue>(string key, TCacheValue value)
|
||||
{
|
||||
if(this.Cache.ContainsKey(key))
|
||||
{
|
||||
this.Cache.Remove(key);
|
||||
}
|
||||
this.Cache.Add(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Add<TCacheValue>(string key, TCacheValue value, string region)
|
||||
{
|
||||
return this.Add(key, value);
|
||||
}
|
||||
|
||||
public override bool Add<TCacheValue>(string key, TCacheValue value, CachePolicy policy)
|
||||
{
|
||||
return this.Add(key, value);
|
||||
}
|
||||
|
||||
public override bool Add<TCacheValue>(string key, TCacheValue value, string region, CachePolicy policy)
|
||||
{
|
||||
return this.Add(key, value);
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
this.Cache.Clear();
|
||||
}
|
||||
|
||||
public override void ClearRegion(string region)
|
||||
{
|
||||
this.Clear();
|
||||
}
|
||||
|
||||
public override bool Exists<TOut>(string key)
|
||||
{
|
||||
return this.Cache.ContainsKey(key);
|
||||
}
|
||||
|
||||
public override bool Exists<TOut>(string key, string region)
|
||||
{
|
||||
return this.Exists<TOut>(key);
|
||||
}
|
||||
|
||||
public override TOut Get<TOut>(string key)
|
||||
{
|
||||
if(!this.Cache.ContainsKey(key))
|
||||
{
|
||||
return default(TOut);
|
||||
}
|
||||
return (TOut)this.Cache[key];
|
||||
}
|
||||
|
||||
public override TOut Get<TOut>(string key, string region)
|
||||
{
|
||||
return Get<TOut>(key);
|
||||
}
|
||||
|
||||
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region)
|
||||
{
|
||||
return Get<TOut>(key);
|
||||
}
|
||||
|
||||
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region, CachePolicy policy)
|
||||
{
|
||||
return Get<TOut>(key);
|
||||
}
|
||||
|
||||
public override bool Remove(string key)
|
||||
{
|
||||
if(this.Cache.ContainsKey(key))
|
||||
{
|
||||
this.Cache.Remove(key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Remove(string key, string region)
|
||||
{
|
||||
return this.Remove(key);
|
||||
}
|
||||
|
||||
public async override Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
|
||||
{
|
||||
var r = this.Get<TOut>(key, region);
|
||||
if (r == null)
|
||||
{
|
||||
r = await getItem();
|
||||
this.Add(key, r, region);
|
||||
this.Logger.LogInformation($"-+> Cache Miss for Key [{ key }], Region [{ region }]");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Logger.LogInformation($"-!> Cache Hit for Key [{ key }], Region [{ region }]");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,11 +106,11 @@ namespace Roadie.Library.Caching
|
|||
{
|
||||
r = await getItem();
|
||||
this.Add(key, r, region);
|
||||
Trace.WriteLine($"-+> Cache Miss for Key [{ key }], Region [{ region }]");
|
||||
this.Logger.LogInformation($"-+> Cache Miss for Key [{ key }], Region [{ region }]");
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.WriteLine($"-!> Cache Hit for Key [{ key }], Region [{ region }]");
|
||||
this.Logger.LogInformation($"-!> Cache Hit for Key [{ key }], Region [{ region }]");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace Roadie.Library.Caching
|
|||
{
|
||||
if (this._doTraceLogging)
|
||||
{
|
||||
this._logger.LogTrace("Added [{0}], Region [{1}]", key, region);
|
||||
this.Logger.LogTrace("Added [{0}], Region [{1}]", key, region);
|
||||
}
|
||||
return this.Redis.StringSet(key, this.Serialize(value));
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace Roadie.Library.Caching
|
|||
server.FlushAllDatabases();
|
||||
if (this._doTraceLogging)
|
||||
{
|
||||
this._logger.LogTrace("Cleared Cache");
|
||||
this.Logger.LogTrace("Cleared Cache");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,12 +156,12 @@ namespace Roadie.Library.Caching
|
|||
{
|
||||
if (this._doTraceLogging)
|
||||
{
|
||||
this._logger.LogTrace("Get Cache Miss Key [{0}], Region [{1}]", key, region);
|
||||
this.Logger.LogTrace("Get Cache Miss Key [{0}], Region [{1}]", key, region);
|
||||
}
|
||||
}
|
||||
else if (this._doTraceLogging)
|
||||
{
|
||||
this._logger.LogTrace("Get Cache Hit Key [{0}], Region [{1}]", key, region);
|
||||
this.Logger.LogTrace("Get Cache Hit Key [{0}], Region [{1}]", key, region);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace Roadie.Library.Extensions
|
||||
{
|
||||
|
@ -19,5 +23,35 @@ namespace Roadie.Library.Extensions
|
|||
|
||||
return OriginalEntity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a deep Copy of the object using a BinaryFormatter.
|
||||
/// IMPORTANT: the object class must be marked as [Serializable] and have an parameterless constructor.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of object being copied.</typeparam>
|
||||
/// <param name="source">The object instance to copy.</param>
|
||||
/// <returns>The copied object.</returns>
|
||||
public static T Clone<T>(this T source)
|
||||
{
|
||||
if (!typeof(T).IsSerializable)
|
||||
{
|
||||
throw new ArgumentException("The type must be serializable.", "source");
|
||||
}
|
||||
|
||||
// Don't serialize a null object, simply return the default for that object
|
||||
if (Object.ReferenceEquals(source, null))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
IFormatter formatter = new BinaryFormatter();
|
||||
using (Stream stream = new MemoryStream())
|
||||
{
|
||||
formatter.Serialize(stream, source);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return (T)formatter.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@ namespace Roadie.Library
|
|||
public DateTimeOffset? LastModified { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public FileOperationResult()
|
||||
{
|
||||
}
|
||||
|
||||
public FileOperationResult(string message)
|
||||
{
|
||||
this.AddMessage(message);
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
|
||||
namespace Roadie.Library
|
||||
{
|
||||
[Serializable]
|
||||
public class OperationResult<T>
|
||||
{
|
||||
private List<Exception> _errors;
|
||||
|
|
Loading…
Reference in a new issue