diff --git a/.editorconfig b/.editorconfig index 077a4c3..807c5e5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,9 +21,6 @@ dotnet_diagnostic.RECS0117.severity = none dotnet_diagnostic.SA0001.severity = none dotnet_diagnostic.SA1649.severity = none -# IDE0290: Use primary constructor -dotnet_diagnostic.IDE0290.severity = none - # IDE0305: Simplify collection initialization dotnet_diagnostic.IDE0305.severity = none diff --git a/Directory.Build.props b/Directory.Build.props index c0086ac..1bc40cd 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,7 @@ https://github.com/squidex/squidex true snupkg - 6.20.0 + 6.21.0 diff --git a/Dockerfile b/Dockerfile index 04ba21d..69f2151 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,9 @@ WORKDIR /src COPY *.sln ./ # Copy the main source project files +COPY ai/*/*.csproj ./ +RUN for file in $(ls *.csproj); do mkdir -p assets/${file%.*}/ && mv $file ai/${file%.*}/; done + COPY assets/*/*.csproj ./ RUN for file in $(ls *.csproj); do mkdir -p assets/${file%.*}/ && mv $file assets/${file%.*}/; done diff --git a/ai/Squidex.AI.Tests/OpenApiFunctionParserTests.cs b/ai/Squidex.AI.Tests/OpenApiFunctionParserTests.cs index 5ce3dd2..878f6b8 100644 --- a/ai/Squidex.AI.Tests/OpenApiFunctionParserTests.cs +++ b/ai/Squidex.AI.Tests/OpenApiFunctionParserTests.cs @@ -5,8 +5,8 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels; using FluentAssertions; -using OpenAI.ObjectModels.RequestModels; using Squidex.AI.Implementation.OpenAI; using Squidex.AI.Utils; using Xunit; diff --git a/ai/Squidex.AI.Tests/Squidex.AI.Tests.csproj b/ai/Squidex.AI.Tests/Squidex.AI.Tests.csproj index f1e38bc..184f1d9 100644 --- a/ai/Squidex.AI.Tests/Squidex.AI.Tests.csproj +++ b/ai/Squidex.AI.Tests/Squidex.AI.Tests.csproj @@ -16,19 +16,19 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/ai/Squidex.AI/DelegateChatTool.cs b/ai/Squidex.AI/DelegateChatTool.cs index 07580b2..3a6886c 100644 --- a/ai/Squidex.AI/DelegateChatTool.cs +++ b/ai/Squidex.AI/DelegateChatTool.cs @@ -7,18 +7,9 @@ namespace Squidex.AI; -public sealed class DelegateChatTool : IChatTool +public sealed class DelegateChatTool(ToolSpec spec, Func> action) : IChatTool { - private readonly Func> action; - - public ToolSpec Spec { get; } - - public DelegateChatTool(ToolSpec spec, Func> action) - { - Spec = spec; - - this.action = action; - } + public ToolSpec Spec { get; } = spec; public Task ExecuteAsync(ToolContext toolContext, CancellationToken ct) diff --git a/ai/Squidex.AI/Implementation/ChatAgent.cs b/ai/Squidex.AI/Implementation/ChatAgent.cs index fcb9069..513efee 100644 --- a/ai/Squidex.AI/Implementation/ChatAgent.cs +++ b/ai/Squidex.AI/Implementation/ChatAgent.cs @@ -11,30 +11,17 @@ namespace Squidex.AI.Implementation; -public sealed class ChatAgent : IChatAgent +public sealed class ChatAgent( + IChatProvider chatProvider, + IChatStore chatStore, + IEnumerable chatPipes, + IEnumerable chatToolProviders, + IOptions options) : IChatAgent { - private readonly ChatOptions options; - private readonly IChatProvider chatProvider; - private readonly IChatStore chatStore; - private readonly IEnumerable chatPipes; - private readonly IEnumerable chatToolProviders; + private readonly ChatOptions options = options.Value; public bool IsConfigured => chatProvider is not NoopChatProvider; - public ChatAgent( - IChatProvider chatProvider, - IChatStore chatStore, - IEnumerable chatPipes, - IEnumerable chatToolProviders, - IOptions options) - { - this.options = options.Value; - this.chatPipes = chatPipes; - this.chatProvider = chatProvider; - this.chatStore = chatStore; - this.chatToolProviders = chatToolProviders; - } - public async Task StopConversationAsync(string conversationId, ChatContext? context = null, CancellationToken ct = default) { diff --git a/ai/Squidex.AI/Implementation/ChatCleaner.cs b/ai/Squidex.AI/Implementation/ChatCleaner.cs index b753542..970ad3a 100644 --- a/ai/Squidex.AI/Implementation/ChatCleaner.cs +++ b/ai/Squidex.AI/Implementation/ChatCleaner.cs @@ -11,32 +11,17 @@ namespace Squidex.AI.Implementation; -public sealed class ChatCleaner : IBackgroundProcess +public sealed class ChatCleaner( + IChatAgent chatAgent, + IChatStore chatStore, + IEnumerable chatTools, + IOptions options, + TimeProvider timeProvider, + ILogger log) : IBackgroundProcess { - private readonly ChatOptions options; - private readonly TimeProvider timeProvider; - private readonly IChatAgent chatAgent; - private readonly IChatStore chatStore; - private readonly IEnumerable chatTools; - private readonly ILogger log; + private readonly ChatOptions options = options.Value; private SimpleTimer? cleanupTimer; - public ChatCleaner( - IChatAgent chatAgent, - IChatStore chatStore, - IEnumerable chatTools, - IOptions options, - TimeProvider timeProvider, - ILogger log) - { - this.chatAgent = chatAgent; - this.chatStore = chatStore; - this.chatTools = chatTools; - this.log = log; - this.options = options.Value; - this.timeProvider = timeProvider; - } - public Task StartAsync( CancellationToken ct) { diff --git a/ai/Squidex.AI/Implementation/ImagePipe.cs b/ai/Squidex.AI/Implementation/ImagePipe.cs index 22b1466..bdd76c2 100644 --- a/ai/Squidex.AI/Implementation/ImagePipe.cs +++ b/ai/Squidex.AI/Implementation/ImagePipe.cs @@ -10,17 +10,11 @@ namespace Squidex.AI.Implementation; -public sealed class ImagePipe : IChatPipe +public sealed class ImagePipe(IImageTool imageGenerator) : IChatPipe { private const string ImageStart = ""; private const string ImageEnd = ""; private const int BufferLength = 5; - private readonly IImageTool imageGenerator; - - public ImagePipe(IImageTool imageGenerator) - { - this.imageGenerator = imageGenerator; - } public async IAsyncEnumerable StreamAsync(IAsyncEnumerable source, ChatProviderRequest request, [EnumeratorCancellation] CancellationToken ct = default) diff --git a/ai/Squidex.AI/Implementation/Mongo/MongoChatStore.cs b/ai/Squidex.AI/Implementation/Mongo/MongoChatStore.cs index 85d7868..b52adaa 100644 --- a/ai/Squidex.AI/Implementation/Mongo/MongoChatStore.cs +++ b/ai/Squidex.AI/Implementation/Mongo/MongoChatStore.cs @@ -13,14 +13,9 @@ namespace Squidex.AI.Implementation.Mongo; -public sealed class MongoChatStore : IChatStore, IInitializable +public sealed class MongoChatStore(IMongoDatabase database, IOptions options) : IChatStore, IInitializable { - private readonly IMongoCollection collection; - - public MongoChatStore(IMongoDatabase database, IOptions options) - { - collection = database.GetCollection(options.Value.CollectionName); - } + private readonly IMongoCollection collection = database.GetCollection(options.Value.CollectionName); public Task InitializeAsync( CancellationToken ct) diff --git a/ai/Squidex.AI/Implementation/OpenAI/DallEOptions.cs b/ai/Squidex.AI/Implementation/OpenAI/DallEOptions.cs index 6ec198f..e016d46 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/DallEOptions.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/DallEOptions.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using OpenAI; -using OpenAI.ObjectModels; +using Betalgo.Ranul.OpenAI; +using Betalgo.Ranul.OpenAI.ObjectModels; namespace Squidex.AI.Implementation.OpenAI; -public sealed class DallEOptions : OpenAiOptions +public sealed class DallEOptions : OpenAIOptions { public string? Model { get; set; } = Models.Dall_e_3; diff --git a/ai/Squidex.AI/Implementation/OpenAI/DallETool.cs b/ai/Squidex.AI/Implementation/OpenAI/DallETool.cs index c2d38f0..a03d1ab 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/DallETool.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/DallETool.cs @@ -5,23 +5,24 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Betalgo.Ranul.OpenAI.Managers; +using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels; using Microsoft.Extensions.Options; -using OpenAI.Managers; -using OpenAI.ObjectModels.RequestModels; using Squidex.Assets; namespace Squidex.AI.Implementation.OpenAI; -public sealed class DallETool : IImageTool +public sealed class DallETool( + IOptions options, + IAssetStore assetStore, + IAssetThumbnailGenerator assetThumbnailGenerator, + IChatProvider chatProvider, + IHttpImageEndpoint httpImageEndpoint, + IHttpClientFactory httpClientFactory) : IImageTool { private const string DataPrefix = "dall_e_image"; - private readonly OpenAIService service; - private readonly DallEOptions options; - private readonly IAssetStore assetStore; - private readonly IAssetThumbnailGenerator assetThumbnailGenerator; - private readonly IChatProvider chatProvider; - private readonly IHttpImageEndpoint httpImageEndpoint; - private readonly IHttpClientFactory httpClientFactory; + private readonly OpenAIService service = new OpenAIService(options.Value); + private readonly DallEOptions options = options.Value; public ToolSpec Spec { get; } = new ToolSpec("dall-e", "Dall-E", "Generates images based on queries.") @@ -35,24 +36,6 @@ public sealed class DallETool : IImageTool } }; - public DallETool( - IOptions options, - IAssetStore assetStore, - IAssetThumbnailGenerator assetThumbnailGenerator, - IChatProvider chatProvider, - IHttpImageEndpoint httpImageEndpoint, - IHttpClientFactory httpClientFactory) - { - service = new OpenAIService(options.Value); - - this.options = options.Value; - this.assetStore = assetStore; - this.assetThumbnailGenerator = assetThumbnailGenerator; - this.chatProvider = chatProvider; - this.httpImageEndpoint = httpImageEndpoint; - this.httpClientFactory = httpClientFactory; - } - public async Task CleanupAsync(Dictionary toolData, CancellationToken ct) { diff --git a/ai/Squidex.AI/Implementation/OpenAI/Helper.cs b/ai/Squidex.AI/Implementation/OpenAI/Helper.cs index b3f0bdb..a531e5f 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/Helper.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/Helper.cs @@ -7,10 +7,10 @@ using System.Text.Json; using System.Text.Json.Nodes; -using OpenAI.Builders; -using OpenAI.ObjectModels.RequestModels; -using OpenAI.ObjectModels.SharedModels; -using OpenAIMessage = OpenAI.ObjectModels.RequestModels.ChatMessage; +using Betalgo.Ranul.OpenAI.Builders; +using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels; +using Betalgo.Ranul.OpenAI.ObjectModels.SharedModels; +using OpenAIMessage = Betalgo.Ranul.OpenAI.ObjectModels.RequestModels.ChatMessage; namespace Squidex.AI.Implementation.OpenAI; diff --git a/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatOptions.cs b/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatOptions.cs index a703e40..1d2e8cf 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatOptions.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatOptions.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using OpenAI; -using OpenAI.ObjectModels; +using Betalgo.Ranul.OpenAI; +using Betalgo.Ranul.OpenAI.ObjectModels; namespace Squidex.AI.Implementation.OpenAI; -public sealed class OpenAIChatOptions : OpenAiOptions +public sealed class OpenAIChatOptions : OpenAIOptions { public string Model { get; set; } = Models.Gpt_4o; diff --git a/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatProvider.cs b/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatProvider.cs index 018df10..187921d 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatProvider.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/OpenAIChatProvider.cs @@ -7,25 +7,18 @@ using System.Globalization; using System.Reactive.Linq; +using Betalgo.Ranul.OpenAI.Managers; +using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels; using Microsoft.Extensions.Options; -using OpenAI.Managers; -using OpenAI.ObjectModels.RequestModels; -using OpenAIMessage = OpenAI.ObjectModels.RequestModels.ChatMessage; +using OpenAIMessage = Betalgo.Ranul.OpenAI.ObjectModels.RequestModels.ChatMessage; namespace Squidex.AI.Implementation.OpenAI; -public sealed class OpenAIChatProvider : IChatProvider +public sealed class OpenAIChatProvider(IOptions options) : IChatProvider { private readonly StreamOptions streamOptions = new StreamOptions { IncludeUsage = true }; - private readonly OpenAIChatOptions options; - private readonly OpenAIService service; - - public OpenAIChatProvider(IOptions options) - { - service = new OpenAIService(options.Value); - - this.options = options.Value; - } + private readonly OpenAIChatOptions options = options.Value; + private readonly OpenAIService service = new OpenAIService(options.Value); public IAsyncEnumerable StreamAsync(ChatProviderRequest request, CancellationToken ct = default) diff --git a/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddings.cs b/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddings.cs index d1f5a0d..37f8689 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddings.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddings.cs @@ -5,23 +5,16 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using Betalgo.Ranul.OpenAI.Managers; +using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels; using Microsoft.Extensions.Options; -using OpenAI.Managers; -using OpenAI.ObjectModels.RequestModels; namespace Squidex.AI.Implementation.OpenAI; -public sealed class OpenAIEmbeddings : IEmbeddings +public sealed class OpenAIEmbeddings(IOptions options) : IEmbeddings { - private readonly OpenAIEmbeddingsOptions options; - private readonly OpenAIService service; - - public OpenAIEmbeddings(IOptions options) - { - service = new OpenAIService(options.Value); - - this.options = options.Value; - } + private readonly OpenAIEmbeddingsOptions options = options.Value; + private readonly OpenAIService service = new OpenAIService(options.Value); public async Task> CalculateEmbeddingsAsync(string query, CancellationToken ct) diff --git a/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddingsOptions.cs b/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddingsOptions.cs index e88c363..3111d75 100644 --- a/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddingsOptions.cs +++ b/ai/Squidex.AI/Implementation/OpenAI/OpenAIEmbeddingsOptions.cs @@ -5,12 +5,12 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== -using OpenAI; -using OpenAI.ObjectModels; +using Betalgo.Ranul.OpenAI; +using Betalgo.Ranul.OpenAI.ObjectModels; namespace Squidex.AI.Implementation.OpenAI; -public sealed class OpenAIEmbeddingsOptions : OpenAiOptions +public sealed class OpenAIEmbeddingsOptions : OpenAIOptions { public string ModelName { get; set; } = Models.TextEmbeddingV3Large; } diff --git a/ai/Squidex.AI/Implementation/Pinecone/PineconeTool.cs b/ai/Squidex.AI/Implementation/Pinecone/PineconeTool.cs index e90c24e..55a66a4 100644 --- a/ai/Squidex.AI/Implementation/Pinecone/PineconeTool.cs +++ b/ai/Squidex.AI/Implementation/Pinecone/PineconeTool.cs @@ -49,7 +49,7 @@ public PineconeTool(IEmbeddings embeddings, IOptions options) public async Task InitializeAsync( CancellationToken ct) { - index = await client.GetIndex(options.IndexName, ct); + index = await client.GetIndex(options.IndexName, ct); } public async Task ExecuteAsync(ToolContext toolContext, diff --git a/ai/Squidex.AI/Implementation/SingleChatToolProvider.cs b/ai/Squidex.AI/Implementation/SingleChatToolProvider.cs index 59a29fd..f9d6d91 100644 --- a/ai/Squidex.AI/Implementation/SingleChatToolProvider.cs +++ b/ai/Squidex.AI/Implementation/SingleChatToolProvider.cs @@ -7,15 +7,8 @@ namespace Squidex.AI.Implementation; -public sealed class SingleChatToolProvider : IChatToolProvider where T : IChatTool +public sealed class SingleChatToolProvider(T tool) : IChatToolProvider where T : IChatTool { - private readonly T tool; - - public SingleChatToolProvider(T tool) - { - this.tool = tool; - } - public IAsyncEnumerable GetToolsAsync(ChatContext chatContext, CancellationToken ct) { diff --git a/ai/Squidex.AI/Squidex.AI.csproj b/ai/Squidex.AI/Squidex.AI.csproj index fb4820e..0af1390 100644 --- a/ai/Squidex.AI/Squidex.AI.csproj +++ b/ai/Squidex.AI/Squidex.AI.csproj @@ -12,23 +12,23 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + diff --git a/assets/Benchmarks/Benchmarks.csproj b/assets/Benchmarks/Benchmarks.csproj index 45566df..2aa47ea 100644 --- a/assets/Benchmarks/Benchmarks.csproj +++ b/assets/Benchmarks/Benchmarks.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.Azure/AzureBlobAssetStore.cs b/assets/Squidex.Assets.Azure/AzureBlobAssetStore.cs index dc17cbc..7f32810 100644 --- a/assets/Squidex.Assets.Azure/AzureBlobAssetStore.cs +++ b/assets/Squidex.Assets.Azure/AzureBlobAssetStore.cs @@ -13,7 +13,7 @@ namespace Squidex.Assets; -public class AzureBlobAssetStore : IAssetStore, IInitializable +public class AzureBlobAssetStore(IOptions options) : IAssetStore, IInitializable { private static readonly BlobUploadOptions NoOverwriteUpload = new BlobUploadOptions { @@ -29,15 +29,10 @@ public class AzureBlobAssetStore : IAssetStore, IInitializable IfNoneMatch = new ETag("*") } }; - private readonly AzureBlobAssetOptions options; + private readonly AzureBlobAssetOptions options = options.Value; private BlobContainerClient blobContainer; private BlobContainerProperties blobContainerProperties; - public AzureBlobAssetStore(IOptions options) - { - this.options = options.Value; - } - public async Task InitializeAsync( CancellationToken ct) { diff --git a/assets/Squidex.Assets.Azure/Squidex.Assets.Azure.csproj b/assets/Squidex.Assets.Azure/Squidex.Assets.Azure.csproj index 1f29618..d030377 100644 --- a/assets/Squidex.Assets.Azure/Squidex.Assets.Azure.csproj +++ b/assets/Squidex.Assets.Azure/Squidex.Assets.Azure.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.FTP/FTPAssetStore.cs b/assets/Squidex.Assets.FTP/FTPAssetStore.cs index 600967a..4af3eb4 100644 --- a/assets/Squidex.Assets.FTP/FTPAssetStore.cs +++ b/assets/Squidex.Assets.FTP/FTPAssetStore.cs @@ -15,25 +15,15 @@ namespace Squidex.Assets; [ExcludeFromCodeCoverage] -public sealed class FTPAssetStore : IAssetStore, IInitializable +public sealed class FTPAssetStore(IOptions options, ILogger log) : IAssetStore, IInitializable { - private readonly ILogger log; - private readonly FTPClientPool pool; - private readonly FTPAssetOptions options; - - public FTPAssetStore(IOptions options, ILogger log) - { - this.options = options.Value; - - this.log = log; - - pool = new FTPClientPool( + private readonly FTPClientPool pool = new FTPClientPool( () => new AsyncFtpClient( options.Value.ServerHost, options.Value.Username, options.Value.Password, options.Value.ServerPort), 1); - } + private readonly FTPAssetOptions options = options.Value; public async Task InitializeAsync( CancellationToken ct) diff --git a/assets/Squidex.Assets.FTP/FTPClientPool.cs b/assets/Squidex.Assets.FTP/FTPClientPool.cs index a6a446c..61f2844 100644 --- a/assets/Squidex.Assets.FTP/FTPClientPool.cs +++ b/assets/Squidex.Assets.FTP/FTPClientPool.cs @@ -9,20 +9,12 @@ namespace Squidex.Assets; -internal sealed class FTPClientPool +internal sealed class FTPClientPool(Func clientFactory, int clientsLimit) { private readonly Queue> queue = new Queue>(); private readonly Queue pool = new Queue(); - private readonly Func clientFactory; - private readonly int clientsLimit; private int created; - public FTPClientPool(Func clientFactory, int clientsLimit) - { - this.clientFactory = clientFactory; - this.clientsLimit = clientsLimit; - } - public async Task<(IAsyncFtpClient, bool IsNew)> GetClientAsync( CancellationToken ct) { diff --git a/assets/Squidex.Assets.FTP/Squidex.Assets.FTP.csproj b/assets/Squidex.Assets.FTP/Squidex.Assets.FTP.csproj index eb58548..5297ba5 100644 --- a/assets/Squidex.Assets.FTP/Squidex.Assets.FTP.csproj +++ b/assets/Squidex.Assets.FTP/Squidex.Assets.FTP.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.GoogleCloud/GoogleCloudAssetStore.cs b/assets/Squidex.Assets.GoogleCloud/GoogleCloudAssetStore.cs index 666edf9..aa22c4e 100644 --- a/assets/Squidex.Assets.GoogleCloud/GoogleCloudAssetStore.cs +++ b/assets/Squidex.Assets.GoogleCloud/GoogleCloudAssetStore.cs @@ -14,18 +14,13 @@ namespace Squidex.Assets; -public sealed class GoogleCloudAssetStore : IAssetStore, IInitializable +public sealed class GoogleCloudAssetStore(IOptions options) : IAssetStore, IInitializable { private static readonly UploadObjectOptions IfNotExists = new UploadObjectOptions { IfGenerationMatch = 0 }; private static readonly CopyObjectOptions IfNotExistsCopy = new CopyObjectOptions { IfGenerationMatch = 0 }; - private readonly string bucketName; + private readonly string bucketName = options.Value.Bucket; private StorageClient storageClient; - public GoogleCloudAssetStore(IOptions options) - { - bucketName = options.Value.Bucket; - } - public async Task InitializeAsync( CancellationToken ct) { diff --git a/assets/Squidex.Assets.GoogleCloud/Squidex.Assets.GoogleCloud.csproj b/assets/Squidex.Assets.GoogleCloud/Squidex.Assets.GoogleCloud.csproj index c3f609f..efe37bc 100644 --- a/assets/Squidex.Assets.GoogleCloud/Squidex.Assets.GoogleCloud.csproj +++ b/assets/Squidex.Assets.GoogleCloud/Squidex.Assets.GoogleCloud.csproj @@ -14,7 +14,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.ImageMagick/ImageMagickThumbnailGenerator.cs b/assets/Squidex.Assets.ImageMagick/ImageMagickThumbnailGenerator.cs index ad6ac4f..7a24277 100644 --- a/assets/Squidex.Assets.ImageMagick/ImageMagickThumbnailGenerator.cs +++ b/assets/Squidex.Assets.ImageMagick/ImageMagickThumbnailGenerator.cs @@ -60,16 +60,21 @@ protected override async Task CreateThumbnailCoreAsync(Stream source, string mim var resizeMode = GetResizeMode(options, w, h, image); var resizeAnchor = GetResizeAnchor(options); - var (size, pad) = ResizeHelper.CalculateTargetLocationAndBounds(resizeMode, new Size(image.Width, image.Height), w, h, resizeAnchor); - - var sourceRectangle = new MagickGeometry(pad.Width, pad.Height) + var (size, pad) = ResizeHelper.CalculateTargetLocationAndBounds( + resizeMode, + new Size((int)image.Width, (int)image.Height), + w, + h, + resizeAnchor); + + var sourceRectangle = new MagickGeometry((uint)pad.Width, (uint)pad.Height) { IgnoreAspectRatio = true }; clone.Resize(sourceRectangle); - image.Extent(size.Width, size.Height); + image.Extent((uint)size.Width, (uint)size.Height); image.CompositeClear(color); image.Composite(clone, pad.X, pad.Y, CompositeOperator.Over); } @@ -83,7 +88,7 @@ protected override async Task CreateThumbnailCoreAsync(Stream source, string mim if (options.Quality.HasValue) { - image.Quality = options.Quality.Value; + image.Quality = (uint)options.Quality.Value; } } @@ -134,8 +139,8 @@ protected override async Task FixCoreAsync(Stream source, string mimeType, Strea return Task.FromResult(new ImageInfo( image.Format.ToImageFormat(), - image.Width, - image.Height, + (int)image.Width, + (int)image.Height, image.Orientation.GetOrientation(), hasSensitiveMetadata)); } diff --git a/assets/Squidex.Assets.ImageMagick/Internal/Extensions.cs b/assets/Squidex.Assets.ImageMagick/Internal/Extensions.cs index f599b93..92ae5af 100644 --- a/assets/Squidex.Assets.ImageMagick/Internal/Extensions.cs +++ b/assets/Squidex.Assets.ImageMagick/Internal/Extensions.cs @@ -58,11 +58,11 @@ public static void CompositeClear(this IMagickImage image, MagickColor col var w = Math.Min(BufferSize, image.Width - x); var h = Math.Min(BufferSize, image.Height - y); - var bufferLength = w * h * colorChannels; + var bufferLength = (int)(w * h * colorChannels); var actualBuffer = buffer.AsSpan()[..bufferLength]; - pixels.SetArea(x, y, w, h, actualBuffer); + pixels.SetArea(x, y, (uint)w, (uint)h, actualBuffer); } } } diff --git a/assets/Squidex.Assets.ImageMagick/Internal/StreamFileAbstraction.cs b/assets/Squidex.Assets.ImageMagick/Internal/StreamFileAbstraction.cs index 37849bb..272e056 100644 --- a/assets/Squidex.Assets.ImageMagick/Internal/StreamFileAbstraction.cs +++ b/assets/Squidex.Assets.ImageMagick/Internal/StreamFileAbstraction.cs @@ -11,23 +11,14 @@ namespace Squidex.Assets.Internal; -internal sealed class StreamFileAbstraction : IFileAbstraction +internal sealed class StreamFileAbstraction(Stream stream, string extension) : IFileAbstraction { - private readonly Stream stream; - private readonly string extension; - public string Name => $"image.{extension}"; public Stream ReadStream => stream; public Stream WriteStream => throw new NotSupportedException(); - public StreamFileAbstraction(Stream stream, string extension) - { - this.stream = stream; - this.extension = extension; - } - public void CloseStream(Stream stream) { } diff --git a/assets/Squidex.Assets.ImageMagick/Squidex.Assets.ImageMagick.csproj b/assets/Squidex.Assets.ImageMagick/Squidex.Assets.ImageMagick.csproj index 041005d..99b53cd 100644 --- a/assets/Squidex.Assets.ImageMagick/Squidex.Assets.ImageMagick.csproj +++ b/assets/Squidex.Assets.ImageMagick/Squidex.Assets.ImageMagick.csproj @@ -12,9 +12,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.ImageSharp/ImageSharpThumbnailGenerator.cs b/assets/Squidex.Assets.ImageSharp/ImageSharpThumbnailGenerator.cs index 15edd9d..c6f93a0 100644 --- a/assets/Squidex.Assets.ImageSharp/ImageSharpThumbnailGenerator.cs +++ b/assets/Squidex.Assets.ImageSharp/ImageSharpThumbnailGenerator.cs @@ -30,17 +30,9 @@ namespace Squidex.Assets; -public sealed class ImageSharpThumbnailGenerator : AssetThumbnailGeneratorBase +public sealed class ImageSharpThumbnailGenerator(IHttpClientFactory httpClientFactory) : AssetThumbnailGeneratorBase { - private readonly HashSet mimeTypes; - private readonly IHttpClientFactory httpClientFactory; - - public ImageSharpThumbnailGenerator(IHttpClientFactory httpClientFactory) - { - this.httpClientFactory = httpClientFactory; - - mimeTypes = Configuration.Default.ImageFormatsManager.ImageFormats.SelectMany(x => x.MimeTypes).ToHashSet(); - } + private readonly HashSet mimeTypes = Configuration.Default.ImageFormatsManager.ImageFormats.SelectMany(x => x.MimeTypes).ToHashSet(); public override bool CanReadAndWrite(string mimeType) { diff --git a/assets/Squidex.Assets.ImageSharp/Squidex.Assets.ImageSharp.csproj b/assets/Squidex.Assets.ImageSharp/Squidex.Assets.ImageSharp.csproj index c66577f..d974dd3 100644 --- a/assets/Squidex.Assets.ImageSharp/Squidex.Assets.ImageSharp.csproj +++ b/assets/Squidex.Assets.ImageSharp/Squidex.Assets.ImageSharp.csproj @@ -12,8 +12,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.Mongo/MongoGridFsAssetStore.cs b/assets/Squidex.Assets.Mongo/MongoGridFsAssetStore.cs index c4d3a6b..1f09528 100644 --- a/assets/Squidex.Assets.Mongo/MongoGridFsAssetStore.cs +++ b/assets/Squidex.Assets.Mongo/MongoGridFsAssetStore.cs @@ -12,17 +12,11 @@ namespace Squidex.Assets; -public sealed class MongoGridFsAssetStore : IAssetStore, IInitializable +public sealed class MongoGridFsAssetStore(IGridFSBucket bucket) : IAssetStore, IInitializable { private static readonly FilterDefinitionBuilder> Filters = Builders>.Filter; private static readonly GridFSDownloadOptions DownloadDefault = new GridFSDownloadOptions(); private static readonly GridFSDownloadOptions DownloadSeekable = new GridFSDownloadOptions { Seekable = true }; - private readonly IGridFSBucket bucket; - - public MongoGridFsAssetStore(IGridFSBucket bucket) - { - this.bucket = bucket; - } public async Task InitializeAsync( CancellationToken ct) diff --git a/assets/Squidex.Assets.Mongo/Squidex.Assets.Mongo.csproj b/assets/Squidex.Assets.Mongo/Squidex.Assets.Mongo.csproj index f8e8aaf..795903f 100644 --- a/assets/Squidex.Assets.Mongo/Squidex.Assets.Mongo.csproj +++ b/assets/Squidex.Assets.Mongo/Squidex.Assets.Mongo.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,7 +21,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/assets/Squidex.Assets.ResizeService/ImageResizer.cs b/assets/Squidex.Assets.ResizeService/ImageResizer.cs index 0fcb629..a6d4ef2 100644 --- a/assets/Squidex.Assets.ResizeService/ImageResizer.cs +++ b/assets/Squidex.Assets.ResizeService/ImageResizer.cs @@ -9,15 +9,8 @@ namespace Squidex.Assets.ResizeService; -public sealed class ImageResizer +public sealed class ImageResizer(IAssetThumbnailGenerator assetThumbnailGenerator) { - private readonly IAssetThumbnailGenerator assetThumbnailGenerator; - - public ImageResizer(IAssetThumbnailGenerator assetThumbnailGenerator) - { - this.assetThumbnailGenerator = assetThumbnailGenerator; - } - public void Map(IEndpointRouteBuilder endpoints) { endpoints.MapPost("/blur", BlurAsync); diff --git a/assets/Squidex.Assets.ResizeService/Squidex.Assets.ResizeService.csproj b/assets/Squidex.Assets.ResizeService/Squidex.Assets.ResizeService.csproj index d12cdfb..5797a51 100644 --- a/assets/Squidex.Assets.ResizeService/Squidex.Assets.ResizeService.csproj +++ b/assets/Squidex.Assets.ResizeService/Squidex.Assets.ResizeService.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.ResizeService/Startup.cs b/assets/Squidex.Assets.ResizeService/Startup.cs index 22efe0c..a1f8730 100644 --- a/assets/Squidex.Assets.ResizeService/Startup.cs +++ b/assets/Squidex.Assets.ResizeService/Startup.cs @@ -9,15 +9,8 @@ namespace Squidex.Assets.ResizeService; -public sealed class Startup +public sealed class Startup(IConfiguration configuration) { - private readonly IConfiguration configuration; - - public Startup(IConfiguration configuration) - { - this.configuration = configuration; - } - public void ConfigureServices(IServiceCollection services) { var options = configuration.GetSection("images").Get()!; diff --git a/assets/Squidex.Assets.S3/AmazonS3AssetStore.cs b/assets/Squidex.Assets.S3/AmazonS3AssetStore.cs index 2325de8..0f295be 100644 --- a/assets/Squidex.Assets.S3/AmazonS3AssetStore.cs +++ b/assets/Squidex.Assets.S3/AmazonS3AssetStore.cs @@ -16,19 +16,14 @@ namespace Squidex.Assets; -public sealed class AmazonS3AssetStore : IAssetStore, IInitializable +public sealed class AmazonS3AssetStore(IOptions options) : IAssetStore, IInitializable { private const int BufferSize = 81920; - private readonly AmazonS3AssetOptions options; + private readonly AmazonS3AssetOptions options = options.Value; private TransferUtility s3Transfer; private AmazonS3Client s3Client; private bool canCopy = true; - public AmazonS3AssetStore(IOptions options) - { - this.options = options.Value; - } - public Task ReleaseAsync( CancellationToken ct) { diff --git a/assets/Squidex.Assets.S3/Squidex.Assets.S3.csproj b/assets/Squidex.Assets.S3/Squidex.Assets.S3.csproj index 28cd126..a83dcb3 100644 --- a/assets/Squidex.Assets.S3/Squidex.Assets.S3.csproj +++ b/assets/Squidex.Assets.S3/Squidex.Assets.S3.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.Tests/AmazonS3AssetStoreTests.cs b/assets/Squidex.Assets.Tests/AmazonS3AssetStoreTests.cs index a051a7e..0147038 100644 --- a/assets/Squidex.Assets.Tests/AmazonS3AssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/AmazonS3AssetStoreTests.cs @@ -13,14 +13,9 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class AmazonS3AssetStoreTests : AssetStoreTests, IClassFixture +public class AmazonS3AssetStoreTests(AmazonS3AssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public AmazonS3AssetStoreFixture _ { get; } - - public AmazonS3AssetStoreTests(AmazonS3AssetStoreFixture fixture) - { - _ = fixture; - } + public AmazonS3AssetStoreFixture _ { get; } = fixture; public override AmazonS3AssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/AzureBlobAssetStoreTests.cs b/assets/Squidex.Assets.Tests/AzureBlobAssetStoreTests.cs index 97eadfc..3371ef4 100644 --- a/assets/Squidex.Assets.Tests/AzureBlobAssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/AzureBlobAssetStoreTests.cs @@ -12,14 +12,9 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class AzureBlobAssetStoreTests : AssetStoreTests, IClassFixture +public class AzureBlobAssetStoreTests(AzureBlobAssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public AzureBlobAssetStoreFixture _ { get; } - - public AzureBlobAssetStoreTests(AzureBlobAssetStoreFixture fixture) - { - _ = fixture; - } + public AzureBlobAssetStoreFixture _ { get; } = fixture; public override AzureBlobAssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/CloudflareR2Tests.cs b/assets/Squidex.Assets.Tests/CloudflareR2Tests.cs index 30b344c..01c409d 100644 --- a/assets/Squidex.Assets.Tests/CloudflareR2Tests.cs +++ b/assets/Squidex.Assets.Tests/CloudflareR2Tests.cs @@ -13,14 +13,9 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class CloudflareR2Tests : AssetStoreTests, IClassFixture +public class CloudflareR2Tests(CloudflareR2Fixture fixture) : AssetStoreTests, IClassFixture { - public CloudflareR2Fixture _ { get; } - - public CloudflareR2Tests(CloudflareR2Fixture fixture) - { - _ = fixture; - } + public CloudflareR2Fixture _ { get; } = fixture; public override AmazonS3AssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/FTPAssetStoreTests.cs b/assets/Squidex.Assets.Tests/FTPAssetStoreTests.cs index ce70abb..d25f831 100644 --- a/assets/Squidex.Assets.Tests/FTPAssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/FTPAssetStoreTests.cs @@ -12,19 +12,14 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class FTPAssetStoreTests : AssetStoreTests, IClassFixture +public class FTPAssetStoreTests(FTPAssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public FTPAssetStoreFixture _ { get; } + public FTPAssetStoreFixture _ { get; } = fixture; protected override bool CanUploadStreamsWithoutLength => false; protected override bool CanDeleteAssetsWithPrefix => false; - public FTPAssetStoreTests(FTPAssetStoreFixture fixture) - { - _ = fixture; - } - public override FTPAssetStore CreateStore() { return _.AssetStore; diff --git a/assets/Squidex.Assets.Tests/FolderAssetStoreTests.cs b/assets/Squidex.Assets.Tests/FolderAssetStoreTests.cs index 19bef61..a94793d 100644 --- a/assets/Squidex.Assets.Tests/FolderAssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/FolderAssetStoreTests.cs @@ -13,14 +13,9 @@ namespace Squidex.Assets; -public class FolderAssetStoreTests : AssetStoreTests, IClassFixture +public class FolderAssetStoreTests(FolderAssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public FolderAssetStoreFixture _ { get; } - - public FolderAssetStoreTests(FolderAssetStoreFixture fixture) - { - _ = fixture; - } + public FolderAssetStoreFixture _ { get; } = fixture; public override FolderAssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/GoogleCloudAssetStoreTests.cs b/assets/Squidex.Assets.Tests/GoogleCloudAssetStoreTests.cs index f5c03f5..926983b 100644 --- a/assets/Squidex.Assets.Tests/GoogleCloudAssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/GoogleCloudAssetStoreTests.cs @@ -12,14 +12,9 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class GoogleCloudAssetStoreTests : AssetStoreTests, IClassFixture +public class GoogleCloudAssetStoreTests(GoogleCloudAssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public GoogleCloudAssetStoreFixture _ { get; } - - public GoogleCloudAssetStoreTests(GoogleCloudAssetStoreFixture fixture) - { - _ = fixture; - } + public GoogleCloudAssetStoreFixture _ { get; } = fixture; public override GoogleCloudAssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/MongoGridFsAssetStoreTests.cs b/assets/Squidex.Assets.Tests/MongoGridFsAssetStoreTests.cs index 6b8390d..3059243 100644 --- a/assets/Squidex.Assets.Tests/MongoGridFsAssetStoreTests.cs +++ b/assets/Squidex.Assets.Tests/MongoGridFsAssetStoreTests.cs @@ -12,14 +12,9 @@ namespace Squidex.Assets; [Trait("Category", "Dependencies")] -public class MongoGridFsAssetStoreTests : AssetStoreTests, IClassFixture +public class MongoGridFsAssetStoreTests(MongoGridFSAssetStoreFixture fixture) : AssetStoreTests, IClassFixture { - public MongoGridFSAssetStoreFixture _ { get; } - - public MongoGridFsAssetStoreTests(MongoGridFSAssetStoreFixture fixture) - { - _ = fixture; - } + public MongoGridFSAssetStoreFixture _ { get; } = fixture; public override MongoGridFsAssetStore CreateStore() { diff --git a/assets/Squidex.Assets.Tests/PauseStream.cs b/assets/Squidex.Assets.Tests/PauseStream.cs index 095ea11..9d64bf1 100644 --- a/assets/Squidex.Assets.Tests/PauseStream.cs +++ b/assets/Squidex.Assets.Tests/PauseStream.cs @@ -7,31 +7,25 @@ namespace Squidex.Assets; -public class PauseStream : DelegateStream +public class PauseStream(Stream innerStream, double pauseAfter) : DelegateStream(innerStream) { - private double pauseAfter = 1; + private double pauseTime = pauseAfter; private int totalRead; - public PauseStream(Stream innerStream, double pauseAfter) - : base(innerStream) - { - this.pauseAfter = pauseAfter; - } - public void Reset(double? newPauseAfter = null) { totalRead = 0; if (newPauseAfter.HasValue) { - pauseAfter = newPauseAfter.Value; + pauseTime = newPauseAfter.Value; } } public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { - if (totalRead >= Length * pauseAfter) + if (totalRead >= Length * pauseTime) { return 0; } diff --git a/assets/Squidex.Assets.Tests/Squidex.Assets.Tests.csproj b/assets/Squidex.Assets.Tests/Squidex.Assets.Tests.csproj index 48c4a61..a32bcb7 100644 --- a/assets/Squidex.Assets.Tests/Squidex.Assets.Tests.csproj +++ b/assets/Squidex.Assets.Tests/Squidex.Assets.Tests.csproj @@ -31,15 +31,15 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.Tests/TusController.cs b/assets/Squidex.Assets.Tests/TusController.cs index 457c99e..8e5ea30 100644 --- a/assets/Squidex.Assets.Tests/TusController.cs +++ b/assets/Squidex.Assets.Tests/TusController.cs @@ -9,15 +9,8 @@ namespace Squidex.Assets; -public class TusController : Controller +public class TusController(AssetTusRunner runner) : Controller { - private readonly AssetTusRunner runner; - - public TusController(AssetTusRunner runner) - { - this.runner = runner; - } - #pragma warning disable ASP0018 // Unused route parameter [Route("files/controller/{**catchAll}")] #pragma warning restore ASP0018 // Unused route parameter diff --git a/assets/Squidex.Assets.TusAdapter/AssetTusFile.cs b/assets/Squidex.Assets.TusAdapter/AssetTusFile.cs index 7279856..4598247 100644 --- a/assets/Squidex.Assets.TusAdapter/AssetTusFile.cs +++ b/assets/Squidex.Assets.TusAdapter/AssetTusFile.cs @@ -12,24 +12,28 @@ namespace Squidex.Assets; -public sealed class AssetTusFile : IAssetFile, ITusFile, IAsyncDisposable, IDisposable +public sealed class AssetTusFile( + string id, + TusMetadata tusMetadata, + Dictionary metadata, + Dictionary metadataRaw, + Stream stream, + Action disposed) : IAssetFile, ITusFile, IAsyncDisposable, IDisposable { - private readonly Stream stream; - private readonly Action disposed; - public string Id { get; } + public string Id { get; } = id; - public string FileName { get; } + public string FileName { get; } = GetFileName(metadata); - public string MimeType { get; } + public string MimeType { get; } = GetMimeType(metadata); - public long FileSize { get; } + public long FileSize { get; } = stream.Length; - public Dictionary Metadata { get; } + public Dictionary Metadata { get; } = metadata; - public Dictionary MetadataRaw { get; } + public Dictionary MetadataRaw { get; } = metadataRaw; - internal TusMetadata TusMetadata { get; } + internal TusMetadata TusMetadata { get; } = tusMetadata; public static AssetTusFile Create(string id, TusMetadata tusMetadata, Stream stream, Action disposed) { @@ -45,29 +49,6 @@ public static AssetTusFile Create(string id, TusMetadata tusMetadata, Stream str return new AssetTusFile(id, tusMetadata, metadata, metadataRaw, stream, disposed); } - public AssetTusFile( - string id, - TusMetadata tusMetadata, - Dictionary metadata, - Dictionary metadataRaw, - Stream stream, - Action disposed) - { - Id = id; - - this.stream = stream; - - FileSize = stream.Length; - FileName = GetFileName(metadata); - MimeType = GetMimeType(metadata); - - Metadata = metadata; - MetadataRaw = metadataRaw; - TusMetadata = tusMetadata; - - this.disposed = disposed; - } - private static string GetFileName(Dictionary metadata) { var result = metadata.FirstOrDefault(x => string.Equals(x.Key, "fileName", StringComparison.OrdinalIgnoreCase)).Value; diff --git a/assets/Squidex.Assets.TusAdapter/AssetTusStore.cs b/assets/Squidex.Assets.TusAdapter/AssetTusStore.cs index 54ccbf2..9819317 100644 --- a/assets/Squidex.Assets.TusAdapter/AssetTusStore.cs +++ b/assets/Squidex.Assets.TusAdapter/AssetTusStore.cs @@ -14,7 +14,7 @@ namespace Squidex.Assets; -public sealed class AssetTusStore : +public sealed class AssetTusStore(IAssetStore assetStore, IAssetKeyValueStore keyValueStore) : ITusExpirationStore, ITusCreationDeferLengthStore, ITusCreationStore, @@ -24,14 +24,6 @@ public sealed class AssetTusStore : { private static readonly TimeSpan DefaultExpiration = TimeSpan.FromDays(2); private readonly ConcurrentDictionary> files = new ConcurrentDictionary>(); - private readonly IAssetStore assetStore; - private readonly IAssetKeyValueStore assetKeyValueStore; - - public AssetTusStore(IAssetStore assetStore, IAssetKeyValueStore keyValueStore) - { - this.assetStore = assetStore; - this.assetKeyValueStore = keyValueStore; - } public async Task CreateFileAsync(long uploadLength, string metadata, CancellationToken cancellationToken) @@ -174,7 +166,7 @@ public async Task> GetExpiredFilesAsync( { var result = new List(); - var expirations = assetKeyValueStore.GetExpiredEntriesAsync(DateTimeOffset.UtcNow, cancellationToken); + var expirations = keyValueStore.GetExpiredEntriesAsync(DateTimeOffset.UtcNow, cancellationToken); await foreach (var (_, value) in expirations.WithCancellation(cancellationToken)) { @@ -221,7 +213,7 @@ public async Task GetUploadOffsetAsync(string fileId, { var key = Key(fileId); - return await assetKeyValueStore.GetAsync(key, ct); + return await keyValueStore.GetAsync(key, ct); } public async Task RemoveExpiredFilesAsync( @@ -229,7 +221,7 @@ public async Task RemoveExpiredFilesAsync( { var deletionCount = 0; - var expirations = assetKeyValueStore.GetExpiredEntriesAsync(DateTimeOffset.UtcNow, cancellationToken); + var expirations = keyValueStore.GetExpiredEntriesAsync(DateTimeOffset.UtcNow, cancellationToken); await foreach (var (_, expiration) in expirations.WithCancellation(cancellationToken)) { @@ -260,7 +252,7 @@ private async Task CleanupAsync(TusMetadata metadata, await assetStore.DeleteAsync(PartName(metadata.Id, i), cancellationToken); } - await assetKeyValueStore.DeleteAsync(Key(metadata.Id), cancellationToken); + await keyValueStore.DeleteAsync(Key(metadata.Id), cancellationToken); } private Task SetMetadataAsync(string fileId, TusMetadata metadata, @@ -275,7 +267,7 @@ private Task SetMetadataAsync(string fileId, TusMetadata metadata, metadata.Expires = DateTimeOffset.UtcNow.Add(DefaultExpiration); } - return assetKeyValueStore.SetAsync(key, metadata, metadata.Expires!.Value, ct); + return keyValueStore.SetAsync(key, metadata, metadata.Expires!.Value, ct); } private static string PartName(string fileId, int index) diff --git a/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLock.cs b/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLock.cs index c7b0099..e8f6a91 100644 --- a/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLock.cs +++ b/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLock.cs @@ -10,17 +10,9 @@ namespace Squidex.Assets.Internal; -internal sealed class AssetFileLock : ITusFileLock +internal sealed class AssetFileLock(IAssetStore assetStore, string fileId) : ITusFileLock { - private readonly IAssetStore assetStore; - private readonly string filePath; - - public AssetFileLock(IAssetStore assetStore, string fileId) - { - this.assetStore = assetStore; - - filePath = $"locks/{fileId}.lock"; - } + private readonly string filePath = $"locks/{fileId}.lock"; public async Task Lock() { diff --git a/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLockProvider.cs b/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLockProvider.cs index d928407..090bb96 100644 --- a/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLockProvider.cs +++ b/assets/Squidex.Assets.TusAdapter/Internal/AssetFileLockProvider.cs @@ -9,15 +9,8 @@ namespace Squidex.Assets.Internal; -public sealed class AssetFileLockProvider : ITusFileLockProvider +public sealed class AssetFileLockProvider(IAssetStore assetStore) : ITusFileLockProvider { - private readonly IAssetStore assetStore; - - public AssetFileLockProvider(IAssetStore assetStore) - { - this.assetStore = assetStore; - } - public Task AquireLock(string fileId) { return Task.FromResult(new AssetFileLock(assetStore, fileId)); diff --git a/assets/Squidex.Assets.TusAdapter/Internal/CancellableStream.cs b/assets/Squidex.Assets.TusAdapter/Internal/CancellableStream.cs index 01a2ab5..77c0ad5 100644 --- a/assets/Squidex.Assets.TusAdapter/Internal/CancellableStream.cs +++ b/assets/Squidex.Assets.TusAdapter/Internal/CancellableStream.cs @@ -9,10 +9,9 @@ namespace Squidex.Assets.Internal; -internal sealed class CancellableStream : DelegateStream +internal sealed class CancellableStream(Stream innerStream, + CancellationToken cancellationToken) : DelegateStream(innerStream) { - private readonly CancellationToken cancellationToken; - public override long Length { get => throw new NotSupportedException(); @@ -23,13 +22,6 @@ public override bool CanWrite get => false; } - public CancellableStream(Stream innerStream, - CancellationToken cancellationToken) - : base(innerStream) - { - this.cancellationToken = cancellationToken; - } - public override int Read(byte[] buffer, int offset, int count) { if (cancellationToken.IsCancellationRequested) diff --git a/assets/Squidex.Assets.TusAdapter/Squidex.Assets.TusAdapter.csproj b/assets/Squidex.Assets.TusAdapter/Squidex.Assets.TusAdapter.csproj index e36bd4f..cb7dce6 100644 --- a/assets/Squidex.Assets.TusAdapter/Squidex.Assets.TusAdapter.csproj +++ b/assets/Squidex.Assets.TusAdapter/Squidex.Assets.TusAdapter.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.TusAdapter/TusActionResult.cs b/assets/Squidex.Assets.TusAdapter/TusActionResult.cs index 3b30550..d33662b 100644 --- a/assets/Squidex.Assets.TusAdapter/TusActionResult.cs +++ b/assets/Squidex.Assets.TusAdapter/TusActionResult.cs @@ -10,21 +10,14 @@ namespace Squidex.Assets; -internal sealed class TusActionResult : IActionResult +internal sealed class TusActionResult(HttpResponse response) : IActionResult { - private readonly HttpResponse response; - public int StatusCode => response.StatusCode; public IHeaderDictionary Headers => response.Headers; public Stream Body => response.Body; - public TusActionResult(HttpResponse response) - { - this.response = response; - } - public void ApplyHeaders(HttpContext context) { foreach (var (key, value) in Headers) diff --git a/assets/Squidex.Assets.TusClient/IProgressHandler.cs b/assets/Squidex.Assets.TusClient/IProgressHandler.cs index 0ee8c5d..0a13065 100644 --- a/assets/Squidex.Assets.TusClient/IProgressHandler.cs +++ b/assets/Squidex.Assets.TusClient/IProgressHandler.cs @@ -9,65 +9,34 @@ namespace Squidex.Assets; -public abstract class UploadEvent +public abstract class UploadEvent(string fileId) { - public string FileId { get; } - - protected UploadEvent(string fileId) - { - FileId = fileId; - } + public string FileId { get; } = fileId; } -public sealed class UploadProgressEvent : UploadEvent +public sealed class UploadProgressEvent(string fileId, int progress, long bytesWritten, long bytesTotal) : UploadEvent(fileId) { - public int Progress { get; } - - public long BytesWritten { get; } + public int Progress { get; } = progress; - public long BytesTotal { get; } + public long BytesWritten { get; } = bytesWritten; - public UploadProgressEvent(string fileId, int progress, long bytesWritten, long bytesTotal) - : base(fileId) - { - Progress = progress; - BytesWritten = bytesWritten; - BytesTotal = bytesTotal; - } + public long BytesTotal { get; } = bytesTotal; } -public sealed class UploadCompletedEvent : UploadEvent +public sealed class UploadCompletedEvent(string fileId, HttpResponseMessage response) : UploadEvent(fileId) { - public HttpResponseMessage Response { get; } - - public UploadCompletedEvent(string fileId, HttpResponseMessage response) - : base(fileId) - { - Response = response; - } + public HttpResponseMessage Response { get; } = response; } -public sealed class UploadCreatedEvent : UploadEvent +public sealed class UploadCreatedEvent(string fileId) : UploadEvent(fileId) { - public UploadCreatedEvent(string fileId) - : base(fileId) - { - } } -public sealed class UploadExceptionEvent : UploadEvent +public sealed class UploadExceptionEvent(string fileId, Exception exception, HttpResponseMessage? response) : UploadEvent(fileId) { - public HttpResponseMessage? Response { get; } - - public Exception Exception { get; } - - public UploadExceptionEvent(string fileId, Exception exception, HttpResponseMessage? response) - : base(fileId) - { - Exception = exception; + public HttpResponseMessage? Response { get; } = response; - Response = response; - } + public Exception Exception { get; } = exception; } public interface IProgressHandler diff --git a/assets/Squidex.Assets.TusClient/Internal/ProgressableStreamContent.cs b/assets/Squidex.Assets.TusClient/Internal/ProgressableStreamContent.cs index 5ae42c5..770fdc6 100644 --- a/assets/Squidex.Assets.TusClient/Internal/ProgressableStreamContent.cs +++ b/assets/Squidex.Assets.TusClient/Internal/ProgressableStreamContent.cs @@ -9,27 +9,15 @@ namespace Squidex.Assets.Internal; -internal sealed class ProgressableStreamContent : HttpContent +internal sealed class ProgressableStreamContent(Stream content, int uploadBufferSize, Func uploadProgress) : HttpContent { - private readonly Stream content; - private readonly int uploadBufferSize; - private readonly long uploadLength; - private readonly Func uploadProgress; + private readonly long uploadLength = content.Length - content.Position; public ProgressableStreamContent(Stream content, Func uploadProgress) : this(content, 4096, uploadProgress) { } - public ProgressableStreamContent(Stream content, int uploadBufferSize, Func uploadProgress) - { - this.content = content; - this.uploadBufferSize = uploadBufferSize; - this.uploadProgress = uploadProgress; - - uploadLength = content.Length - content.Position; - } - protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) { return SerializeToStreamAsync(stream, default); diff --git a/assets/Squidex.Assets.TusClient/Squidex.Assets.TusClient.csproj b/assets/Squidex.Assets.TusClient/Squidex.Assets.TusClient.csproj index 7efee4c..767bac5 100644 --- a/assets/Squidex.Assets.TusClient/Squidex.Assets.TusClient.csproj +++ b/assets/Squidex.Assets.TusClient/Squidex.Assets.TusClient.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/assets/Squidex.Assets.TusClient/UploadFile.cs b/assets/Squidex.Assets.TusClient/UploadFile.cs index f8f6183..4af74db 100644 --- a/assets/Squidex.Assets.TusClient/UploadFile.cs +++ b/assets/Squidex.Assets.TusClient/UploadFile.cs @@ -9,23 +9,15 @@ namespace Squidex.Assets; -public sealed class UploadFile +public sealed class UploadFile(Stream stream, string fileName, string contentType, long contentLength) { - public Stream Stream { get; } + public Stream Stream { get; } = stream; - public string FileName { get; } + public string FileName { get; } = fileName; - public string ContentType { get; } + public string ContentType { get; } = contentType; - public long ContentLength { get; } - - public UploadFile(Stream stream, string fileName, string contentType, long contentLength) - { - Stream = stream; - FileName = fileName; - ContentType = contentType; - ContentLength = contentLength; - } + public long ContentLength { get; } = contentLength; public static UploadFile FromFile(FileInfo fileInfo, string? mimeType = null) { diff --git a/assets/Squidex.Assets/AssetAlreadyExistsException.cs b/assets/Squidex.Assets/AssetAlreadyExistsException.cs index 721d0bc..bed8b53 100644 --- a/assets/Squidex.Assets/AssetAlreadyExistsException.cs +++ b/assets/Squidex.Assets/AssetAlreadyExistsException.cs @@ -8,13 +8,8 @@ namespace Squidex.Assets; [Serializable] -public class AssetAlreadyExistsException : Exception +public class AssetAlreadyExistsException(string fileName, Exception? inner = null) : Exception(FormatMessage(fileName), inner) { - public AssetAlreadyExistsException(string fileName, Exception? inner = null) - : base(FormatMessage(fileName), inner) - { - } - private static string FormatMessage(string fileName) { ArgumentException.ThrowIfNullOrWhiteSpace(fileName); diff --git a/assets/Squidex.Assets/AssetNotFoundException.cs b/assets/Squidex.Assets/AssetNotFoundException.cs index 024651c..f3a33ff 100644 --- a/assets/Squidex.Assets/AssetNotFoundException.cs +++ b/assets/Squidex.Assets/AssetNotFoundException.cs @@ -8,13 +8,8 @@ namespace Squidex.Assets; [Serializable] -public class AssetNotFoundException : Exception +public class AssetNotFoundException(string fileName, Exception? inner = null) : Exception(FormatMessage(fileName), inner) { - public AssetNotFoundException(string fileName, Exception? inner = null) - : base(FormatMessage(fileName), inner) - { - } - private static string FormatMessage(string fileName) { ArgumentException.ThrowIfNullOrWhiteSpace(fileName); diff --git a/assets/Squidex.Assets/BytesRange.cs b/assets/Squidex.Assets/BytesRange.cs index 9129bf0..5c0af9c 100644 --- a/assets/Squidex.Assets/BytesRange.cs +++ b/assets/Squidex.Assets/BytesRange.cs @@ -7,11 +7,11 @@ namespace Squidex.Assets; -public readonly struct BytesRange +public readonly struct BytesRange(long? from, long? to) { - public readonly long? From; + public readonly long? From = from; - public readonly long? To; + public readonly long? To = to; public long Length { @@ -38,13 +38,6 @@ public bool IsDefined get { return (From >= 0 || To >= 0) && Length > 0; } } - public BytesRange(long? from, long? to) - { - From = from; - - To = to; - } - public override string? ToString() { if (Length == 0) diff --git a/assets/Squidex.Assets/FolderAssetStore.cs b/assets/Squidex.Assets/FolderAssetStore.cs index d910697..0ebacfe 100644 --- a/assets/Squidex.Assets/FolderAssetStore.cs +++ b/assets/Squidex.Assets/FolderAssetStore.cs @@ -11,18 +11,10 @@ namespace Squidex.Assets; -public sealed class FolderAssetStore : IAssetStore, IInitializable +public sealed class FolderAssetStore(IOptions options, ILogger log) : IAssetStore, IInitializable { private const int BufferSize = 81920; - private readonly ILogger log; - private readonly DirectoryInfo directory; - - public FolderAssetStore(IOptions options, ILogger log) - { - this.log = log; - - directory = new DirectoryInfo(options.Value.Path); - } + private readonly DirectoryInfo directory = new DirectoryInfo(options.Value.Path); public Task InitializeAsync( CancellationToken ct) diff --git a/assets/Squidex.Assets/Remote/RemoteThumbnailGenerator.cs b/assets/Squidex.Assets/Remote/RemoteThumbnailGenerator.cs index ef46eb2..574c959 100644 --- a/assets/Squidex.Assets/Remote/RemoteThumbnailGenerator.cs +++ b/assets/Squidex.Assets/Remote/RemoteThumbnailGenerator.cs @@ -11,18 +11,8 @@ namespace Squidex.Assets.Remote; -public sealed class RemoteThumbnailGenerator : AssetThumbnailGeneratorBase +public sealed class RemoteThumbnailGenerator(IHttpClientFactory httpClientFactory, IAssetThumbnailGenerator inner) : AssetThumbnailGeneratorBase { - private readonly IHttpClientFactory httpClientFactory; - private readonly IAssetThumbnailGenerator inner; - - public RemoteThumbnailGenerator(IHttpClientFactory httpClientFactory, IAssetThumbnailGenerator inner) - { - this.httpClientFactory = httpClientFactory; - - this.inner = inner; - } - public override bool CanReadAndWrite(string mimeType) { return inner.CanReadAndWrite(mimeType); diff --git a/assets/Squidex.Assets/Squidex.Assets.csproj b/assets/Squidex.Assets/Squidex.Assets.csproj index 69ac9a3..079d806 100644 --- a/assets/Squidex.Assets/Squidex.Assets.csproj +++ b/assets/Squidex.Assets/Squidex.Assets.csproj @@ -12,19 +12,19 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/assets/TusTestServer/Controller/TusController.cs b/assets/TusTestServer/Controller/TusController.cs index 999637a..ada8145 100644 --- a/assets/TusTestServer/Controller/TusController.cs +++ b/assets/TusTestServer/Controller/TusController.cs @@ -10,16 +10,10 @@ namespace TusTestServer.Controller; -public class TusController : ControllerBase +public class TusController(AssetTusRunner runner) : ControllerBase { - private readonly AssetTusRunner runner; private readonly Uri uploadUri = new Uri("http://localhost:4000/files/controller"); - public TusController(AssetTusRunner runner) - { - this.runner = runner; - } - [Route("/upload")] public async Task UploadAsync() { @@ -136,11 +130,11 @@ public Task OnFailedAsync(UploadExceptionEvent @event, } } - public class PauseStream : DelegateStream + public class PauseStream(Stream innerStream, double pauseAfter) : DelegateStream(innerStream) { - private readonly int maxLength; + private readonly int maxLength = (int)Math.Floor(innerStream.Length * pauseAfter) + 1; private long totalRead; - private long totalRemaining; + private long totalRemaining = innerStream.Length; private long seekStart; public override long Length @@ -154,14 +148,6 @@ public override long Position set => throw new NotSupportedException(); } - public PauseStream(Stream innerStream, double pauseAfter) - : base(innerStream) - { - maxLength = (int)Math.Floor(innerStream.Length * pauseAfter) + 1; - - totalRemaining = innerStream.Length; - } - public override long Seek(long offset, SeekOrigin origin) { var position = seekStart = base.Seek(offset, origin); diff --git a/assets/TusTestServer/TusTestServer.csproj b/assets/TusTestServer/TusTestServer.csproj index 441ffd0..96478ea 100644 --- a/assets/TusTestServer/TusTestServer.csproj +++ b/assets/TusTestServer/TusTestServer.csproj @@ -9,11 +9,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/caching/Squidex.Caching.Tests/Squidex.Caching.Tests.csproj b/caching/Squidex.Caching.Tests/Squidex.Caching.Tests.csproj index 8c089b8..a90556e 100644 --- a/caching/Squidex.Caching.Tests/Squidex.Caching.Tests.csproj +++ b/caching/Squidex.Caching.Tests/Squidex.Caching.Tests.csproj @@ -11,13 +11,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/caching/Squidex.Caching/AsyncLocalCleaner.cs b/caching/Squidex.Caching/AsyncLocalCleaner.cs index ef69252..aee29eb 100644 --- a/caching/Squidex.Caching/AsyncLocalCleaner.cs +++ b/caching/Squidex.Caching/AsyncLocalCleaner.cs @@ -7,15 +7,8 @@ namespace Squidex.Caching; -internal sealed class AsyncLocalCleaner : IDisposable +internal sealed class AsyncLocalCleaner(AsyncLocal asyncLocal) : IDisposable { - private readonly AsyncLocal asyncLocal; - - public AsyncLocalCleaner(AsyncLocal asyncLocal) - { - this.asyncLocal = asyncLocal; - } - public void Dispose() { asyncLocal.Value = default!; diff --git a/caching/Squidex.Caching/BackgroundCache.cs b/caching/Squidex.Caching/BackgroundCache.cs index a64e4a6..8caf0fe 100644 --- a/caching/Squidex.Caching/BackgroundCache.cs +++ b/caching/Squidex.Caching/BackgroundCache.cs @@ -17,18 +17,11 @@ public sealed class BackgroundCache : IBackgroundCache private readonly ConcurrentDictionary isUpdating = new ConcurrentDictionary(); private readonly IMemoryCache memoryCache; - private sealed class Entry + private sealed class Entry(Task value, DateTimeOffset expires) { - public Task Value { get; } + public Task Value { get; } = value; - public DateTimeOffset Expires { get; } - - public Entry(Task value, DateTimeOffset expires) - { - Value = value; - - Expires = expires; - } + public DateTimeOffset Expires { get; } = expires; } public Func? Clock { get; set; } diff --git a/caching/Squidex.Caching/ReplicatedCache.cs b/caching/Squidex.Caching/ReplicatedCache.cs index eb85750..e821bb8 100644 --- a/caching/Squidex.Caching/ReplicatedCache.cs +++ b/caching/Squidex.Caching/ReplicatedCache.cs @@ -10,19 +10,10 @@ namespace Squidex.Caching; -public sealed class ReplicatedCache : IReplicatedCache, IMessageHandler +public sealed class ReplicatedCache(IMemoryCache memoryCache, IMessageBus messageBus) : IReplicatedCache, IMessageHandler { - private readonly IMemoryCache memoryCache; - private readonly IMessageBus messageBus; - public Guid InstanceId { get; } = Guid.NewGuid(); - public ReplicatedCache(IMemoryCache memoryCache, IMessageBus messageBus) - { - this.memoryCache = memoryCache; - this.messageBus = messageBus; - } - public Task HandleAsync(CacheInvalidateMessage message, CancellationToken ct) { diff --git a/caching/Squidex.Caching/Squidex.Caching.csproj b/caching/Squidex.Caching/Squidex.Caching.csproj index 62c5f2a..236524c 100644 --- a/caching/Squidex.Caching/Squidex.Caching.csproj +++ b/caching/Squidex.Caching/Squidex.Caching.csproj @@ -12,13 +12,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + all diff --git a/hosting/Squidex.Hosting.Abstractions/Configuration/ConfigurationException.cs b/hosting/Squidex.Hosting.Abstractions/Configuration/ConfigurationException.cs index efebe71..bf63f60 100644 --- a/hosting/Squidex.Hosting.Abstractions/Configuration/ConfigurationException.cs +++ b/hosting/Squidex.Hosting.Abstractions/Configuration/ConfigurationException.cs @@ -10,21 +10,15 @@ namespace Squidex.Hosting.Configuration; [Serializable] -public class ConfigurationException : Exception +public class ConfigurationException(IReadOnlyList errors, Exception? inner = null) : Exception(FormatMessage(errors), inner) { - public IReadOnlyList Errors { get; } + public IReadOnlyList Errors { get; } = errors; public ConfigurationException(ConfigurationError error, Exception? inner = null) : this([error], inner) { } - public ConfigurationException(IReadOnlyList errors, Exception? inner = null) - : base(FormatMessage(errors), inner) - { - Errors = errors; - } - private static string FormatMessage(IReadOnlyList errors) { ArgumentNullException.ThrowIfNull(errors); diff --git a/hosting/Squidex.Hosting.Abstractions/Configuration/OptionsErrorProvider.cs b/hosting/Squidex.Hosting.Abstractions/Configuration/OptionsErrorProvider.cs index 36c2a6f..ba244b5 100644 --- a/hosting/Squidex.Hosting.Abstractions/Configuration/OptionsErrorProvider.cs +++ b/hosting/Squidex.Hosting.Abstractions/Configuration/OptionsErrorProvider.cs @@ -10,17 +10,8 @@ namespace Squidex.Hosting.Configuration; -public sealed class OptionsErrorProvider : IErrorProvider, IValidateOptions where T : class, IValidatableOptions +public sealed class OptionsErrorProvider(IOptions options, string prefix) : IErrorProvider, IValidateOptions where T : class, IValidatableOptions { - private readonly IOptions options; - private readonly string prefix; - - public OptionsErrorProvider(IOptions options, string prefix) - { - this.options = options; - this.prefix = prefix; - } - public IEnumerable GetErrors() { return GetErrors(options.Value); diff --git a/hosting/Squidex.Hosting.Abstractions/Configuration/ValidationInitializer.cs b/hosting/Squidex.Hosting.Abstractions/Configuration/ValidationInitializer.cs index 3501674..7e42bec 100644 --- a/hosting/Squidex.Hosting.Abstractions/Configuration/ValidationInitializer.cs +++ b/hosting/Squidex.Hosting.Abstractions/Configuration/ValidationInitializer.cs @@ -7,17 +7,10 @@ namespace Squidex.Hosting.Configuration; -public sealed class ValidationInitializer : IInitializable +public sealed class ValidationInitializer(IEnumerable errorProviders) : IInitializable { - private readonly IEnumerable errorProviders; - public int Order => int.MinValue; - public ValidationInitializer(IEnumerable errorProviders) - { - this.errorProviders = errorProviders; - } - public Task InitializeAsync( CancellationToken ct) { diff --git a/hosting/Squidex.Hosting.Abstractions/Squidex.Hosting.Abstractions.csproj b/hosting/Squidex.Hosting.Abstractions/Squidex.Hosting.Abstractions.csproj index 3438633..351314c 100644 --- a/hosting/Squidex.Hosting.Abstractions/Squidex.Hosting.Abstractions.csproj +++ b/hosting/Squidex.Hosting.Abstractions/Squidex.Hosting.Abstractions.csproj @@ -13,13 +13,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/hosting/Squidex.Hosting.TestRunner/EmbedMiddleware.cs b/hosting/Squidex.Hosting.TestRunner/EmbedMiddleware.cs index 68a3594..836bb39 100644 --- a/hosting/Squidex.Hosting.TestRunner/EmbedMiddleware.cs +++ b/hosting/Squidex.Hosting.TestRunner/EmbedMiddleware.cs @@ -7,15 +7,8 @@ namespace Squidex.Hosting; -public sealed class EmbedMiddleware +public sealed class EmbedMiddleware(RequestDelegate next) { - private readonly RequestDelegate next; - - public EmbedMiddleware(RequestDelegate next) - { - this.next = next; - } - public Task InvokeAsync(HttpContext context) { var request = context.Request; diff --git a/hosting/Squidex.Hosting.TestRunner/Squidex.Hosting.TestRunner.csproj b/hosting/Squidex.Hosting.TestRunner/Squidex.Hosting.TestRunner.csproj index 1213edf..632f540 100644 --- a/hosting/Squidex.Hosting.TestRunner/Squidex.Hosting.TestRunner.csproj +++ b/hosting/Squidex.Hosting.TestRunner/Squidex.Hosting.TestRunner.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/hosting/Squidex.Hosting.TestRunner/Startup.cs b/hosting/Squidex.Hosting.TestRunner/Startup.cs index c3cf13b..bb11d83 100644 --- a/hosting/Squidex.Hosting.TestRunner/Startup.cs +++ b/hosting/Squidex.Hosting.TestRunner/Startup.cs @@ -11,15 +11,8 @@ namespace Squidex.Hosting; -public sealed class Startup +public sealed class Startup(IConfiguration configuration) { - private readonly IConfiguration configuration; - - public Startup(IConfiguration configuration) - { - this.configuration = configuration; - } - public void ConfigureServices(IServiceCollection services) { services.AddSingletonAs(_ => JsonLogWriterFactory.Readable()) diff --git a/hosting/Squidex.Hosting.Tests/ServiceRegistrationTests.cs b/hosting/Squidex.Hosting.Tests/ServiceRegistrationTests.cs index 2f1ca0d..e1558b3 100644 --- a/hosting/Squidex.Hosting.Tests/ServiceRegistrationTests.cs +++ b/hosting/Squidex.Hosting.Tests/ServiceRegistrationTests.cs @@ -30,14 +30,9 @@ private sealed class ServiceWrapped : IWrapped, IInterface1, IInterface2 public IWrapped? Inner => null; } - private sealed class ServiceWrapper : IWrapped + private sealed class ServiceWrapper(ServiceRegistrationTests.IWrapped inner) : IWrapped { - public IWrapped? Inner { get; } - - public ServiceWrapper(IWrapped inner) - { - Inner = inner; - } + public IWrapped? Inner { get; } = inner; } [Fact] diff --git a/hosting/Squidex.Hosting.Tests/Squidex.Hosting.Tests.csproj b/hosting/Squidex.Hosting.Tests/Squidex.Hosting.Tests.csproj index 44d5f5c..492d36f 100644 --- a/hosting/Squidex.Hosting.Tests/Squidex.Hosting.Tests.csproj +++ b/hosting/Squidex.Hosting.Tests/Squidex.Hosting.Tests.csproj @@ -14,17 +14,17 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/hosting/Squidex.Hosting/BackgroundHost.cs b/hosting/Squidex.Hosting/BackgroundHost.cs index 89b75cc..f48fbbe 100644 --- a/hosting/Squidex.Hosting/BackgroundHost.cs +++ b/hosting/Squidex.Hosting/BackgroundHost.cs @@ -10,13 +10,8 @@ namespace Squidex.Hosting; -public sealed class BackgroundHost : SystemHost, IHostedService +public sealed class BackgroundHost(ISemanticLog log, IEnumerable systems) : SystemHost(log, systems), IHostedService { - public BackgroundHost(ISemanticLog log, IEnumerable systems) - : base(log, systems) - { - } - public async Task StartAsync( CancellationToken cancellationToken) { diff --git a/hosting/Squidex.Hosting/DelegateInitializer.cs b/hosting/Squidex.Hosting/DelegateInitializer.cs index 88e24c3..d728570 100644 --- a/hosting/Squidex.Hosting/DelegateInitializer.cs +++ b/hosting/Squidex.Hosting/DelegateInitializer.cs @@ -7,25 +7,12 @@ namespace Squidex.Hosting; -public sealed class DelegateInitializer : IInitializable +public sealed class DelegateInitializer(IServiceProvider serviceProvider, string name, int order, Func action) : IInitializable { - private readonly IServiceProvider serviceProvider; - private readonly string name; - private readonly int order; - private readonly Func action; - public string Name => name; public int Order => order; - public DelegateInitializer(IServiceProvider serviceProvider, string name, int order, Func action) - { - this.serviceProvider = serviceProvider; - this.name = name; - this.order = order; - this.action = action; - } - public Task InitializeAsync( CancellationToken ct) { diff --git a/hosting/Squidex.Hosting/DelegateInitializer{T}.cs b/hosting/Squidex.Hosting/DelegateInitializer{T}.cs index eb300dc..431e110 100644 --- a/hosting/Squidex.Hosting/DelegateInitializer{T}.cs +++ b/hosting/Squidex.Hosting/DelegateInitializer{T}.cs @@ -9,25 +9,12 @@ namespace Squidex.Hosting; -public sealed class DelegateInitializer : IInitializable where T : class +public sealed class DelegateInitializer(IServiceProvider serviceProvider, string name, int order, Func action) : IInitializable where T : class { - private readonly IServiceProvider serviceProvider; - private readonly string name; - private readonly int order; - private readonly Func action; - public string Name => name; public int Order => order; - public DelegateInitializer(IServiceProvider serviceProvider, string name, int order, Func action) - { - this.serviceProvider = serviceProvider; - this.name = name; - this.order = order; - this.action = action; - } - public Task InitializeAsync( CancellationToken ct) { diff --git a/hosting/Squidex.Hosting/InitializerHost.cs b/hosting/Squidex.Hosting/InitializerHost.cs index 1d5bdd9..5be72d4 100644 --- a/hosting/Squidex.Hosting/InitializerHost.cs +++ b/hosting/Squidex.Hosting/InitializerHost.cs @@ -10,13 +10,8 @@ namespace Squidex.Hosting; -public sealed class InitializerHost : SystemHost, IHostedService +public sealed class InitializerHost(ISemanticLog log, IEnumerable systems) : SystemHost(log, systems), IHostedService { - public InitializerHost(ISemanticLog log, IEnumerable systems) - : base(log, systems) - { - } - public async Task StartAsync( CancellationToken cancellationToken) { diff --git a/hosting/Squidex.Hosting/Squidex.Hosting.csproj b/hosting/Squidex.Hosting/Squidex.Hosting.csproj index 73efc6f..5f30a2f 100644 --- a/hosting/Squidex.Hosting/Squidex.Hosting.csproj +++ b/hosting/Squidex.Hosting/Squidex.Hosting.csproj @@ -16,7 +16,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/hosting/Squidex.Hosting/SystemHost.cs b/hosting/Squidex.Hosting/SystemHost.cs index 713dcfd..ccc2f38 100644 --- a/hosting/Squidex.Hosting/SystemHost.cs +++ b/hosting/Squidex.Hosting/SystemHost.cs @@ -9,23 +9,16 @@ namespace Squidex.Hosting; -public abstract class SystemHost where T : ISystem +public abstract class SystemHost(ISemanticLog log, IEnumerable systems) where T : ISystem { - protected IReadOnlyList<(T System, string Name)> Systems { get; } - - protected ISemanticLog Log { get; } - - protected SystemHost(ISemanticLog log, IEnumerable systems) - { - Log = log; - - Systems = + protected IReadOnlyList<(T System, string Name)> Systems { get; } = systems.Distinct() .Select(x => (System: x, Name: GetName(x))) .OrderBy(x => x.System.Order) .ThenBy(x => x.Name) .ToList(); - } + + protected ISemanticLog Log { get; } = log; private static string GetName(T system) { diff --git a/hosting/Squidex.Hosting/Web/CleanupHostMiddleware.cs b/hosting/Squidex.Hosting/Web/CleanupHostMiddleware.cs index 81165c5..eedab3d 100644 --- a/hosting/Squidex.Hosting/Web/CleanupHostMiddleware.cs +++ b/hosting/Squidex.Hosting/Web/CleanupHostMiddleware.cs @@ -9,15 +9,8 @@ namespace Squidex.Hosting.Web; -public sealed class CleanupHostMiddleware +public sealed class CleanupHostMiddleware(RequestDelegate next) { - private readonly RequestDelegate next; - - public CleanupHostMiddleware(RequestDelegate next) - { - this.next = next; - } - public Task InvokeAsync(HttpContext context) { var request = context.Request; diff --git a/hosting/Squidex.Hosting/Web/ConfigureForwardedHeaders.cs b/hosting/Squidex.Hosting/Web/ConfigureForwardedHeaders.cs index 5919945..8396df8 100644 --- a/hosting/Squidex.Hosting/Web/ConfigureForwardedHeaders.cs +++ b/hosting/Squidex.Hosting/Web/ConfigureForwardedHeaders.cs @@ -12,16 +12,9 @@ namespace Squidex.Hosting.Web; -public sealed class ConfigureForwardedHeaders : IConfigureOptions +public sealed class ConfigureForwardedHeaders(IOptions urlOptions, IUrlGenerator urlGenerator) : IConfigureOptions { - private readonly UrlOptions urlOptions; - private readonly IUrlGenerator urlGenerator; - - public ConfigureForwardedHeaders(IOptions urlOptions, IUrlGenerator urlGenerator) - { - this.urlOptions = urlOptions.Value; - this.urlGenerator = urlGenerator; - } + private readonly UrlOptions urlOptions = urlOptions.Value; public void Configure(ForwardedHeadersOptions options) { diff --git a/hosting/Squidex.Hosting/Web/ConfigureHttpsRedirection.cs b/hosting/Squidex.Hosting/Web/ConfigureHttpsRedirection.cs index 7ae05ed..0d47142 100644 --- a/hosting/Squidex.Hosting/Web/ConfigureHttpsRedirection.cs +++ b/hosting/Squidex.Hosting/Web/ConfigureHttpsRedirection.cs @@ -10,14 +10,9 @@ namespace Squidex.Hosting.Web; -public sealed class ConfigureHttpsRedirection : IConfigureOptions +public sealed class ConfigureHttpsRedirection(IOptions urlOptions) : IConfigureOptions { - private readonly UrlOptions urlOptions; - - public ConfigureHttpsRedirection(IOptions urlOptions) - { - this.urlOptions = urlOptions.Value; - } + private readonly UrlOptions urlOptions = urlOptions.Value; public void Configure(HttpsRedirectionOptions options) { diff --git a/hosting/Squidex.Hosting/Web/HtmlTransformMiddleware.cs b/hosting/Squidex.Hosting/Web/HtmlTransformMiddleware.cs index 001bc52..5a13b37 100644 --- a/hosting/Squidex.Hosting/Web/HtmlTransformMiddleware.cs +++ b/hosting/Squidex.Hosting/Web/HtmlTransformMiddleware.cs @@ -11,22 +11,12 @@ namespace Squidex.Hosting.Web; -public sealed class HtmlTransformMiddleware +public sealed class HtmlTransformMiddleware(HtmlTransformOptions options, RequestDelegate next) { - private readonly HtmlTransformOptions options; - private readonly RequestDelegate next; - - public HtmlTransformMiddleware(HtmlTransformOptions options, RequestDelegate next) - { - this.options = options; - this.next = next; - } - - private sealed class BufferStream : Stream + private sealed class BufferStream(HttpContext context) : Stream { private static readonly RecyclableMemoryStreamManager Buffers = new RecyclableMemoryStreamManager(); - private readonly Stream originalBody; - private readonly HttpContext context; + private readonly Stream originalBody = context.Response.Body; private bool writingStarted; private MemoryStream? memoryStream; @@ -45,14 +35,6 @@ private Stream ActualStream get => memoryStream ?? originalBody; } - public BufferStream(HttpContext context) - { - this.context = context; - - // Keep an instance of the original body, because the body will be replaced later. - this.originalBody = context.Response.Body; - } - public async Task CompleteAsync(HtmlTransformOptions options) { if (memoryStream == null || memoryStream.Length == 0) @@ -85,7 +67,7 @@ public async Task CompleteAsync(HtmlTransformOptions options) } finally { - this.context.Response.Body = originalBody; + context.Response.Body = originalBody; } } diff --git a/log/Squidex.Log.Tests/Squidex.Log.Tests.csproj b/log/Squidex.Log.Tests/Squidex.Log.Tests.csproj index ba9f3bd..d77c008 100644 --- a/log/Squidex.Log.Tests/Squidex.Log.Tests.csproj +++ b/log/Squidex.Log.Tests/Squidex.Log.Tests.csproj @@ -15,14 +15,14 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/log/Squidex.Log/Adapter/CategoryNameAppender.cs b/log/Squidex.Log/Adapter/CategoryNameAppender.cs index a870102..f00e57a 100644 --- a/log/Squidex.Log/Adapter/CategoryNameAppender.cs +++ b/log/Squidex.Log/Adapter/CategoryNameAppender.cs @@ -7,15 +7,8 @@ namespace Squidex.Log.Adapter; -public sealed class CategoryNameAppender : ILogAppender +public sealed class CategoryNameAppender(string category) : ILogAppender { - private readonly string category; - - public CategoryNameAppender(string category) - { - this.category = category; - } - public void Append(IObjectWriter writer, SemanticLogLevel logLevel, Exception? exception) { writer.WriteProperty(nameof(category), category); diff --git a/log/Squidex.Log/Adapter/SemanticLogLogger.cs b/log/Squidex.Log/Adapter/SemanticLogLogger.cs index 6fe585c..b911390 100644 --- a/log/Squidex.Log/Adapter/SemanticLogLogger.cs +++ b/log/Squidex.Log/Adapter/SemanticLogLogger.cs @@ -10,15 +10,8 @@ namespace Squidex.Log.Adapter; -internal sealed class SemanticLogLogger : ILogger +internal sealed class SemanticLogLogger(ISemanticLog semanticLog) : ILogger { - private readonly ISemanticLog semanticLog; - - public SemanticLogLogger(ISemanticLog semanticLog) - { - this.semanticLog = semanticLog; - } - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { SemanticLogLevel semanticLogLevel; diff --git a/log/Squidex.Log/ConsoleLogChannel.cs b/log/Squidex.Log/ConsoleLogChannel.cs index 771b660..0466d28 100644 --- a/log/Squidex.Log/ConsoleLogChannel.cs +++ b/log/Squidex.Log/ConsoleLogChannel.cs @@ -9,15 +9,9 @@ namespace Squidex.Log; -public sealed class ConsoleLogChannel : ILogChannel, IDisposable +public sealed class ConsoleLogChannel(bool useColors = false) : ILogChannel, IDisposable { private readonly ConsoleLogProcessor processor = new ConsoleLogProcessor(); - private readonly bool useColors; - - public ConsoleLogChannel(bool useColors = false) - { - this.useColors = useColors; - } public void Dispose() { diff --git a/log/Squidex.Log/Internal/AnsiLogConsole.cs b/log/Squidex.Log/Internal/AnsiLogConsole.cs index b6638b2..3ccb7d8 100644 --- a/log/Squidex.Log/Internal/AnsiLogConsole.cs +++ b/log/Squidex.Log/Internal/AnsiLogConsole.cs @@ -10,15 +10,8 @@ namespace Squidex.Log.Internal; [ExcludeFromCodeCoverage] -public sealed class AnsiLogConsole : IConsole +public sealed class AnsiLogConsole(bool logToStdError) : IConsole { - private readonly bool logToStdError; - - public AnsiLogConsole(bool logToStdError) - { - this.logToStdError = logToStdError; - } - public void Reset() { } diff --git a/log/Squidex.Log/Internal/WindowsLogConsole.cs b/log/Squidex.Log/Internal/WindowsLogConsole.cs index 06d4509..d1948fb 100644 --- a/log/Squidex.Log/Internal/WindowsLogConsole.cs +++ b/log/Squidex.Log/Internal/WindowsLogConsole.cs @@ -10,15 +10,8 @@ namespace Squidex.Log.Internal; [ExcludeFromCodeCoverage] -public sealed class WindowsLogConsole : IConsole +public sealed class WindowsLogConsole(bool logToStdError) : IConsole { - private readonly bool logToStdError; - - public WindowsLogConsole(bool logToStdError) - { - this.logToStdError = logToStdError; - } - public void Reset() { Console.ResetColor(); diff --git a/log/Squidex.Log/JsonLogWriterFactory.cs b/log/Squidex.Log/JsonLogWriterFactory.cs index 8294c8c..05e78d9 100644 --- a/log/Squidex.Log/JsonLogWriterFactory.cs +++ b/log/Squidex.Log/JsonLogWriterFactory.cs @@ -10,9 +10,9 @@ namespace Squidex.Log; -public sealed class JsonLogWriterFactory : IRootWriterFactory +public sealed class JsonLogWriterFactory(bool indended = false, bool formatLine = false) : IRootWriterFactory { - private readonly ObjectPool writerPool; + private readonly ObjectPool writerPool = new DefaultObjectPoolProvider().Create(new JsonLogWriterPolicy(indended, formatLine)); internal sealed class JsonLogWriterPolicy : PooledObjectPolicy { @@ -45,11 +45,6 @@ public override bool Return(JsonLogWriter obj) } } - public JsonLogWriterFactory(bool indended = false, bool formatLine = false) - { - writerPool = new DefaultObjectPoolProvider().Create(new JsonLogWriterPolicy(indended, formatLine)); - } - public static JsonLogWriterFactory Default() { return new JsonLogWriterFactory(); diff --git a/log/Squidex.Log/Squidex.Log.csproj b/log/Squidex.Log/Squidex.Log.csproj index 7d0769f..80b2e50 100644 --- a/log/Squidex.Log/Squidex.Log.csproj +++ b/log/Squidex.Log/Squidex.Log.csproj @@ -12,12 +12,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all diff --git a/log/Squidex.Log/TimestampLogAppender.cs b/log/Squidex.Log/TimestampLogAppender.cs index 4734421..4bc3761 100644 --- a/log/Squidex.Log/TimestampLogAppender.cs +++ b/log/Squidex.Log/TimestampLogAppender.cs @@ -7,20 +7,15 @@ namespace Squidex.Log; -public sealed class TimestampLogAppender : ILogAppender +public sealed class TimestampLogAppender(Func? clock = null) : ILogAppender { - private readonly Func clock; + private readonly Func clock = clock ?? (() => DateTime.UtcNow); public TimestampLogAppender() : this(null) { } - public TimestampLogAppender(Func? clock = null) - { - this.clock = clock ?? (() => DateTime.UtcNow); - } - public void Append(IObjectWriter writer, SemanticLogLevel logLevel, Exception? exception) { writer.WriteProperty("timestamp", clock()); diff --git a/log/Squidex.Log/ValueStopwatch.cs b/log/Squidex.Log/ValueStopwatch.cs index b630335..2e585f7 100644 --- a/log/Squidex.Log/ValueStopwatch.cs +++ b/log/Squidex.Log/ValueStopwatch.cs @@ -9,15 +9,13 @@ namespace Squidex.Log; -internal readonly struct ValueStopwatch +internal readonly struct ValueStopwatch(long startTime) { private const long TicksPerMillisecond = 10000; private const long TicksPerSecond = TicksPerMillisecond * 1000; private static readonly double TickFrequency; - private readonly long startTime; - static ValueStopwatch() { if (Stopwatch.IsHighResolution) @@ -26,11 +24,6 @@ static ValueStopwatch() } } - public ValueStopwatch(long startTime) - { - this.startTime = startTime; - } - public static ValueStopwatch StartNew() { return new ValueStopwatch(Stopwatch.GetTimestamp()); diff --git a/messaging/Squidex.Messaging.All/Squidex.Messaging.All.csproj b/messaging/Squidex.Messaging.All/Squidex.Messaging.All.csproj index f4d3e55..64b9362 100644 --- a/messaging/Squidex.Messaging.All/Squidex.Messaging.All.csproj +++ b/messaging/Squidex.Messaging.All/Squidex.Messaging.All.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/messaging/Squidex.Messaging.GoogleCloud/GooglePubSubTransport.cs b/messaging/Squidex.Messaging.GoogleCloud/GooglePubSubTransport.cs index 11498a1..68f0aa4 100644 --- a/messaging/Squidex.Messaging.GoogleCloud/GooglePubSubTransport.cs +++ b/messaging/Squidex.Messaging.GoogleCloud/GooglePubSubTransport.cs @@ -16,22 +16,14 @@ namespace Squidex.Messaging.GoogleCloud; -public sealed class GooglePubSubTransport : IMessagingTransport +public sealed class GooglePubSubTransport(IOptions options, + ILogger log) : IMessagingTransport { private readonly Dictionary> publishers = []; - private readonly GooglePubSubTransportOptions options; + private readonly GooglePubSubTransportOptions options = options.Value; private readonly GooglePushConfig pushConfig = new GooglePushConfig(); private readonly HashSet createdSubcriptions = []; private readonly HashSet createdTopics = []; - private readonly ILogger log; - - public GooglePubSubTransport(IOptions options, - ILogger log) - { - this.options = options.Value; - - this.log = log; - } public Task InitializeAsync( CancellationToken ct) diff --git a/messaging/Squidex.Messaging.GoogleCloud/Squidex.Messaging.GoogleCloud.csproj b/messaging/Squidex.Messaging.GoogleCloud/Squidex.Messaging.GoogleCloud.csproj index 6e5f0a9..93b8f5e 100644 --- a/messaging/Squidex.Messaging.GoogleCloud/Squidex.Messaging.GoogleCloud.csproj +++ b/messaging/Squidex.Messaging.GoogleCloud/Squidex.Messaging.GoogleCloud.csproj @@ -12,8 +12,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/messaging/Squidex.Messaging.Kafka/KafkaOwner.cs b/messaging/Squidex.Messaging.Kafka/KafkaOwner.cs index e89e982..d58c0c5 100644 --- a/messaging/Squidex.Messaging.Kafka/KafkaOwner.cs +++ b/messaging/Squidex.Messaging.Kafka/KafkaOwner.cs @@ -11,26 +11,19 @@ namespace Squidex.Messaging.Kafka; -public sealed class KafkaOwner +public sealed class KafkaOwner(IOptions options, + ILogger log) { - private readonly IProducer producer; - - public Handle Handle => producer.Handle; - - public KafkaTransportOptions Options { get; } - - public KafkaOwner(IOptions options, - ILogger log) - { - Options = options.Value; - - producer = + private readonly IProducer producer = new ProducerBuilder(options.Value) .SetLogHandler(KafkaLogFactory.ProducerLog(log)) .SetErrorHandler(KafkaLogFactory.ProducerError(log)) .SetStatisticsHandler(KafkaLogFactory.ProducerStats(log)) .Build(); - } + + public Handle Handle => producer.Handle; + + public KafkaTransportOptions Options { get; } = options.Value; public void Dispose() { diff --git a/messaging/Squidex.Messaging.Kafka/KafkaTransport.cs b/messaging/Squidex.Messaging.Kafka/KafkaTransport.cs index fa1480e..1a4858a 100644 --- a/messaging/Squidex.Messaging.Kafka/KafkaTransport.cs +++ b/messaging/Squidex.Messaging.Kafka/KafkaTransport.cs @@ -12,20 +12,11 @@ namespace Squidex.Messaging.Kafka; -public sealed class KafkaTransport : IMessagingTransport +public sealed class KafkaTransport(KafkaOwner owner, + ILogger log) : IMessagingTransport { - private readonly KafkaOwner owner; - private readonly ILogger log; private IProducer? producer; - public KafkaTransport(KafkaOwner owner, - ILogger log) - { - this.owner = owner; - - this.log = log; - } - public Task InitializeAsync( CancellationToken ct) { diff --git a/messaging/Squidex.Messaging.Kafka/Squidex.Messaging.Kafka.csproj b/messaging/Squidex.Messaging.Kafka/Squidex.Messaging.Kafka.csproj index 60b6ecc..a2a4ecd 100644 --- a/messaging/Squidex.Messaging.Kafka/Squidex.Messaging.Kafka.csproj +++ b/messaging/Squidex.Messaging.Kafka/Squidex.Messaging.Kafka.csproj @@ -12,8 +12,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/messaging/Squidex.Messaging.Mongo/MongoMessagingDataStore.cs b/messaging/Squidex.Messaging.Mongo/MongoMessagingDataStore.cs index c907fbb..e924ca4 100644 --- a/messaging/Squidex.Messaging.Mongo/MongoMessagingDataStore.cs +++ b/messaging/Squidex.Messaging.Mongo/MongoMessagingDataStore.cs @@ -11,9 +11,9 @@ namespace Squidex.Messaging.Mongo; -public sealed class MongoMessagingDataStore : IMessagingDataStore, IInitializable +public sealed class MongoMessagingDataStore(IMongoDatabase database, IOptions options) : IMessagingDataStore, IInitializable { - private readonly IMongoCollection collection; + private readonly IMongoCollection collection = database.GetCollection(options.Value.CollectionName); private sealed class Entity { @@ -32,11 +32,6 @@ private sealed class Entity public DateTime Expiration { get; set; } } - public MongoMessagingDataStore(IMongoDatabase database, IOptions options) - { - collection = database.GetCollection(options.Value.CollectionName); - } - public Task InitializeAsync( CancellationToken ct) { diff --git a/messaging/Squidex.Messaging.Mongo/MongoTransport.cs b/messaging/Squidex.Messaging.Mongo/MongoTransport.cs index f5386f1..3071a2a 100644 --- a/messaging/Squidex.Messaging.Mongo/MongoTransport.cs +++ b/messaging/Squidex.Messaging.Mongo/MongoTransport.cs @@ -13,28 +13,15 @@ namespace Squidex.Messaging.Mongo; -public sealed class MongoTransport : IMessagingTransport +public sealed class MongoTransport( + IMongoDatabase database, + IMessagingDataProvider messagingDataProvider, + IOptions options, + TimeProvider timeProvider, + ILogger log) : IMessagingTransport { private readonly Dictionary>> collections = []; - private readonly MongoTransportOptions options; - private readonly IMongoDatabase database; - private readonly IMessagingDataProvider messagingDataProvider; - private readonly TimeProvider timeProvider; - private readonly ILogger log; - - public MongoTransport( - IMongoDatabase database, - IMessagingDataProvider messagingDataProvider, - IOptions options, - TimeProvider timeProvider, - ILogger log) - { - this.options = options.Value; - this.database = database; - this.messagingDataProvider = messagingDataProvider; - this.timeProvider = timeProvider; - this.log = log; - } + private readonly MongoTransportOptions options = options.Value; public Task InitializeAsync( CancellationToken ct) diff --git a/messaging/Squidex.Messaging.Mongo/MongoTransportCleaner.cs b/messaging/Squidex.Messaging.Mongo/MongoTransportCleaner.cs index 07332c5..64efbff 100644 --- a/messaging/Squidex.Messaging.Mongo/MongoTransportCleaner.cs +++ b/messaging/Squidex.Messaging.Mongo/MongoTransportCleaner.cs @@ -11,18 +11,14 @@ namespace Squidex.Messaging.Mongo; -internal sealed class MongoTransportCleaner : IAsyncDisposable +internal sealed class MongoTransportCleaner(IMongoCollection collection, string collectionName, + TimeSpan timeout, + TimeSpan expires, + TimeSpan updateInterval, + ILogger log, + TimeProvider timeProvider) : IAsyncDisposable { - private readonly SimpleTimer timer; - - public MongoTransportCleaner(IMongoCollection collection, string collectionName, - TimeSpan timeout, - TimeSpan expires, - TimeSpan updateInterval, - ILogger log, - TimeProvider timeProvider) - { - timer = new SimpleTimer(async ct => + private readonly SimpleTimer timer = new SimpleTimer(async ct => { var now = timeProvider.GetUtcNow().UtcDateTime; @@ -40,7 +36,6 @@ public MongoTransportCleaner(IMongoCollection collection, string c log.LogInformation("{collectionName}: Items reset: {count}.", collectionName, update.ModifiedCount); } }, updateInterval, log); - } public ValueTask DisposeAsync() { diff --git a/messaging/Squidex.Messaging.Mongo/Squidex.Messaging.Mongo.csproj b/messaging/Squidex.Messaging.Mongo/Squidex.Messaging.Mongo.csproj index d9e092c..fb50b59 100644 --- a/messaging/Squidex.Messaging.Mongo/Squidex.Messaging.Mongo.csproj +++ b/messaging/Squidex.Messaging.Mongo/Squidex.Messaging.Mongo.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -20,7 +20,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/messaging/Squidex.Messaging.RabbitMq/RabbitMqOwner.cs b/messaging/Squidex.Messaging.RabbitMq/RabbitMqOwner.cs index b552241..ab4333f 100644 --- a/messaging/Squidex.Messaging.RabbitMq/RabbitMqOwner.cs +++ b/messaging/Squidex.Messaging.RabbitMq/RabbitMqOwner.cs @@ -12,7 +12,7 @@ namespace Squidex.Messaging.RabbitMq; public sealed class RabbitMqOwner { - public IConnection Connection { get; } + public Task Connection { get; } public RabbitMqTransportOptions Options { get; } @@ -23,11 +23,16 @@ public RabbitMqOwner(IOptions options) var connectionFactory = new ConnectionFactory { Uri = options.Value.Uri, - - // Of course we want an asynchronous behavior. - DispatchConsumersAsync = true }; - Connection = connectionFactory.CreateConnection(); + Connection = connectionFactory.CreateConnectionAsync(); + } + + public async Task CreateChannelAsync( + CancellationToken ct) + { + var connection = await Connection; + + return await connection.CreateChannelAsync(cancellationToken: ct); } } diff --git a/messaging/Squidex.Messaging.RabbitMq/RabbitMqSubscription.cs b/messaging/Squidex.Messaging.RabbitMq/RabbitMqSubscription.cs index 34aa64c..229281d 100644 --- a/messaging/Squidex.Messaging.RabbitMq/RabbitMqSubscription.cs +++ b/messaging/Squidex.Messaging.RabbitMq/RabbitMqSubscription.cs @@ -15,35 +15,56 @@ namespace Squidex.Messaging.RabbitMq; internal sealed class RabbitMqSubscription : IMessageAck, IAsyncDisposable { private readonly CancellationTokenSource stopToken = new CancellationTokenSource(); - private readonly IModel model; private readonly string queueName; - private readonly string consumerTag; + private readonly IChannel channel; private readonly ILogger log; + private string consumerTag; - public RabbitMqSubscription(string queueName, RabbitMqOwner factory, - MessageTransportCallback callback, ILogger log) + private RabbitMqSubscription(string queueName, IChannel channel, ILogger log) { this.queueName = queueName; + this.channel = channel; + this.log = log; + } + + public static async Task OpenAsync( + string queueName, RabbitMqOwner + factory, + MessageTransportCallback callback, + ILogger log, + CancellationToken ct) + { + var rabbitMqChannel = await factory.CreateChannelAsync(ct); + var rabbitMqSubscription = new RabbitMqSubscription(queueName, rabbitMqChannel, log); - model = factory.Connection.CreateModel(); + await rabbitMqSubscription.StartAsync(callback, ct); - var eventConsumer = new AsyncEventingBasicConsumer(model); + return rabbitMqSubscription; + } - eventConsumer.Received += async (_, @event) => + internal async Task StartAsync(MessageTransportCallback callback, + CancellationToken ct) + { + var eventConsumer = new AsyncEventingBasicConsumer(channel); + + eventConsumer.ReceivedAsync += async (_, @event) => { try { var headers = new TransportHeaders(); - foreach (var (key, value) in @event.BasicProperties.Headers) + if (@event.BasicProperties.Headers != null) { - if (value is byte[] bytes) - { - headers[key] = Encoding.UTF8.GetString(bytes); - } - else if (value is string text) + foreach (var (key, value) in @event.BasicProperties.Headers) { - headers[key] = text; + if (value is byte[] bytes) + { + headers[key] = Encoding.UTF8.GetString(bytes); + } + else if (value is string text) + { + headers[key] = text; + } } } @@ -58,68 +79,67 @@ public RabbitMqSubscription(string queueName, RabbitMqOwner factory, } }; - consumerTag = model.BasicConsume(queueName, false, eventConsumer); - - this.log = log; + consumerTag = await channel.BasicConsumeAsync(queueName, false, eventConsumer, ct); } public async ValueTask DisposeAsync() { await stopToken.CancelAsync(); - - model.BasicCancel(consumerTag); - model.Dispose(); + try + { + await channel.BasicCancelAsync(consumerTag, cancellationToken: default); + } + finally + { + channel.Dispose(); + } } - public Task OnErrorAsync(TransportResult result, + public async Task OnErrorAsync(TransportResult result, CancellationToken ct) { if (stopToken.IsCancellationRequested) { - return Task.CompletedTask; + return; } if (result.Data is not ulong deliverTag) { log.LogWarning("Transport message has no RabbitMq delivery tag."); - return Task.CompletedTask; + return; } try { - model.BasicReject(deliverTag, false); + await channel.BasicRejectAsync(deliverTag, false, ct); } catch (Exception ex) { log.LogError(ex, "Failed to acknowledge message from queue {queue}.", queueName); } - - return Task.CompletedTask; } - public Task OnSuccessAsync(TransportResult result, + public async Task OnSuccessAsync(TransportResult result, CancellationToken ct) { if (stopToken.IsCancellationRequested) { - return Task.CompletedTask; + return; } if (result.Data is not ulong deliverTag) { log.LogWarning("Transport message has no RabbitMq delivery tag."); - return Task.CompletedTask; + return; } try { - model.BasicAck(deliverTag, false); + await channel.BasicAckAsync(deliverTag, false, ct); } catch (Exception ex) { log.LogError(ex, "Failed to reject message from queue {queue}.", queueName); } - - return Task.CompletedTask; } } diff --git a/messaging/Squidex.Messaging.RabbitMq/RabbitMqTransport.cs b/messaging/Squidex.Messaging.RabbitMq/RabbitMqTransport.cs index ca2d245..960fe0a 100644 --- a/messaging/Squidex.Messaging.RabbitMq/RabbitMqTransport.cs +++ b/messaging/Squidex.Messaging.RabbitMq/RabbitMqTransport.cs @@ -11,88 +11,84 @@ namespace Squidex.Messaging.RabbitMq; -public sealed class RabbitMqTransport : IMessagingTransport +public sealed class RabbitMqTransport(RabbitMqOwner owner, + ILogger log) : IMessagingTransport { - private readonly RabbitMqOwner owner; - private readonly ILogger log; private readonly HashSet createdQueues = []; - private IModel? model; + private readonly SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1); + private IChannel? channelModel; - public RabbitMqTransport(RabbitMqOwner owner, - ILogger log) - { - this.owner = owner; - - this.log = log; - } - - public Task InitializeAsync( + public async Task InitializeAsync( CancellationToken ct) { - if (model != null) + if (channelModel != null) { - return Task.CompletedTask; + return; } - model = owner.Connection.CreateModel(); - - return Task.CompletedTask; + channelModel = await owner.CreateChannelAsync(ct); } public Task ReleaseAsync( CancellationToken ct) { - if (model == null) + if (channelModel == null) { return Task.CompletedTask; } - model.Dispose(); - model = null; + channelModel.Dispose(); + channelModel = null; return Task.CompletedTask; } - public Task CreateChannelAsync(ChannelName channel, string instanceName, bool consume, ProducerOptions producerOptions, + public async Task CreateChannelAsync(ChannelName channel, string instanceName, bool consume, ProducerOptions producerOptions, CancellationToken ct) { - if (model == null) + if (channelModel == null) { ThrowHelper.InvalidOperationException("Transport not initialized yet."); - return Task.FromResult(null); + return null; } - lock (model) + await semaphoreSlim.WaitAsync(ct); + try { if (channel.Type == ChannelType.Queue) { - model.QueueDeclare(channel.Name, true, false, false, null); + await channelModel.QueueDeclareAsync(channel.Name, true, false, false, null, cancellationToken: ct); } else { - model.ExchangeDeclare(channel.Name, "fanout", true, false, null); + await channelModel.ExchangeDeclareAsync(channel.Name, "fanout", true, false, null, cancellationToken: ct); } } + finally + { + semaphoreSlim.Release(); + } - return Task.FromResult(null); + return null; } - public Task ProduceAsync(ChannelName channel, string instanceName, TransportMessage transportMessage, + public async Task ProduceAsync(ChannelName channel, string instanceName, TransportMessage transportMessage, CancellationToken ct) { - if (model == null) + if (channelModel == null) { ThrowHelper.InvalidOperationException("Transport not initialized yet."); - return Task.CompletedTask; + return; } - lock (model) + await semaphoreSlim.WaitAsync(ct); + try { - var properties = model.CreateBasicProperties(); + var properties = new BasicProperties(); if (transportMessage.Headers.Count > 0) { - properties.Headers = new Dictionary(); + properties.Headers = new Dictionary(); foreach (var (key, value) in transportMessage.Headers) { @@ -102,26 +98,23 @@ public Task ProduceAsync(ChannelName channel, string instanceName, TransportMess if (channel.Type == ChannelType.Queue) { - model.BasicPublish(string.Empty, channel.Name, properties, transportMessage.Data); + await channelModel.BasicPublishAsync(string.Empty, channel.Name, false, properties, transportMessage.Data, ct); } else { - model.BasicPublish(channel.Name, "*", properties, transportMessage.Data); + await channelModel.BasicPublishAsync(channel.Name, "*", false, properties, transportMessage.Data, ct); } } - - return Task.CompletedTask; + finally + { + semaphoreSlim.Release(); + } } - public Task SubscribeAsync(ChannelName channel, string instanceName, MessageTransportCallback callback, + public async Task SubscribeAsync(ChannelName channel, string instanceName, MessageTransportCallback callback, CancellationToken ct) { - return Task.FromResult(SubscribeCore(channel, instanceName, callback)); - } - - private RabbitMqSubscription SubscribeCore(ChannelName channel, string instanceName, MessageTransportCallback callback) - { - if (model == null) + if (channelModel == null) { ThrowHelper.InvalidOperationException("Transport not initialized yet."); return null!; @@ -131,13 +124,14 @@ private RabbitMqSubscription SubscribeCore(ChannelName channel, string instanceN if (channel.Type == ChannelType.Topic) { - queueName = CreateTemporaryQueue(channel, instanceName); + queueName = await CreateTemporaryQueueAsync(channel, instanceName, ct); } - return new RabbitMqSubscription(queueName, owner, callback, log); + return await RabbitMqSubscription.OpenAsync(queueName, owner, callback, log, ct); } - private string CreateTemporaryQueue(ChannelName channel, string instanceName) + private async Task CreateTemporaryQueueAsync(ChannelName channel, string instanceName, + CancellationToken ct) { var queueName = $"{channel.Name}_{instanceName}"; @@ -146,13 +140,16 @@ private string CreateTemporaryQueue(ChannelName channel, string instanceName) return queueName; } - lock (model!) + await semaphoreSlim.WaitAsync(ct); + try { // Create a queue that only lives as long as the client is connected. - model.QueueDeclare(queueName); - - // Bind the queue to the exchange. - model.QueueBind(queueName, channel.Name, "*"); + await channelModel!.QueueDeclareAsync(queueName, cancellationToken: ct); + await channelModel!.QueueBindAsync(queueName, channel.Name, "*", cancellationToken: ct); + } + finally + { + semaphoreSlim.Release(); } return queueName; diff --git a/messaging/Squidex.Messaging.RabbitMq/Squidex.Messaging.RabbitMq.csproj b/messaging/Squidex.Messaging.RabbitMq/Squidex.Messaging.RabbitMq.csproj index a223669..0a7a2ef 100644 --- a/messaging/Squidex.Messaging.RabbitMq/Squidex.Messaging.RabbitMq.csproj +++ b/messaging/Squidex.Messaging.RabbitMq/Squidex.Messaging.RabbitMq.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -20,7 +20,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/messaging/Squidex.Messaging.Redis/LoggerTextWriter.cs b/messaging/Squidex.Messaging.Redis/LoggerTextWriter.cs index 14305ff..462e226 100644 --- a/messaging/Squidex.Messaging.Redis/LoggerTextWriter.cs +++ b/messaging/Squidex.Messaging.Redis/LoggerTextWriter.cs @@ -10,15 +10,8 @@ namespace Squidex.Messaging.Redis; -internal sealed class LoggerTextWriter : TextWriter +internal sealed class LoggerTextWriter(ILogger log) : TextWriter { - private readonly ILogger log; - - public LoggerTextWriter(ILogger log) - { - this.log = log; - } - public override Encoding Encoding => Encoding.UTF8; public override void Write(char value) diff --git a/messaging/Squidex.Messaging.Redis/RedisTransport.cs b/messaging/Squidex.Messaging.Redis/RedisTransport.cs index 1dbc831..ef646f5 100644 --- a/messaging/Squidex.Messaging.Redis/RedisTransport.cs +++ b/messaging/Squidex.Messaging.Redis/RedisTransport.cs @@ -13,21 +13,13 @@ namespace Squidex.Messaging.Redis; -public sealed class RedisTransport : IMessagingTransport +public sealed class RedisTransport(IOptions options, + ILogger log) : IMessagingTransport { - private readonly ILogger log; - private readonly RedisTransportOptions options; + private readonly RedisTransportOptions options = options.Value; private ISubscriber? subscriber; private IDatabase? database; - public RedisTransport(IOptions options, - ILogger log) - { - this.options = options.Value; - - this.log = log; - } - public async Task InitializeAsync( CancellationToken ct) { diff --git a/messaging/Squidex.Messaging.Redis/Squidex.Messaging.Redis.csproj b/messaging/Squidex.Messaging.Redis/Squidex.Messaging.Redis.csproj index 8f8753f..a73d935 100644 --- a/messaging/Squidex.Messaging.Redis/Squidex.Messaging.Redis.csproj +++ b/messaging/Squidex.Messaging.Redis/Squidex.Messaging.Redis.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -21,7 +21,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/messaging/Squidex.Messaging.Subscriptions/Implementation/SubscriptionService.cs b/messaging/Squidex.Messaging.Subscriptions/Implementation/SubscriptionService.cs index eb1866f..222146f 100644 --- a/messaging/Squidex.Messaging.Subscriptions/Implementation/SubscriptionService.cs +++ b/messaging/Squidex.Messaging.Subscriptions/Implementation/SubscriptionService.cs @@ -15,28 +15,16 @@ namespace Squidex.Messaging.Subscriptions.Implementation; -public sealed class SubscriptionService : ISubscriptionService, IMessageHandler +public sealed class SubscriptionService( + IInstanceNameProvider instanceName, + IMessageBus messageBus, + IMessagingDataProvider messagingDataProvider, + IOptions options, + ILogger log) : ISubscriptionService, IMessageHandler { private readonly ConcurrentDictionary localSubscriptions = []; - private readonly SubscriptionOptions options; - private readonly string instanceName; - private readonly IMessageBus messageBus; - private readonly IMessagingDataProvider messagingDataProvider; - private readonly ILogger log; - - public SubscriptionService( - IInstanceNameProvider instanceName, - IMessageBus messageBus, - IMessagingDataProvider messagingDataProvider, - IOptions options, - ILogger log) - { - this.instanceName = instanceName.Name; - this.messageBus = messageBus; - this.messagingDataProvider = messagingDataProvider; - this.options = options.Value; - this.log = log; - } + private readonly SubscriptionOptions options = options.Value; + private readonly string instanceName = instanceName.Name; public async Task HasSubscriptionsAsync(string key, CancellationToken ct = default) diff --git a/messaging/Squidex.Messaging.Subscriptions/Squidex.Messaging.Subscriptions.csproj b/messaging/Squidex.Messaging.Subscriptions/Squidex.Messaging.Subscriptions.csproj index 37de1bc..e105c4f 100644 --- a/messaging/Squidex.Messaging.Subscriptions/Squidex.Messaging.Subscriptions.csproj +++ b/messaging/Squidex.Messaging.Subscriptions/Squidex.Messaging.Subscriptions.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/messaging/Squidex.Messaging.Tests/Internal/Types.cs b/messaging/Squidex.Messaging.Tests/Internal/Types.cs index cfc58e3..d2d2366 100644 --- a/messaging/Squidex.Messaging.Tests/Internal/Types.cs +++ b/messaging/Squidex.Messaging.Tests/Internal/Types.cs @@ -14,23 +14,12 @@ public sealed class TestValue(string value) public string Value { get; } = value; } -public sealed class TestMessage : BaseMessage +public sealed class TestMessage(Guid testId, int value) : BaseMessage(testId) { - public int Value { get; } - - public TestMessage(Guid testId, int value) - : base(testId) - { - Value = value; - } + public int Value { get; } = value; } -public abstract class BaseMessage +public abstract class BaseMessage(Guid testId) { - public Guid TestId { get; } - - protected BaseMessage(Guid testId) - { - TestId = testId; - } + public Guid TestId { get; } = testId; } diff --git a/messaging/Squidex.Messaging.Tests/MongoMessagingPrefetchTests.cs b/messaging/Squidex.Messaging.Tests/MongoMessagingPrefetchTests.cs index 2b02466..df15be4 100644 --- a/messaging/Squidex.Messaging.Tests/MongoMessagingPrefetchTests.cs +++ b/messaging/Squidex.Messaging.Tests/MongoMessagingPrefetchTests.cs @@ -11,14 +11,9 @@ namespace Squidex.Messaging; -public class MongoMessagingPrefetchTests : MessagingTestsBase, IClassFixture +public class MongoMessagingPrefetchTests(MongoFixture fixture) : MessagingTestsBase, IClassFixture { - public MongoFixture _ { get; } - - public MongoMessagingPrefetchTests(MongoFixture fixture) - { - _ = fixture; - } + public MongoFixture _ { get; } = fixture; protected override void Configure(MessagingBuilder builder) { diff --git a/messaging/Squidex.Messaging.Tests/MongoMessagingTests.cs b/messaging/Squidex.Messaging.Tests/MongoMessagingTests.cs index ce45ec4..1aff121 100644 --- a/messaging/Squidex.Messaging.Tests/MongoMessagingTests.cs +++ b/messaging/Squidex.Messaging.Tests/MongoMessagingTests.cs @@ -11,14 +11,9 @@ namespace Squidex.Messaging; -public class MongoMessagingTests : MessagingTestsBase, IClassFixture +public class MongoMessagingTests(MongoFixture fixture) : MessagingTestsBase, IClassFixture { - public MongoFixture _ { get; } - - public MongoMessagingTests(MongoFixture fixture) - { - _ = fixture; - } + public MongoFixture _ { get; } = fixture; protected override void Configure(MessagingBuilder builder) { diff --git a/messaging/Squidex.Messaging.Tests/MongoSubscriptionStoreTests.cs b/messaging/Squidex.Messaging.Tests/MongoSubscriptionStoreTests.cs index cbc3a3a..d8ffbd6 100644 --- a/messaging/Squidex.Messaging.Tests/MongoSubscriptionStoreTests.cs +++ b/messaging/Squidex.Messaging.Tests/MongoSubscriptionStoreTests.cs @@ -12,14 +12,9 @@ namespace Squidex.Messaging; [Trait("Category", "Dependencies")] -public class MongoSubscriptionStoreTests : SubscriptionStoreTestsBase, IClassFixture +public class MongoSubscriptionStoreTests(MongoFixture fixture) : SubscriptionStoreTestsBase, IClassFixture { - public MongoFixture _ { get; } - - public MongoSubscriptionStoreTests(MongoFixture fixture) - { - _ = fixture; - } + public MongoFixture _ { get; } = fixture; protected override void Configure(MessagingBuilder builder) { diff --git a/messaging/Squidex.Messaging.Tests/RedisMessagingTests.cs b/messaging/Squidex.Messaging.Tests/RedisMessagingTests.cs index 438d7bd..180b1c3 100644 --- a/messaging/Squidex.Messaging.Tests/RedisMessagingTests.cs +++ b/messaging/Squidex.Messaging.Tests/RedisMessagingTests.cs @@ -12,17 +12,12 @@ namespace Squidex.Messaging; -public class RedisMessagingTests : MessagingTestsBase, IClassFixture +public class RedisMessagingTests(RedisFixture fixture) : MessagingTestsBase, IClassFixture { - public RedisFixture _ { get; } + public RedisFixture _ { get; } = fixture; protected override bool CanHandleAndSimulateTimeout => false; - public RedisMessagingTests(RedisFixture fixture) - { - _ = fixture; - } - protected override void Configure(MessagingBuilder builder) { builder.AddRedisTransport(TestHelpers.Configuration, options => diff --git a/messaging/Squidex.Messaging.Tests/Squidex.Messaging.Tests.csproj b/messaging/Squidex.Messaging.Tests/Squidex.Messaging.Tests.csproj index babf113..b4a5a96 100644 --- a/messaging/Squidex.Messaging.Tests/Squidex.Messaging.Tests.csproj +++ b/messaging/Squidex.Messaging.Tests/Squidex.Messaging.Tests.csproj @@ -15,16 +15,16 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/messaging/Squidex.Messaging.Tests/SubscriptionServiceTests.cs b/messaging/Squidex.Messaging.Tests/SubscriptionServiceTests.cs index fbd0553..9a47890 100644 --- a/messaging/Squidex.Messaging.Tests/SubscriptionServiceTests.cs +++ b/messaging/Squidex.Messaging.Tests/SubscriptionServiceTests.cs @@ -17,17 +17,12 @@ namespace Squidex.Messaging; [Trait("Category", "Dependencies")] -public class SubscriptionServiceTests : IClassFixture +public class SubscriptionServiceTests(MongoFixture fixture) : IClassFixture { private readonly string groupName = $"group-{Guid.NewGuid()}"; private readonly string key = $"key-{Guid.NewGuid()}"; - public MongoFixture _ { get; } - - public SubscriptionServiceTests(MongoFixture fixture) - { - _ = fixture; - } + public MongoFixture _ { get; } = fixture; [Fact] public async Task Should_subscribe_hot() diff --git a/messaging/Squidex.Messaging/Implementation/CachingMessagingDataProvider.cs b/messaging/Squidex.Messaging/Implementation/CachingMessagingDataProvider.cs index eefb51c..1df5d47 100644 --- a/messaging/Squidex.Messaging/Implementation/CachingMessagingDataProvider.cs +++ b/messaging/Squidex.Messaging/Implementation/CachingMessagingDataProvider.cs @@ -10,18 +10,9 @@ namespace Squidex.Messaging.Implementation; -public sealed class CachingMessagingDataProvider : IMessagingDataProvider +public sealed class CachingMessagingDataProvider(IMemoryCache cache, IMessagingDataProvider inner, IOptions options) : IMessagingDataProvider { - private readonly IMessagingDataProvider inner; - private readonly IMemoryCache cache; - private readonly MessagingOptions options; - - public CachingMessagingDataProvider(IMemoryCache cache, IMessagingDataProvider inner, IOptions options) - { - this.options = options.Value; - this.cache = cache; - this.inner = inner; - } + private readonly MessagingOptions options = options.Value; public async Task> GetEntriesAsync(string group, CancellationToken ct = default) where T : notnull diff --git a/messaging/Squidex.Messaging/Implementation/DefaultMessageBus.cs b/messaging/Squidex.Messaging/Implementation/DefaultMessageBus.cs index dd9e1ff..c738bab 100644 --- a/messaging/Squidex.Messaging/Implementation/DefaultMessageBus.cs +++ b/messaging/Squidex.Messaging/Implementation/DefaultMessageBus.cs @@ -10,17 +10,9 @@ namespace Squidex.Messaging.Implementation; -internal sealed class DefaultMessageBus : IMessageBus +internal sealed class DefaultMessageBus(IInternalMessageProducer internalProducer, IOptions options) : IMessageBus { - private readonly IInternalMessageProducer internalProducer; - private readonly RoutingCollection routing; - - public DefaultMessageBus(IInternalMessageProducer internalProducer, IOptions options) - { - this.internalProducer = internalProducer; - - routing = new RoutingCollection(options.Value.Routing); - } + private readonly RoutingCollection routing = new RoutingCollection(options.Value.Routing); public async Task PublishAsync(object message, string? key = null, CancellationToken ct = default) diff --git a/messaging/Squidex.Messaging/Implementation/DelegateAsyncDisposable.cs b/messaging/Squidex.Messaging/Implementation/DelegateAsyncDisposable.cs index a1462bc..cf839f2 100644 --- a/messaging/Squidex.Messaging/Implementation/DelegateAsyncDisposable.cs +++ b/messaging/Squidex.Messaging/Implementation/DelegateAsyncDisposable.cs @@ -7,15 +7,8 @@ namespace Squidex.Messaging.Implementation; -public sealed class DelegateAsyncDisposable : IAsyncDisposable +public sealed class DelegateAsyncDisposable(Func action) : IAsyncDisposable { - private readonly Func action; - - public DelegateAsyncDisposable(Func action) - { - this.action = action; - } - public ValueTask DisposeAsync() { return action(); diff --git a/messaging/Squidex.Messaging/Implementation/DelegatingProducer.cs b/messaging/Squidex.Messaging/Implementation/DelegatingProducer.cs index 22ee0c9..b9f1408 100644 --- a/messaging/Squidex.Messaging/Implementation/DelegatingProducer.cs +++ b/messaging/Squidex.Messaging/Implementation/DelegatingProducer.cs @@ -11,29 +11,16 @@ namespace Squidex.Messaging.Implementation; -public sealed class DelegatingProducer : IInternalMessageProducer +public sealed class DelegatingProducer( + IInstanceNameProvider instanceName, + IMessagingTransports messagingTransports, + IMessagingSerializer messagingSerializer, + IOptionsMonitor channelOptions, + TimeProvider timeProvider) : IInternalMessageProducer { private readonly HashSet initializedChannels = []; private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1); - private readonly string instanceName; - private readonly IMessagingTransports messagingTransports; - private readonly IMessagingSerializer messagingSerializer; - private readonly IOptionsMonitor channelOptions; - private readonly TimeProvider timeProvider; - - public DelegatingProducer( - IInstanceNameProvider instanceName, - IMessagingTransports messagingTransports, - IMessagingSerializer messagingSerializer, - IOptionsMonitor channelOptions, - TimeProvider timeProvider) - { - this.channelOptions = channelOptions; - this.instanceName = instanceName.Name; - this.messagingTransports = messagingTransports; - this.messagingSerializer = messagingSerializer; - this.timeProvider = timeProvider; - } + private readonly string instanceName = instanceName.Name; public async Task ProduceAsync(ChannelName channel, object message, string? key = null, CancellationToken ct = default) diff --git a/messaging/Squidex.Messaging/Implementation/MessagingDataProvider.cs b/messaging/Squidex.Messaging/Implementation/MessagingDataProvider.cs index 8fb96f5..092a521 100644 --- a/messaging/Squidex.Messaging/Implementation/MessagingDataProvider.cs +++ b/messaging/Squidex.Messaging/Implementation/MessagingDataProvider.cs @@ -11,30 +11,17 @@ namespace Squidex.Messaging.Implementation; -public sealed class MessagingDataProvider : IMessagingDataProvider, IBackgroundProcess +public sealed class MessagingDataProvider( + IMessagingDataStore messagingDataStore, + IMessagingSerializer messagingSerializer, + IOptions options, + TimeProvider timeProvider, + ILogger log) : IMessagingDataProvider, IBackgroundProcess { private readonly Dictionary<(string Group, string Key), (SerializedObject Value, TimeSpan Expires)> localData = []; - private readonly MessagingOptions options; - private readonly IMessagingDataStore messagingDataStore; - private readonly IMessagingSerializer messagingSerializer; - private readonly ILogger log; - private readonly TimeProvider timeProvider; + private readonly MessagingOptions options = options.Value; private SimpleTimer? updateTimer; - public MessagingDataProvider( - IMessagingDataStore messagingDataStore, - IMessagingSerializer messagingSerializer, - IOptions options, - TimeProvider timeProvider, - ILogger log) - { - this.options = options.Value; - this.messagingDataStore = messagingDataStore; - this.messagingSerializer = messagingSerializer; - this.timeProvider = timeProvider; - this.log = log; - } - public Task StartAsync( CancellationToken ct) { diff --git a/messaging/Squidex.Messaging/Internal/AggregateAsyncDisposable.cs b/messaging/Squidex.Messaging/Internal/AggregateAsyncDisposable.cs index 3c3d347..404ab37 100644 --- a/messaging/Squidex.Messaging/Internal/AggregateAsyncDisposable.cs +++ b/messaging/Squidex.Messaging/Internal/AggregateAsyncDisposable.cs @@ -7,15 +7,8 @@ namespace Squidex.Messaging.Internal; -public sealed class AggregateAsyncDisposable : IAsyncDisposable +public sealed class AggregateAsyncDisposable(params IAsyncDisposable[] inners) : IAsyncDisposable { - private readonly IAsyncDisposable[] inners; - - public AggregateAsyncDisposable(params IAsyncDisposable[] inners) - { - this.inners = inners; - } - public async ValueTask DisposeAsync() { foreach (var inner in inners) diff --git a/messaging/Squidex.Messaging/Squidex.Messaging.csproj b/messaging/Squidex.Messaging/Squidex.Messaging.csproj index 1982d2c..f5b8027 100644 --- a/messaging/Squidex.Messaging/Squidex.Messaging.csproj +++ b/messaging/Squidex.Messaging/Squidex.Messaging.csproj @@ -12,14 +12,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/text/Squidex.Text.Tests/Squidex.Text.Tests.csproj b/text/Squidex.Text.Tests/Squidex.Text.Tests.csproj index 764a216..9d07ada 100644 --- a/text/Squidex.Text.Tests/Squidex.Text.Tests.csproj +++ b/text/Squidex.Text.Tests/Squidex.Text.Tests.csproj @@ -16,19 +16,19 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/text/Squidex.Text/ReadOnlyMemoryCharComparer.cs b/text/Squidex.Text/ReadOnlyMemoryCharComparer.cs index b5c41bb..eb8756e 100644 --- a/text/Squidex.Text/ReadOnlyMemoryCharComparer.cs +++ b/text/Squidex.Text/ReadOnlyMemoryCharComparer.cs @@ -9,7 +9,7 @@ namespace Squidex.Text; -internal sealed class ReadOnlyMemoryCharComparer : IEqualityComparer> +internal sealed class ReadOnlyMemoryCharComparer(StringComparison comparison) : IEqualityComparer> { public static readonly ReadOnlyMemoryCharComparer Ordinal = new ReadOnlyMemoryCharComparer(StringComparison.Ordinal); @@ -29,13 +29,6 @@ public static readonly ReadOnlyMemoryCharComparer CurrentCulture public static readonly ReadOnlyMemoryCharComparer CurrentCultureIgnoreCase = new ReadOnlyMemoryCharComparer(StringComparison.CurrentCultureIgnoreCase); - private readonly StringComparison comparison; - - public ReadOnlyMemoryCharComparer(StringComparison comparison) - { - this.comparison = comparison; - } - public bool Equals(ReadOnlyMemory x, ReadOnlyMemory y) { return x.Span.Equals(y.Span, comparison); diff --git a/text/Squidex.Text/RichText/TextVisitor.cs b/text/Squidex.Text/RichText/TextVisitor.cs index fb9184f..77cd235 100644 --- a/text/Squidex.Text/RichText/TextVisitor.cs +++ b/text/Squidex.Text/RichText/TextVisitor.cs @@ -10,18 +10,12 @@ namespace Squidex.Text.RichText; -public sealed class TextVisitor : Visitor +public sealed class TextVisitor(StringBuilder stringBuilder, int maxLength) : Visitor { - private readonly StringBuilder stringBuilder; - private readonly int maxLength; + private readonly StringBuilder stringBuilder = stringBuilder; + private readonly int maxLength = maxLength; private NodeType previousNodeType; - public TextVisitor(StringBuilder stringBuilder, int maxLength) - { - this.stringBuilder = stringBuilder; - this.maxLength = maxLength; - } - public static void Render(INode node, StringBuilder stringBuilder, int maxLength = int.MaxValue) { new TextVisitor(stringBuilder, maxLength).VisitRoot(node); diff --git a/text/Squidex.Text/RichText/Writer/IndentedWriter.cs b/text/Squidex.Text/RichText/Writer/IndentedWriter.cs index 2954b4d..5becef5 100644 --- a/text/Squidex.Text/RichText/Writer/IndentedWriter.cs +++ b/text/Squidex.Text/RichText/Writer/IndentedWriter.cs @@ -9,17 +9,11 @@ namespace Squidex.Text.RichText.Writer; -internal sealed class IndentedWriter : IWriter +internal sealed class IndentedWriter(StringBuilder stringBuilder) : IWriter { - private readonly StringBuilder stringBuilder = new StringBuilder(); private readonly Stack indents = new Stack(10); private bool previousWasLine = true; - public IndentedWriter(StringBuilder stringBuilder) - { - this.stringBuilder = stringBuilder; - } - public IWriter WriteLine(string text) { AppendIndentsCore(); diff --git a/text/Squidex.Text/RichText/Writer/PlainWriter.cs b/text/Squidex.Text/RichText/Writer/PlainWriter.cs index b1121cc..cfc6879 100644 --- a/text/Squidex.Text/RichText/Writer/PlainWriter.cs +++ b/text/Squidex.Text/RichText/Writer/PlainWriter.cs @@ -9,15 +9,8 @@ namespace Squidex.Text.RichText.Writer; -internal sealed class PlainWriter : IWriter +internal sealed class PlainWriter(StringBuilder stringBuilder) : IWriter { - private readonly StringBuilder stringBuilder; - - public PlainWriter(StringBuilder stringBuilder) - { - this.stringBuilder = stringBuilder; - } - public IWriter WriteLine(string text) { stringBuilder.Append(text); diff --git a/text/Squidex.Text/Squidex.Text.csproj b/text/Squidex.Text/Squidex.Text.csproj index 34f9e17..817c55d 100644 --- a/text/Squidex.Text/Squidex.Text.csproj +++ b/text/Squidex.Text/Squidex.Text.csproj @@ -14,21 +14,21 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + diff --git a/text/Squidex.Text/SvgError.cs b/text/Squidex.Text/SvgError.cs index fb9cdd9..47bf3b3 100644 --- a/text/Squidex.Text/SvgError.cs +++ b/text/Squidex.Text/SvgError.cs @@ -7,19 +7,11 @@ namespace Squidex.Text; -public sealed class SvgError +public sealed class SvgError(string error, int lineCount = -1, int linePosition = -1) { - public int LineCount { get; } + public int LineCount { get; } = lineCount; - public int LinePosition { get; } + public int LinePosition { get; } = linePosition; - public string Error { get; } - - public SvgError(string error, int lineCount = -1, int linePosition = -1) - { - Error = error; - - LineCount = lineCount; - LinePosition = linePosition; - } + public string Error { get; } = error; } diff --git a/text/Squidex.Text/Translations/DeepL/DeepLTranslationService.cs b/text/Squidex.Text/Translations/DeepL/DeepLTranslationService.cs index ecff053..0cdf091 100644 --- a/text/Squidex.Text/Translations/DeepL/DeepLTranslationService.cs +++ b/text/Squidex.Text/Translations/DeepL/DeepLTranslationService.cs @@ -14,12 +14,11 @@ namespace Squidex.Text.Translations.DeepL; [ExcludeFromCodeCoverage] -public sealed class DeepLTranslationService : ITranslationService +public sealed class DeepLTranslationService(IHttpClientFactory httpClientFactory, IOptions options) : ITranslationService { private const string UrlPaid = "https://api.deepl.com/v2/translate"; private const string UrlFree = "https://api-free.deepl.com/v2/translate"; - private readonly DeepLTranslationOptions options; - private readonly IHttpClientFactory httpClientFactory; + private readonly DeepLTranslationOptions options = options.Value; private sealed class TranslationsDto { @@ -36,15 +35,7 @@ private sealed class TranslationDto public string DetectedSourceLanguage { get; set; } } - public bool IsConfigured { get; } - - public DeepLTranslationService(IHttpClientFactory httpClientFactory, IOptions options) - { - this.options = options.Value; - this.httpClientFactory = httpClientFactory; - - IsConfigured = !string.IsNullOrWhiteSpace(options.Value.AuthKey); - } + public bool IsConfigured { get; } = !string.IsNullOrWhiteSpace(options.Value.AuthKey); public async Task> TranslateAsync(IEnumerable texts, string targetLanguage, string? sourceLanguage = null, CancellationToken ct = default) diff --git a/text/Squidex.Text/Translations/GoogleCloud/GoogleCloudTranslationService.cs b/text/Squidex.Text/Translations/GoogleCloud/GoogleCloudTranslationService.cs index dad7bb7..ce69781 100644 --- a/text/Squidex.Text/Translations/GoogleCloud/GoogleCloudTranslationService.cs +++ b/text/Squidex.Text/Translations/GoogleCloud/GoogleCloudTranslationService.cs @@ -11,19 +11,12 @@ namespace Squidex.Text.Translations.GoogleCloud; -public sealed class GoogleCloudTranslationService : ITranslationService +public sealed class GoogleCloudTranslationService(IOptions options) : ITranslationService { - private readonly GoogleCloudTranslationOptions options; + private readonly GoogleCloudTranslationOptions options = options.Value; private TranslationServiceClient service; - public bool IsConfigured { get; } - - public GoogleCloudTranslationService(IOptions options) - { - this.options = options.Value; - - IsConfigured = !string.IsNullOrWhiteSpace(options.Value.ProjectId); - } + public bool IsConfigured { get; } = !string.IsNullOrWhiteSpace(options.Value.ProjectId); public async Task> TranslateAsync(IEnumerable texts, string targetLanguage, string? sourceLanguage = null, CancellationToken ct = default)