caching for banners and images
This commit is contained in:
parent
afb21e566a
commit
36f54a0c95
@ -9,69 +9,5 @@
|
||||
"AllowedHosts": "*",
|
||||
"GoogleAnalyticsCode": "",
|
||||
"APIRoot": "http://localhost:3439",
|
||||
"GlobalAPIRoot": "https://ganjgah.ir",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=museum;Trusted_Connection=True;MultipleActiveResultSets=true"
|
||||
},
|
||||
"PictureFileService": {
|
||||
"StoragePath": "C:\\museum",
|
||||
"ResizedImageContentType": "image/jpeg",
|
||||
"NormalImageMaxWidth": "800",
|
||||
"NormalImageMaxHeight": "1350",
|
||||
"ThumbnailImageWidth": "300",
|
||||
"ThumbnailMaxHeight": "500"
|
||||
},
|
||||
"Security": {
|
||||
"Secret": "k4Fy7pDsc0LgXQ8PCCfZtwmju5Ed8asc",
|
||||
"DefaultTokenExpirationInSeconds": "3600"
|
||||
},
|
||||
"SmptConfig": {
|
||||
"Server": "smtp.gmail.com",
|
||||
"Port": "587",
|
||||
"UseSsl": "true",
|
||||
"UseTls": "true",
|
||||
"Username": "test@gmail.com",
|
||||
"Password": "password",
|
||||
"From": "test@gmail.com"
|
||||
},
|
||||
"LocalSqliteImport": {
|
||||
"FilePath": "C:\\Users\\moham\\AppData\\Local\\ganjoor\\ganjoor\\ganjoor.s3db"
|
||||
},
|
||||
"IIS": {
|
||||
"UploadLimit": "52428800"
|
||||
},
|
||||
"AudioMySqlServer": {
|
||||
"Server": "localhost",
|
||||
"Username": "root",
|
||||
"Password": "",
|
||||
"Database": "adab",
|
||||
"2ndDatabase": "audio",
|
||||
"2ndUsername": "audio",
|
||||
"2ndPassword": "",
|
||||
"SongsDatabase": "golha",
|
||||
"SongsUsername": "root",
|
||||
"SongsPassword": "",
|
||||
"ReportedCommentsDatabase": "rpcmnts",
|
||||
"ReportedCommentsUsername": "root",
|
||||
"ReportedCommentsPassword": "",
|
||||
"PoetImagesImportPath": "C:\\Users\\moham\\source\\repos\\GanjooRazor\\wwwroot\\image\\poets"
|
||||
},
|
||||
"AudioSFPServer": {
|
||||
"Host": "localhost",
|
||||
"Port": "22",
|
||||
"Username": "root",
|
||||
"Password": "",
|
||||
"RootPath": "/home"
|
||||
},
|
||||
"AudioUploadService": {
|
||||
"Enabled": "True",
|
||||
"TempUploadPath": "C:\\tempaudio",
|
||||
"LocalAudioRepositoryPath": "D:\\My Documents\\My Web Design\\ganjoor\\www\\i",
|
||||
"CurrentSoundFilesFolder": "a2"
|
||||
},
|
||||
"SignUp": {
|
||||
"Enabled": "True",
|
||||
"VerifyEmail": "True"
|
||||
}
|
||||
|
||||
"GlobalAPIRoot": "http://localhost:3439"
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RSecurityBackend.Services;
|
||||
using RSecurityBackend.Controllers;
|
||||
using Audit.WebApi;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace RMuseum.Controllers
|
||||
{
|
||||
@ -13,12 +12,12 @@ namespace RMuseum.Controllers
|
||||
[Route("api/rimages")]
|
||||
public class RImageController : RImageControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="pictureFileService">
|
||||
/// </param>
|
||||
public RImageController(IImageFileService pictureFileService) : base(pictureFileService)
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="pictureFileService"></param>
|
||||
/// <param name="memoryCache"></param>
|
||||
public RImageController(IImageFileService pictureFileService, IMemoryCache memoryCache) : base(pictureFileService, memoryCache)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -1225,12 +1225,12 @@
|
||||
Generic Image Provider
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:RMuseum.Controllers.RImageController.#ctor(RSecurityBackend.Services.IImageFileService)">
|
||||
<member name="M:RMuseum.Controllers.RImageController.#ctor(RSecurityBackend.Services.IImageFileService,Microsoft.Extensions.Caching.Memory.IMemoryCache)">
|
||||
<summary>
|
||||
constructor
|
||||
</summary>
|
||||
<param name="pictureFileService">
|
||||
</param>
|
||||
<param name="pictureFileService"></param>
|
||||
<param name="memoryCache"></param>
|
||||
</member>
|
||||
<member name="T:RMuseum.Controllers.RLongRunningJobsController">
|
||||
<summary>
|
||||
|
||||
@ -38,7 +38,6 @@ namespace RMuseum.Services.Implementation
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>(null, image.ExceptionString);
|
||||
}
|
||||
|
||||
|
||||
GanjoorSiteBanner banner = new GanjoorSiteBanner()
|
||||
{
|
||||
RImage = image.Result,
|
||||
@ -50,6 +49,8 @@ namespace RMuseum.Services.Implementation
|
||||
_context.GanjoorSiteBanners.Add(banner);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
await CleanBannersCache();
|
||||
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>
|
||||
(
|
||||
new GanjoorSiteBannerViewModel()
|
||||
@ -93,6 +94,8 @@ namespace RMuseum.Services.Implementation
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
await CleanBannersCache();
|
||||
|
||||
return new RServiceResult<bool>(true);
|
||||
|
||||
}
|
||||
@ -119,6 +122,8 @@ namespace RMuseum.Services.Implementation
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
await CleanBannersCache();
|
||||
|
||||
return new RServiceResult<bool>(true);
|
||||
|
||||
}
|
||||
@ -154,6 +159,30 @@ namespace RMuseum.Services.Implementation
|
||||
}
|
||||
}
|
||||
|
||||
private const string _cacheKeyForIdSet = "SiteBannersService::GetARandomActiveSiteBanner::idSet";
|
||||
|
||||
private static string GetBannerCacheKey(int bannerId)
|
||||
{
|
||||
return $"SiteBannersService::BannerCacheKey::{bannerId}";
|
||||
}
|
||||
|
||||
private async Task CleanBannersCache()
|
||||
{
|
||||
int[] idSet = await _context.GanjoorSiteBanners.Select(b => b.Id).ToArrayAsync();
|
||||
foreach(int id in idSet)
|
||||
{
|
||||
var cacheKey = GetBannerCacheKey(id);
|
||||
if(_memoryCache.TryGetValue(id, out GanjoorSiteBannerViewModel o))
|
||||
{
|
||||
_memoryCache.Remove(id);
|
||||
}
|
||||
}
|
||||
if (_memoryCache.TryGetValue(_cacheKeyForIdSet, out idSet))
|
||||
{
|
||||
_memoryCache.Remove(_cacheKeyForIdSet);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// get a random site banner
|
||||
/// </summary>
|
||||
@ -162,30 +191,37 @@ namespace RMuseum.Services.Implementation
|
||||
{
|
||||
try
|
||||
{
|
||||
var cacheKeyForIdSet = $"GetARandomActiveSiteBanner::idSet";
|
||||
if (!_memoryCache.TryGetValue(cacheKeyForIdSet, out int[] idSet))
|
||||
if (!_memoryCache.TryGetValue(_cacheKeyForIdSet, out int[] idSet))
|
||||
{
|
||||
idSet = await _context.GanjoorSiteBanners.Where(b => b.Active == true).Select(b => b.Id).ToArrayAsync();
|
||||
_memoryCache.Set(cacheKeyForIdSet, idSet);
|
||||
_memoryCache.Set(_cacheKeyForIdSet, idSet);
|
||||
}
|
||||
if (idSet.Length == 0)
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>(null);//not found
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>(null);//no active banner
|
||||
|
||||
Random rnd = new Random(DateTime.Now.Millisecond);
|
||||
int id = idSet[rnd.Next(0, idSet.Length)];
|
||||
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>(
|
||||
await _context.GanjoorSiteBanners
|
||||
.Where(b => b.Id == id)
|
||||
.Select(b => new GanjoorSiteBannerViewModel()
|
||||
{
|
||||
Id = b.Id,
|
||||
ImageUrl = $"api/rimages/{b.RImageId}.jpg",
|
||||
AlternateText = b.AlternateText,
|
||||
TargetUrl = b.TargetUrl,
|
||||
Active = b.Active
|
||||
}).AsNoTracking().SingleAsync()
|
||||
);
|
||||
var cachKey = GetBannerCacheKey(id);
|
||||
if (!_memoryCache.TryGetValue(cachKey, out GanjoorSiteBannerViewModel banner))
|
||||
{
|
||||
banner =
|
||||
await _context.GanjoorSiteBanners
|
||||
.Where(b => b.Id == id)
|
||||
.Select(b => new GanjoorSiteBannerViewModel()
|
||||
{
|
||||
Id = b.Id,
|
||||
ImageUrl = $"api/rimages/{b.RImageId}.jpg",
|
||||
AlternateText = b.AlternateText,
|
||||
TargetUrl = b.TargetUrl,
|
||||
Active = b.Active
|
||||
})
|
||||
.AsNoTracking()
|
||||
.SingleAsync();
|
||||
_memoryCache.Set(cachKey, banner);
|
||||
}
|
||||
|
||||
return new RServiceResult<GanjoorSiteBannerViewModel>(banner);
|
||||
|
||||
}
|
||||
catch (Exception exp)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using RSecurityBackend.Models.Auth.Memory;
|
||||
using RSecurityBackend.Models.Generic;
|
||||
using RSecurityBackend.Models.Image;
|
||||
@ -30,30 +31,45 @@ namespace RSecurityBackend.Controllers
|
||||
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
|
||||
public async Task<IActionResult> Get(Guid id)
|
||||
{
|
||||
RServiceResult<RImage> img =
|
||||
await _pictureFileService.GetImage(id);
|
||||
var cachKey = $"RImageControllerBase::RImage::{id}";
|
||||
if(!_memoryCache.TryGetValue(cachKey, out RImage img))
|
||||
{
|
||||
RServiceResult<RImage> imgRes =
|
||||
await _pictureFileService.GetImage(id);
|
||||
|
||||
if (!string.IsNullOrEmpty(img.ExceptionString))
|
||||
return BadRequest(img.ExceptionString);
|
||||
if (!string.IsNullOrEmpty(imgRes.ExceptionString))
|
||||
return BadRequest(imgRes.ExceptionString);
|
||||
|
||||
if (img.Result == null)
|
||||
return NotFound();
|
||||
if (imgRes.Result == null)
|
||||
return NotFound();
|
||||
|
||||
Response.GetTypedHeaders().LastModified = img.Result.LastModified;
|
||||
img = imgRes.Result;
|
||||
|
||||
_memoryCache.Set(cachKey, img);
|
||||
}
|
||||
|
||||
var cachKeyForPath = $"RImageControllerBase::Path::{id}";
|
||||
if (!_memoryCache.TryGetValue(cachKeyForPath, out string imgPath))
|
||||
{
|
||||
RServiceResult<string> imgPathRes = _pictureFileService.GetImagePath(img);
|
||||
if (!string.IsNullOrEmpty(imgPathRes.ExceptionString))
|
||||
return BadRequest(imgPathRes.ExceptionString);
|
||||
|
||||
imgPath = imgPathRes.Result;
|
||||
|
||||
_memoryCache.Set(cachKeyForPath, imgPath);
|
||||
}
|
||||
|
||||
Response.GetTypedHeaders().LastModified = img.LastModified;
|
||||
|
||||
var requestHeaders = Request.GetTypedHeaders();
|
||||
if (requestHeaders.IfModifiedSince.HasValue &&
|
||||
requestHeaders.IfModifiedSince.Value >= img.Result.LastModified)
|
||||
requestHeaders.IfModifiedSince.Value >= img.LastModified)
|
||||
{
|
||||
return StatusCode(StatusCodes.Status304NotModified);
|
||||
}
|
||||
|
||||
RServiceResult<string> imgPath = _pictureFileService.GetImagePath(img.Result);
|
||||
if (!string.IsNullOrEmpty(imgPath.ExceptionString))
|
||||
return BadRequest(imgPath.ExceptionString);
|
||||
|
||||
|
||||
return new FileStreamResult(new FileStream(imgPath.Result, FileMode.Open, FileAccess.Read), "image/jpeg");
|
||||
return new FileStreamResult(new FileStream(imgPath, FileMode.Open, FileAccess.Read), "image/jpeg");
|
||||
|
||||
}
|
||||
|
||||
@ -105,11 +121,12 @@ namespace RSecurityBackend.Controllers
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="pictureFileService">
|
||||
/// </param>
|
||||
public RImageControllerBase(IImageFileService pictureFileService)
|
||||
/// <param name="pictureFileService"></param>
|
||||
/// <param name="memoryCache"></param>
|
||||
public RImageControllerBase(IImageFileService pictureFileService, IMemoryCache memoryCache)
|
||||
{
|
||||
_pictureFileService = pictureFileService;
|
||||
_memoryCache = memoryCache;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -117,6 +134,11 @@ namespace RSecurityBackend.Controllers
|
||||
/// </summary>
|
||||
protected readonly IImageFileService _pictureFileService;
|
||||
|
||||
/// <summary>
|
||||
/// IMemoryCache
|
||||
/// </summary>
|
||||
protected readonly IMemoryCache _memoryCache;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,18 +444,23 @@
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:RSecurityBackend.Controllers.RImageControllerBase.#ctor(RSecurityBackend.Services.IImageFileService)">
|
||||
<member name="M:RSecurityBackend.Controllers.RImageControllerBase.#ctor(RSecurityBackend.Services.IImageFileService,Microsoft.Extensions.Caching.Memory.IMemoryCache)">
|
||||
<summary>
|
||||
constructor
|
||||
</summary>
|
||||
<param name="pictureFileService">
|
||||
</param>
|
||||
<param name="pictureFileService"></param>
|
||||
<param name="memoryCache"></param>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Controllers.RImageControllerBase._pictureFileService">
|
||||
<summary>
|
||||
Artifact Service
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:RSecurityBackend.Controllers.RImageControllerBase._memoryCache">
|
||||
<summary>
|
||||
IMemoryCache
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:RSecurityBackend.Controllers.RLongRunningJobsControllerBase">
|
||||
<summary>
|
||||
Long Running Jobs
|
||||
|
||||
Loading…
Reference in New Issue
Block a user