core: redo search cache from scratch. resolves #10382 (#10447)

In simple words, when you make a request in Jackett, the results are saved in memory (cache). The next request will return results form the cache improving response time and making fewer requests to the sites.
* We assume all indexers/sites are stateless, the same request return the same response. If you change the search term, categories or something in the query Jackett has to make a live request to the indexer.
* There are some situations when we don't want to use the cache:
** When we are testing the indexers => if query.IsTest results are not cached
** When the user updates the configuration of one indexer => We call CleanIndexerCache to remove cached results before testing the configuration
** When there is some error/exception in the indexer => The results are not cached so we can retry in the next request
* We want to limit the memory usage, so we try to remove elements from cache ASAP:
** Each indexer can have a maximum number of results in memory. If the limit is exceeded we remove old results
** Cached results expire after some time
* Users can configure the cache or even disable it
This commit is contained in:
Diego Heras
2020-12-11 23:14:21 +01:00
committed by GitHub
parent ec3787e803
commit 69125add3e
126 changed files with 744 additions and 364 deletions

View File

@@ -114,14 +114,14 @@ namespace Jackett.Common.Services
var indexerTypes = allNonMetaInstantiatableIndexerTypes.Where(p => p.Name != "CardigannIndexer");
var nativeIndexers = indexerTypes.Select(type =>
{
var constructorArgumentTypes = new [] { typeof(IIndexerConfigurationService), typeof(WebClient), typeof(Logger), typeof(IProtectionService) };
var constructorArgumentTypes = new [] { typeof(IIndexerConfigurationService), typeof(WebClient), typeof(Logger), typeof(IProtectionService), typeof(ICacheService) };
var constructor = type.GetConstructor(constructorArgumentTypes);
if (constructor != null)
{
// create own webClient instance for each indexer (separate cookies stores, etc.)
var indexerWebClientInstance = (WebClient)Activator.CreateInstance(webClient.GetType(), processService, logger, globalConfigService, serverConfig);
var arguments = new object[] { configService, indexerWebClientInstance, logger, protectionService };
var arguments = new object[] { configService, indexerWebClientInstance, logger, protectionService, cacheService };
var indexer = (IIndexer)constructor.Invoke(arguments);
return indexer;
}
@@ -176,7 +176,7 @@ namespace Jackett.Common.Services
// create own webClient instance for each indexer (seperate cookies stores, etc.)
var indexerWebClientInstance = (WebClient)Activator.CreateInstance(webClient.GetType(), processService, logger, globalConfigService, serverConfig);
IIndexer indexer = new CardigannIndexer(configService, indexerWebClientInstance, logger, protectionService, definition);
IIndexer indexer = new CardigannIndexer(configService, indexerWebClientInstance, logger, protectionService, cacheService, definition);
configService.Load(indexer);
return indexer;
}
@@ -229,7 +229,7 @@ namespace Jackett.Common.Services
}
logger.Info("Adding aggregate indexer ('all' indexer) ...");
aggregateIndexer = new AggregateIndexer(fallbackStrategyProvider, resultFilterProvider, configService, webClient, logger, protectionService)
aggregateIndexer = new AggregateIndexer(fallbackStrategyProvider, resultFilterProvider, configService, webClient, logger, protectionService, cacheService)
{
Indexers = indexers.Values
};
@@ -291,17 +291,18 @@ namespace Jackett.Common.Services
public async Task TestIndexer(string name)
{
var indexer = GetIndexer(name);
var browseQuery = new TorznabQuery
var query = new TorznabQuery
{
QueryType = "search",
SearchTerm = "",
IsTest = true
};
var result = await indexer.ResultsForQuery(browseQuery);
logger.Info($"Found {result.Releases.Count()} releases from {indexer.DisplayName}");
var result = await indexer.ResultsForQuery(query);
logger.Info($"Test search in {indexer.DisplayName} => Found {result.Releases.Count()} releases");
if (!result.Releases.Any())
throw new Exception("Found no results while trying to browse this tracker");
cacheService.CacheRssResults(indexer, result.Releases);
}
public void DeleteIndexer(string name)