Commit 0e1a8aec authored by Alessio Parma's avatar Alessio Parma 🐔

config + readme

parent ac20700a
Pipeline #151685070 failed with stages
in 6 minutes and 21 seconds
......@@ -48,11 +48,13 @@ docker run -it -e Security__AllowAnonymousAccess=true -p 8080:8080 pommalabs/thu
Local instance will be listening on port 8080 and will accept unauthenticated requests.
### Configuration
Docker image can be configured using the following environment variables:
| Environment variable | Notes | Default value |
| ------------------------------------------------ | ------------------------------------------------ | -------------- |
| `Cache__Lifetime` | How long each cache entry will live. | 10 minutes |
| `Database__CacheLifetime` | How long each cache entry will live. | 10 minutes |
| `Database__ConnectionString` | Connection string of a SQL database. | |
| `Database__Provider` | Provider (`None`, `PostgreSql`, `SqlServer`). | `None` |
| `Security__AcceptApiKeysViaHeaderParameter` | Accept API keys via header parameter. | `true` |
......@@ -69,9 +71,7 @@ Docker image can be configured using the following environment variables:
## Usage
```
TODO: Document a simple call.
```
Sample web service calls can be found on [Thumbnailer RapidAPI page][rapidapi-endpoints].
**Image optimization** supports following content types:
......
// File name: CacheConfiguration.cs
//
// Author(s): Alessio Parma <[email protected]>
//
// The MIT License (MIT)
//
// Copyright (c) 2019-2020 Alessio Parma <[email protected]>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
namespace PommaLabs.Thumbnailer.Models.Configurations
{
/// <summary>
/// Internal cache configuration.
/// </summary>
public sealed class CacheConfiguration
{
/// <summary>
/// How long each cache entry will live. Defaults to 10 minutes.
/// </summary>
public TimeSpan Lifetime { get; set; } = TimeSpan.FromMinutes(10);
}
}
......@@ -38,6 +38,11 @@ public sealed class DatabaseConfiguration
/// </summary>
private string? _connectionString;
/// <summary>
/// How long each cache entry will live. Defaults to 10 minutes.
/// </summary>
public TimeSpan CacheLifetime { get; set; } = TimeSpan.FromMinutes(10);
/// <summary>
/// Connection string of a SQL database.
/// </summary>
......
......@@ -169,7 +169,7 @@ public TempFileDTO(string contentType, string? extension)
/// cached and it is returned to the caller.
/// </summary>
/// <param name="cache">Cache.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
/// <param name="file">
/// File which might be deleted if a file with the same hash exists in the cache.
/// </param>
......@@ -179,7 +179,7 @@ public TempFileDTO(string contentType, string? extension)
/// </returns>
/// <remarks>This method is used to avoid flooding the server with the same files.</remarks>
public static async Task<TempFileDTO> CheckCacheAsync(
ICache cache, IOptions<CacheConfiguration> cacheConfiguration,
ICache cache, IOptions<DatabaseConfiguration> databaseConfiguration,
TempFileDTO file, CancellationToken cancellationToken)
{
if (file._path == null || !file._path.IsFile)
......@@ -197,7 +197,7 @@ public TempFileDTO(string contentType, string? extension)
partition: nameof(TempFileDTO),
key: new CacheKey(hash),
valueGetter: () => Task.FromResult(file),
lifetime: cacheConfiguration.Value.Lifetime,
lifetime: databaseConfiguration.Value.CacheLifetime,
cancellationToken: cancellationToken,
continueOnCapturedContext: false).ConfigureAwait(false);
......
......@@ -39,22 +39,22 @@ namespace PommaLabs.Thumbnailer.Services.Background
public sealed class CleanupTempApiKeysBackgroundService : BackgroundService
{
private readonly IApiKeyStore _apiKeyStore;
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly ILogger<CleanupTempApiKeysBackgroundService> _logger;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="logger">Logger.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
/// <param name="apiKeyStore">API key store.</param>
public CleanupTempApiKeysBackgroundService(
ILogger<CleanupTempApiKeysBackgroundService> logger,
IOptions<CacheConfiguration> cacheConfiguration,
IOptions<DatabaseConfiguration> databaseConfiguration,
IApiKeyStore apiKeyStore)
{
_logger = logger;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
_apiKeyStore = apiKeyStore;
}
......@@ -76,7 +76,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
_logger.LogWarning(ex, "An error occurred while deleting expired temporary API keys");
}
var delaySeconds = (int)_cacheConfiguration.Value.Lifetime.TotalSeconds / 10;
var delaySeconds = (int)_databaseConfiguration.Value.CacheLifetime.TotalSeconds / 10;
_logger.LogDebug("Temporary API keys cleanup service will run again in {DelaySeconds} seconds", delaySeconds);
await Task.Delay(delaySeconds * 1000, stoppingToken).ConfigureAwait(false);
......
......@@ -40,8 +40,8 @@ namespace PommaLabs.Thumbnailer.Services.Background
/// </summary>
public sealed class CleanupTempFilesBackgroundService : BackgroundService
{
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IClock _clock;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly ILogger<CleanupTempFilesBackgroundService> _logger;
private readonly ITempFileStore _tempFileStore;
......@@ -49,17 +49,17 @@ public sealed class CleanupTempFilesBackgroundService : BackgroundService
/// Constructor.
/// </summary>
/// <param name="logger">Logger.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
/// <param name="tempFileStore">Temporary file store.</param>
/// <param name="clock">Clock.</param>
public CleanupTempFilesBackgroundService(
ILogger<CleanupTempFilesBackgroundService> logger,
IOptions<CacheConfiguration> cacheConfiguration,
IOptions<DatabaseConfiguration> databaseConfiguration,
ITempFileStore tempFileStore,
IClock clock)
{
_logger = logger;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
_tempFileStore = tempFileStore;
_clock = clock;
}
......@@ -81,7 +81,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
_logger.LogWarning(ex, "An error occurred while deleting old temporary files");
}
var delaySeconds = (int)_cacheConfiguration.Value.Lifetime.TotalSeconds / 10;
var delaySeconds = (int)_databaseConfiguration.Value.CacheLifetime.TotalSeconds / 10;
_logger.LogDebug("Temporary files cleanup service will run again in {DelaySeconds} seconds", delaySeconds);
await Task.Delay(delaySeconds * 1000, stoppingToken).ConfigureAwait(false);
......@@ -92,7 +92,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
private async Task DeleteOldTempFilesAsync(CancellationToken stoppingToken)
{
var threshold = _clock.UtcNow.AddSeconds(_cacheConfiguration.Value.Lifetime.TotalSeconds * -2);
var threshold = _clock.UtcNow.AddSeconds(_databaseConfiguration.Value.CacheLifetime.TotalSeconds * -2);
var evaluatedFileCount = 0;
var deletedFileCount = 0;
......
......@@ -37,7 +37,7 @@ namespace PommaLabs.Thumbnailer.Services.Managers.Download
public sealed class CachingDownloadManager : IDownloadManager
{
private readonly ICache _cache;
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly IDownloadManager _downloadManager;
/// <summary>
......@@ -45,15 +45,15 @@ public sealed class CachingDownloadManager : IDownloadManager
/// </summary>
/// <param name="downloadManager">Download manager.</param>
/// <param name="cache">Cache.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
public CachingDownloadManager(
IDownloadManager downloadManager,
ICache cache,
IOptions<CacheConfiguration> cacheConfiguration)
IOptions<DatabaseConfiguration> databaseConfiguration)
{
_downloadManager = downloadManager;
_cache = cache;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
}
/// <inheritdoc/>
......@@ -65,9 +65,9 @@ public async Task<TempFileDTO> DownloadFileAsync(Uri fileUri, CancellationToken
valueGetter: async () =>
{
var file = await _downloadManager.DownloadFileAsync(fileUri, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _cacheConfiguration, file, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _databaseConfiguration, file, cancellationToken).ConfigureAwait(false);
},
interval: _cacheConfiguration.Value.Lifetime,
interval: _databaseConfiguration.Value.CacheLifetime,
cancellationToken: cancellationToken,
continueOnCapturedContext: false).ConfigureAwait(false);
}
......
......@@ -37,7 +37,7 @@ namespace PommaLabs.Thumbnailer.Services.Managers.Optimization
public sealed class CachingOptimizationManager : IOptimizationManager
{
private readonly ICache _cache;
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly IOptimizationManager _optimizationManager;
/// <summary>
......@@ -45,15 +45,15 @@ public sealed class CachingOptimizationManager : IOptimizationManager
/// </summary>
/// <param name="optimizationManager">Optimization manager.</param>
/// <param name="cache">Cache.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
public CachingOptimizationManager(
IOptimizationManager optimizationManager,
ICache cache,
IOptions<CacheConfiguration> cacheConfiguration)
IOptions<DatabaseConfiguration> databaseConfiguration)
{
_optimizationManager = optimizationManager;
_cache = cache;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
}
/// <inheritdoc/>
......@@ -64,7 +64,7 @@ public sealed class CachingOptimizationManager : IOptimizationManager
return await _cache.GetOrAddSlidingAsync(
partition: nameof(IOptimizationManager),
valueExpression: () => _optimizationManager.OptimizeImageAsync(file, mode, cancellationToken),
interval: _cacheConfiguration.Value.Lifetime,
interval: _databaseConfiguration.Value.CacheLifetime,
cancellationToken: cancellationToken,
continueOnCapturedContext: false).ConfigureAwait(false);
}
......
......@@ -36,7 +36,7 @@ namespace PommaLabs.Thumbnailer.Services.Managers.Thumbnail
public sealed class CachingThumbnailManager : IThumbnailManager
{
private readonly ICache _cache;
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly IThumbnailManager _thumbnailManager;
/// <summary>
......@@ -44,15 +44,15 @@ public sealed class CachingThumbnailManager : IThumbnailManager
/// </summary>
/// <param name="thumbnailManager">Thumbnail manager.</param>
/// <param name="cache">Cache.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
public CachingThumbnailManager(
IThumbnailManager thumbnailManager,
ICache cache,
IOptions<CacheConfiguration> cacheConfiguration)
IOptions<DatabaseConfiguration> databaseConfiguration)
{
_thumbnailManager = thumbnailManager;
_cache = cache;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
}
/// <inheritdoc/>
......@@ -63,7 +63,7 @@ public sealed class CachingThumbnailManager : IThumbnailManager
return await _cache.GetOrAddSlidingAsync(
partition: nameof(IThumbnailManager),
valueExpression: () => _thumbnailManager.GenerateThumbnailAsync(file, widthPx, heightPx, shavePx, fill, cancellationToken),
interval: _cacheConfiguration.Value.Lifetime,
interval: _databaseConfiguration.Value.CacheLifetime,
cancellationToken: cancellationToken,
continueOnCapturedContext: false).ConfigureAwait(false);
}
......
......@@ -38,7 +38,7 @@ namespace PommaLabs.Thumbnailer.Services.Stores.TempFiles
public sealed class CachingTempFileStore : ITempFileStore
{
private readonly ICache _cache;
private readonly IOptions<CacheConfiguration> _cacheConfiguration;
private readonly IOptions<DatabaseConfiguration> _databaseConfiguration;
private readonly ITempFileStore _tempFileStore;
/// <summary>
......@@ -46,15 +46,15 @@ public sealed class CachingTempFileStore : ITempFileStore
/// </summary>
/// <param name="tempFileStore">Temporary file store.</param>
/// <param name="cache">Cache.</param>
/// <param name="cacheConfiguration">Cache configuration.</param>
/// <param name="databaseConfiguration">Database configuration.</param>
public CachingTempFileStore(
ITempFileStore tempFileStore,
ICache cache,
IOptions<CacheConfiguration> cacheConfiguration)
IOptions<DatabaseConfiguration> databaseConfiguration)
{
_tempFileStore = tempFileStore;
_cache = cache;
_cacheConfiguration = cacheConfiguration;
_databaseConfiguration = databaseConfiguration;
}
/// <inheritdoc/>
......@@ -76,14 +76,14 @@ public Task<IEnumerable<TempFileDTO>> GetTempFilesAsync(CancellationToken cancel
public async Task<TempFileDTO> HandleFileUploadAsync(IFormFile formFile, CancellationToken cancellationToken)
{
var file = await _tempFileStore.HandleFileUploadAsync(formFile, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _cacheConfiguration, file, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _databaseConfiguration, file, cancellationToken).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task<TempFileDTO> HandleFileUploadAsync(UploadedFileDTO externalFile, CancellationToken cancellationToken)
{
var file = await _tempFileStore.HandleFileUploadAsync(externalFile, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _cacheConfiguration, file, cancellationToken).ConfigureAwait(false);
return await TempFileDTO.CheckCacheAsync(_cache, _databaseConfiguration, file, cancellationToken).ConfigureAwait(false);
}
}
}
}
\ No newline at end of file
......@@ -167,7 +167,6 @@ private static string XmlCommentsFilePath
public void ConfigureContainer(ServiceRegistry services)
{
// Configuration classes:
services.Configure<CacheConfiguration>(Configuration.GetSection("Caching"));
services.Configure<DatabaseConfiguration>(Configuration.GetSection("Database"));
services.Configure<RecaptchaSettings>(Configuration.GetSection("Website").GetSection("Recaptcha"));
services.Configure<SecurityConfiguration>(Configuration.GetSection("Security"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment