/// <summary> Refresh cache by key, TODO: temp</summary> public async Task RefreshCacheAsync(string cacheKey = null) { //using var scope = GeneralContext.CreateServiceScope(); if (GeneralContext.ServiceScope != null) { try { var cacheItems = this.GetCacheItems <ApiCacheItem>(); if (cacheKey != null) { cacheItems = cacheItems.Where(x => x.Key == cacheKey).ToDictionary(k => k.Key, v => v.Value); } CRPMContext dbContext = GeneralContext.ServiceScope.ServiceProvider.GetService <CRPMContext>(); var items = cacheItems.Where(x => x.Value?.Query.ToUpper().Contains("SELECT") ?? false); foreach (var item in items) { using var conn = dbContext.Database.GetDbConnection(); if (conn.State.Equals(ConnectionState.Closed)) { conn.Open(); } using var command = conn.CreateCommand(); command.CommandText = item.Value.Query; //var result = command.ExecuteNonQuery(); //var result = dbContext.Database.ExecuteSqlRaw(item.Value.Query); var result = dbContext.Set <User>() .FromSqlRaw <User>(item.Value.Query) .ToList(); var l = dbContext.User.Local; var list = dbContext.GetTrackEntries <User>(); using var db = new NpgsqlConnection(conn.ConnectionString); var result1 = db.Query <User>(item.Value.Query); //using var cmd = new NpgsqlCommand(item.Value.Query, con); //cmd.q var cacheItem = new ApiCacheItem(result, true, true, item.ToString()); await _cache.SetAsync(item.Key, Util.ConvertObjectToByteArray(cacheItem)); //var encodedData = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(data)); //await _cache.SetAsync(cacheKey, encodedData, new DistributedCacheEntryOptions()); _logger.LogInformation("{cacheKey} cache refreshed", item.Key); } } catch (System.Exception ex) { GeneralContext.Logger.Error(ex.GetApiMessageInfo()); } } }
public static ApiCacheItem Get(ApiInputHandler input) { ApiCacheItem item = cache.Where(x => x.Resource == input.Resource && x.Payload == input.Body).FirstOrDefault(); if (item == null) { return(null); } if (DateTime.Now.Subtract(item.Created).TotalMilliseconds > lifetimeMS) { lock (LOCK) { if (cache.Contains(item)) { cache.Remove(item); } } return(null); } return(item); }
private ApiHandlerOutput Process(ApiInputHandler input) { string typeName = Business.Resource.GetType(input.Resource); if (string.IsNullOrWhiteSpace(typeName)) { throw new ApiNotFoundException(input.Resource); } bool canAccess = Business.Authorization.CanAccess(input.Resource, Context.Current.User); if (!canAccess) { logger.Warn($"Access denied for resource {input.Resource}"); throw new SecurityException(Messages.AccessDenied); } if (Business.Authorization.RequireToken(input.Resource)) { string token = input.Context.Request.Headers["ZestyApiToken"]; if (string.IsNullOrWhiteSpace(token)) { token = input.Context.Request.Query["t"]; } if (!Business.Authorization.IsValid(Context.Current.User.Id, input.Context.Session.Id, token)) { logger.Warn($"Invalid token for resource {input.Resource}"); throw new SecurityException(Messages.TokenMissing); } } ApiCacheItem cacheItem = ApiCache.Get(input); if (cacheItem != null) { logger.Info($"Output found in cache for request {input.Resource}"); return(cacheItem.Output); } else { ApiHandlerBase handler = InstanceHelper.Create <ApiHandlerBase>(typeName); ApiHandlerOutput output = handler.Process(input); if (output.CachePolicy == ApiCachePolicy.Enable) { cacheItem = new ApiCacheItem { Created = DateTime.Now, Output = output, Payload = input.Body, Resource = input.Resource }; ApiCache.Store(cacheItem); logger.Info($"Output stored in cache for request {input.Resource}"); } if (output.ResourceHistoryOutput != null && output.ResourceHistoryOutput.ResourceHistoryPolicy == ApiResourceHistoryPolicy.Save) { Business.History.Save(output.ResourceHistoryOutput.Item); } return(output); } }
/// <summary> Set cache</summary> public Task SetAsync(string key, string query, object data, bool scoped = true, bool preLoad = true) { var item = new ApiCacheItem(data, preLoad, scoped, query); return(_cache.SetAsync(key.ToLower(), Util.ConvertObjectToByteArray(item))); }
public ValueTask WriteAsync(ApiCacheItem item, CancellationToken stoppingToken = default) { return(_channelWriter.WriteAsync(item, stoppingToken)); }
/// <summary> Preload data and set cache, TODO: not complete </summary> public async Task <bool> PreloadAsync(IServiceProvider serviceProvider) { this.CacheLoaded = true; try { // get controllers typeOf(ControllerBaseAction), that its have metods with attributes typeOf(ApiCacheAttribute) var controllerTypes = Assembly.GetEntryAssembly().ExportedTypes .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(ControllerBaseAction))) .Where(t => t.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Any(method => method.CustomAttributes .Any(attr => attr.AttributeType == typeof(ApiCacheAttribute) && attr.ConstructorArguments.Count == 2 && attr.ConstructorArguments.LastOrDefault().ArgumentType == typeof(Boolean) && Convert.ToBoolean(attr.ConstructorArguments.LastOrDefault().Value)) )); foreach (var controllerType in controllerTypes) { ConstructorInfo firstConstrutor = controllerType .GetConstructors(BindingFlags.Public | BindingFlags.Instance) .FirstOrDefault(); // get parameters of constructor for DI services var parameters = new List <object>(); foreach (var param in firstConstrutor.GetParameters()) { var service = serviceProvider.GetService(param.ParameterType); parameters.Add(service); } // get methods typeOf(ApiCacheAttribute) x.GetParameters().Length == 0 var methods = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(x => x.CustomAttributes.Any(attr => attr.AttributeType == typeof(ApiCacheAttribute) && attr.ConstructorArguments.Count == 2 && attr.ConstructorArguments.LastOrDefault().ArgumentType == typeof(Boolean) && Convert.ToBoolean(attr.ConstructorArguments.LastOrDefault().Value))) .ToList(); if (methods.Any()) { // create controller object object controllerObject = firstConstrutor.Invoke(parameters.ToArray()); foreach (var method in methods) { // method invoke Task <IActionResult> task = method.Invoke(controllerObject, null) as Task <IActionResult>; await task.ConfigureAwait(false); // method result var resultProperty = task.GetType().GetProperty("Result"); var resultValue = resultProperty.GetValue(task) as ObjectResult; if (resultValue != null) { ICacheService cacheService = serviceProvider.GetService <ICacheService>(); var attr = method.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(ApiCacheAttribute)); if (attr != null && attr.ConstructorArguments.Count == 2) { //.Where(x => Convert.ToBoolean(x.ConstructorArguments.FirstOrDefault().Value)) var isPreload = Convert.ToBoolean(attr.ConstructorArguments[1].Value); //var isScoped = Convert.ToBoolean(attr.ConstructorArguments[1].Value); // create cacheItem from result var apiServiceName = typeof(ICacheService).Assembly.GetName().Name + "Api"; var cacheValue = new ApiCacheItem(resultValue.Value, isPreload); var cacheKey = cacheService.CreateCacheKey(method, resultValue.Value.GetType()); // set http items for quick access from http context var httpContext = serviceProvider.GetService <IHttpContextAccessor>().HttpContext; httpContext.Items[cacheKey.ToLower()] = resultValue.Value; // set cache await cacheService.SetAsync(cacheKey, cacheValue); } } } } } this.CacheLoading = false; this.CacheLoaded = true; return(await Task.FromResult <bool>(true)); } catch (Exception ex) { GeneralContext.Logger.Error(ex.GetApiMessageInfo()); return(await Task.FromResult <bool>(false)); } }
public static void Store(ApiCacheItem item) { cache.Add(item); }