public virtual void CacheSearchResult(string folderPath, string pattern, IEnumerable <string> result) { _searchCache[new SearchQuery(folderPath, pattern)] = new CachedSearchResult() { Result = result, CachedAt = DateTime.Now }; }
public virtual bool GetCachedSearchResult(string folderPath, string pattern, out CachedSearchResult result) { var key = new SearchQuery(folderPath, pattern); if (_searchCache.ContainsKey(key)) { result = _searchCache[key]; return(true); } result = new CachedSearchResult(); return(false); }
public IQueryable <V2FeedPackage> Search(string searchTerm, string targetFramework, bool includePrerelease) { var packages = PackageRepo.GetAll() .Include(p => p.Authors) .Include(p => p.PackageRegistration) .Include(p => p.PackageRegistration.Owners) .Where(p => p.Listed); // Check if the caller is requesting packages or calling the count operation. bool requestingCount = HttpContext.Request.RawUrl.Contains("$count"); var isEmptySearchTerm = string.IsNullOrEmpty(searchTerm); if ((requestingCount && isEmptySearchTerm) || isEmptySearchTerm) { // Fetch the cache key for the empty search query. string cacheKey = GetCacheKeyForEmptySearchQuery(includePrerelease); IQueryable <V2FeedPackage> searchResults; DateTime lastModified; var cachedObject = HttpContext.Cache.Get(cacheKey); var currentDateTime = DateTime.UtcNow; if (cachedObject == null && !requestingCount) { searchResults = SearchV2FeedCore(packages, searchTerm, targetFramework, includePrerelease, useCache: false); lastModified = currentDateTime; // cache the most common search query // note: this is per instance cache var cachedPackages = searchResults.ToList(); // don't cache empty results in case we missed any potential ODATA expressions if (!cachedPackages.Any()) { var cachedSearchResult = new CachedSearchResult(); cachedSearchResult.LastModified = currentDateTime; cachedSearchResult.Packages = cachedPackages; HttpContext.Cache.Add( cacheKey, cachedSearchResult, null, currentDateTime.AddSeconds(DEFAULT_CACHE_TIME_SECONDS_V2FEED), Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } } else if (cachedObject == null) { // first hit on $count and nothing in cache yet; // we can't cache due to the $count hijack in SearchV2FeedCore... return(SearchV2FeedCore(packages, searchTerm, targetFramework, includePrerelease, useCache: false)); } else { var cachedSearchResult = (CachedSearchResult)cachedObject; searchResults = cachedSearchResult.Packages.AsQueryable(); lastModified = cachedSearchResult.LastModified; } // Clients should cache twice as long. // This way, they won't notice differences in the short-lived per instance cache. HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public); HttpContext.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(60)); HttpContext.Response.Cache.SetExpires(currentDateTime.AddSeconds(DEFAULT_CACHE_TIME_SECONDS_V2FEED * 2)); HttpContext.Response.Cache.SetLastModified(lastModified); HttpContext.Response.Cache.SetValidUntilExpires(true); return(searchResults); } return(SearchV2FeedCore(packages, searchTerm, targetFramework, includePrerelease, useCache: true)); }
public IQueryable <V2FeedPackage> Search(string searchTerm, string targetFramework, bool includePrerelease) { // Handle OData-style |-separated list of frameworks. string[] targetFrameworkList = (targetFramework ?? "").Split(new[] { '\'', '|' }, StringSplitOptions.RemoveEmptyEntries); // For now, we'll just filter on the first one. if (targetFrameworkList.Length > 0) { // Until we support multiple frameworks, we need to prefer aspnet50 over aspnetcore50. if (targetFrameworkList.Contains("aspnet50")) { targetFramework = "aspnet50"; } else { targetFramework = targetFrameworkList[0]; } } // Check if the caller is requesting packages or calling the count operation. bool requestingCount = HttpContext.Request.RawUrl.Contains("$count"); var isEmptySearchTerm = string.IsNullOrEmpty(searchTerm); if ((requestingCount && isEmptySearchTerm) || isEmptySearchTerm) { // Fetch the cache key for the empty search query. string cacheKey = GetCacheKeyForEmptySearchQuery(targetFramework, includePrerelease); IQueryable <V2FeedPackage> searchResults; DateTime lastModified; var cachedObject = HttpContext.Cache.Get(cacheKey); var currentDateTime = DateTime.UtcNow; if (cachedObject == null && !requestingCount) { searchResults = SearchV2FeedCore(searchTerm, targetFramework, includePrerelease); lastModified = currentDateTime; // cache the most common search query // note: this is per instance cache var cachedPackages = searchResults.ToList(); // don't cache empty resulsets in case we missed any potential ODATA expressions if (!cachedPackages.Any()) { var cachedSearchResult = new CachedSearchResult(); cachedSearchResult.LastModified = currentDateTime; cachedSearchResult.Packages = cachedPackages; HttpContext.Cache.Add(cacheKey, cachedSearchResult, null, currentDateTime.AddSeconds(ServerCacheExpirationInSeconds), Cache.NoSlidingExpiration, CacheItemPriority.Default, null); } } else if (cachedObject == null) { // first hit on $count and nothing in cache yet; // we can't cache due to the $count hijack in SearchV2FeedCore... return(SearchV2FeedCore(searchTerm, targetFramework, includePrerelease)); } else { var cachedSearchResult = (CachedSearchResult)cachedObject; searchResults = cachedSearchResult.Packages.AsQueryable(); lastModified = cachedSearchResult.LastModified; } // Clients should cache twice as long. // This way, they won't notice differences in the short-lived per instance cache. HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public); HttpContext.Response.Cache.SetMaxAge(TimeSpan.FromSeconds(60)); HttpContext.Response.Cache.SetExpires(currentDateTime.AddSeconds(ServerCacheExpirationInSeconds * 2)); HttpContext.Response.Cache.SetLastModified(lastModified); HttpContext.Response.Cache.SetValidUntilExpires(true); return(searchResults); } return(SearchV2FeedCore(searchTerm, targetFramework, includePrerelease)); }