From 21e3d2e51a47b77d472c9a667f5694c3484e4aa7 Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Thu, 3 Oct 2024 15:53:20 +0330 Subject: [PATCH 01/10] WIP: Add Marten Client --- Aspire.CommunityToolkit.sln | 35 ++-- Directory.Packages.props | 2 + .../Aspire.CommunityToolkit.Marten.csproj | 17 ++ .../MartenApplicationBuilderExtensions.cs | 181 ++++++++++++++++++ .../MartenSettings.cs | 41 ++++ src/Directory.Build.props | 4 +- src/HealthChecksExtensions.cs | 34 ++++ 7 files changed, 298 insertions(+), 16 deletions(-) create mode 100644 src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj create mode 100644 src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs create mode 100644 src/Aspire.CommunityToolkit.Marten/MartenSettings.cs create mode 100644 src/HealthChecksExtensions.cs diff --git a/Aspire.CommunityToolkit.sln b/Aspire.CommunityToolkit.sln index 9d381ee2..4c0a51ae 100644 --- a/Aspire.CommunityToolkit.sln +++ b/Aspire.CommunityToolkit.sln @@ -7,7 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{414151D4-700 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Java", "src\Aspire.CommunityToolkit.Hosting.Java\Aspire.CommunityToolkit.Hosting.Java.csproj", "{DAA67050-44B3-458F-9818-5877D606866A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps", "src\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj", "{125DFA83-328D-4F8B-91EC-3057FFF410BE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps", "src\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.csproj", "{125DFA83-328D-4F8B-91EC-3057FFF410BE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{8519CC01-1370-47C8-AD94-B0F326B1563F}" EndProject @@ -25,37 +25,39 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{899F0713 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Java.Tests", "tests\Aspire.CommunityToolkit.Hosting.Java.Tests\Aspire.CommunityToolkit.Hosting.Java.Tests.csproj", "{E2905A71-E25D-46FC-A128-D6A366D4D751}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests", "tests\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests.csproj", "{1B55E682-B518-4E59-8972-07C82ED5A677}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests", "tests\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests\Aspire.CommunityToolkit.Hosting.Azure.StaticWebApps.Tests.csproj", "{1B55E682-B518-4E59-8972-07C82ED5A677}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Testing", "tests\Aspire.CommunityToolkit.Testing\Aspire.CommunityToolkit.Testing.csproj", "{4C1D5422-4C52-4603-A01A-E1E6304633EC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Testing", "tests\Aspire.CommunityToolkit.Testing\Aspire.CommunityToolkit.Testing.csproj", "{4C1D5422-4C52-4603-A01A-E1E6304633EC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "swa", "swa", "{564FA6A0-EC54-41C6-A35F-89890E1D06E3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.StaticWebApps.AppHost", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.AppHost\Aspire.CommunityToolkit.StaticWebApps.AppHost.csproj", "{C083A377-13CA-47C1-8B17-1FE353EA76F0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.StaticWebApps.AppHost", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.AppHost\Aspire.CommunityToolkit.StaticWebApps.AppHost.csproj", "{C083A377-13CA-47C1-8B17-1FE353EA76F0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.StaticWebApps.ApiApp", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.ApiApp\Aspire.CommunityToolkit.StaticWebApps.ApiApp.csproj", "{BAEA0F6F-39E9-4893-8787-C4D292D3B169}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.StaticWebApps.ApiApp", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.ApiApp\Aspire.CommunityToolkit.StaticWebApps.ApiApp.csproj", "{BAEA0F6F-39E9-4893-8787-C4D292D3B169}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults\Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults.csproj", "{83FF8083-7EE2-4196-86A8-239F921B443C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults", "examples\swa\Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults\Aspire.CommunityToolkit.StaticWebApps.ServiceDefaults.csproj", "{83FF8083-7EE2-4196-86A8-239F921B443C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions", "src\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.csproj", "{1F299343-30DF-4599-A95D-BCFB1754DA48}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions", "src\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.csproj", "{1F299343-30DF-4599-A95D-BCFB1754DA48}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nodejs-ext", "nodejs-ext", "{261AC321-8982-4C3A-8DBF-DAFC95F97697}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost", "examples\nodejs-ext\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost.csproj", "{D3F5EF2B-CE37-4339-A8BD-50E6C5B2AFA1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost", "examples\nodejs-ext\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.AppHost.csproj", "{D3F5EF2B-CE37-4339-A8BD-50E6C5B2AFA1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests", "tests\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests.csproj", "{E8F93376-1367-4A7B-A729-116199804356}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests", "tests\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests\Aspire.CommunityToolkit.Hosting.NodeJS.Extensions.Tests.csproj", "{E8F93376-1367-4A7B-A729-116199804356}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Ollama", "src\Aspire.CommunityToolkit.Hosting.Ollama\Aspire.CommunityToolkit.Hosting.Ollama.csproj", "{6C6696CB-8DCC-4E93-A667-A313D70E0220}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Ollama", "src\Aspire.CommunityToolkit.Hosting.Ollama\Aspire.CommunityToolkit.Hosting.Ollama.csproj", "{6C6696CB-8DCC-4E93-A667-A313D70E0220}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Ollama.Tests", "tests\Aspire.CommunityToolkit.Hosting.Ollama.Tests\Aspire.CommunityToolkit.Hosting.Ollama.Tests.csproj", "{1DB27FA0-E7E4-42C1-B062-4DE0128D4FA1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Ollama.Tests", "tests\Aspire.CommunityToolkit.Hosting.Ollama.Tests\Aspire.CommunityToolkit.Hosting.Ollama.Tests.csproj", "{1DB27FA0-E7E4-42C1-B062-4DE0128D4FA1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ollama", "ollama", "{14BD8AE7-C8DF-4C7C-8244-7F74C101569D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Ollama.AppHost", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.AppHost\Aspire.CommunityToolkit.Hosting.Ollama.AppHost.csproj", "{F4602DC8-3C17-4834-B640-9A3B27FE278A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Ollama.AppHost", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.AppHost\Aspire.CommunityToolkit.Hosting.Ollama.AppHost.csproj", "{F4602DC8-3C17-4834-B640-9A3B27FE278A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults\Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults.csproj", "{2F037600-2002-4A13-9359-98FB0D2416BE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults\Aspire.CommunityToolkit.Hosting.Ollama.ServiceDefaults.csproj", "{2F037600-2002-4A13-9359-98FB0D2416BE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.CommunityToolkit.Hosting.Ollama.Web", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.Web\Aspire.CommunityToolkit.Hosting.Ollama.Web.csproj", "{0A17021E-5F10-429B-88C8-E4073EADACB6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Hosting.Ollama.Web", "examples\ollama\Aspire.CommunityToolkit.Hosting.Ollama.Web\Aspire.CommunityToolkit.Hosting.Ollama.Web.csproj", "{0A17021E-5F10-429B-88C8-E4073EADACB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.CommunityToolkit.Marten", "src\Aspire.CommunityToolkit.Marten\Aspire.CommunityToolkit.Marten.csproj", "{BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -143,6 +145,10 @@ Global {0A17021E-5F10-429B-88C8-E4073EADACB6}.Debug|Any CPU.Build.0 = Debug|Any CPU {0A17021E-5F10-429B-88C8-E4073EADACB6}.Release|Any CPU.ActiveCfg = Release|Any CPU {0A17021E-5F10-429B-88C8-E4073EADACB6}.Release|Any CPU.Build.0 = Release|Any CPU + {BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -172,6 +178,7 @@ Global {F4602DC8-3C17-4834-B640-9A3B27FE278A} = {14BD8AE7-C8DF-4C7C-8244-7F74C101569D} {2F037600-2002-4A13-9359-98FB0D2416BE} = {14BD8AE7-C8DF-4C7C-8244-7F74C101569D} {0A17021E-5F10-429B-88C8-E4073EADACB6} = {14BD8AE7-C8DF-4C7C-8244-7F74C101569D} + {BE9A90D9-1DBD-4BE7-9D2D-981BC2B3B954} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0} diff --git a/Directory.Packages.props b/Directory.Packages.props index 2ec36416..73c7caee 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,6 +10,7 @@ + @@ -31,5 +32,6 @@ + \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj b/src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj new file mode 100644 index 00000000..d7d8e611 --- /dev/null +++ b/src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj @@ -0,0 +1,17 @@ + + + + postgres marten + + + + + + + + + + + + + diff --git a/src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs b/src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs new file mode 100644 index 00000000..a64d278a --- /dev/null +++ b/src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs @@ -0,0 +1,181 @@ +using Aspire; +using Aspire.CommunityToolkit.Marten; +using HealthChecks.NpgSql; +using Marten; +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using Npgsql; +using Weasel.Core; + +namespace Microsoft.Extensions.Hosting; + +/// +/// TODO +/// +public static class MartenApplicationBuilderExtensions +{ + private const string DefaultConfigSectionName = "Aspire:Marten"; + + /// + /// TODO + /// + /// + /// + /// + /// + public static void AddMartenClient( + this IHostApplicationBuilder builder, + string connectionName, + Action? configureSettings = null, + Action? configureStoreOptions = null + ) + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentException.ThrowIfNullOrEmpty(connectionName); + + builder.AddMartenClient(DefaultConfigSectionName, configureSettings, configureStoreOptions, connectionName, serviceKey: null); + } + + /// + /// TOOD + /// + /// + /// + /// + /// + public static void AddKeyedMartenClient( + this IHostApplicationBuilder builder, + string name, + Action? configureSettings = null, + Action? configureStoreOptions = null) + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentException.ThrowIfNullOrEmpty(name); + + builder.AddMartenClient( + $"{DefaultConfigSectionName}:{name}", + configureSettings, + configureStoreOptions, + connectionName: name, + serviceKey: name); + } + + private static void AddMartenClient( + this IHostApplicationBuilder builder, + string configurationSectionName, + Action? configureSettings, + Action? configureStoreOptions, + string connectionName, + object? serviceKey) + { + ArgumentNullException.ThrowIfNull(builder); + + var configSection = builder.Configuration.GetSection(configurationSectionName); + + MartenSettings settings = new(); + configSection.Bind(settings); + + if (builder.Configuration.GetConnectionString(connectionName) is string connectionString) + { + settings.ConnectionString = connectionString; + } + + configureSettings?.Invoke(settings); + + builder.RegisterMartenServices(settings, configurationSectionName, connectionName, serviceKey, configureStoreOptions); + + + if (!settings.DisableTracing) + { + builder.Services.AddOpenTelemetry() + .WithTracing(tracing => + { + tracing.AddSource("Marten"); + }) + .WithMetrics(metrics => + { + metrics.AddMeter("Marten"); + }); + } + + if (!settings.DisableMetrics) + { + builder.Services.AddOpenTelemetry() + .WithTracing(tracing => + { + tracing.AddSource("Marten"); + }); + } + + if (!settings.DisableHealthChecks) + { + builder.TryAddHealthCheck(new HealthCheckRegistration( + serviceKey is null ? "Aspire.Marten" : $"Aspire.Marten_{connectionName}", + sp => new NpgSqlHealthCheck( + new NpgSqlHealthCheckOptions(serviceKey is null + ? sp.GetRequiredService() + : sp.GetRequiredKeyedService(serviceKey))), + failureStatus: default, + tags: default, + timeout: default)); + } + } + + private static void RegisterMartenServices(this IHostApplicationBuilder builder, MartenSettings settings, string configurationSectionName, string connectionName, object? serviceKey, Action? configureStoreOptions) + { + + builder.Services.AddKeyedSingleton(serviceKey is null ? "Aspire.Marten" : $"Aspire.Marten_{connectionName}", (serviceProvider, _) => + { + ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); + + var dataSourceBuilder = new NpgsqlDataSourceBuilder(settings.ConnectionString); + dataSourceBuilder.UseLoggerFactory(serviceProvider.GetService()); + + return dataSourceBuilder.Build(); + }); + + if (serviceKey is null) + { + builder.Services.AddMarten(storeOption => + { + ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); + + configureStoreOptions?.Invoke(storeOption); + storeOption.Connection(settings.ConnectionString!); + }); + } + else + { + builder.Services.AddKeyedSingleton(serviceKey, (sp, _) => + { + var store = DocumentStore.For((storeOption) => + { + ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); + + configureStoreOptions?.Invoke(storeOption); + storeOption.Connection(settings.ConnectionString!); + }); + return store; + }); + builder.Services.AddKeyedSingleton(serviceKey, (sp, _) => + { + return sp.GetRequiredService().LightweightSession(); + }); + builder.Services.AddScoped((sp) => + { + return sp.GetRequiredService().QuerySession(); + }); + } + } + + private static void ValidateConnectionString(string? connectionString, string connectionName, string defaultConfigSectionName) + { + if (string.IsNullOrWhiteSpace(connectionString)) + { + throw new InvalidOperationException($"ConnectionString is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'ConnectionString' key in '{defaultConfigSectionName}' configuration section."); + } + } +} \ No newline at end of file diff --git a/src/Aspire.CommunityToolkit.Marten/MartenSettings.cs b/src/Aspire.CommunityToolkit.Marten/MartenSettings.cs new file mode 100644 index 00000000..1186ca6e --- /dev/null +++ b/src/Aspire.CommunityToolkit.Marten/MartenSettings.cs @@ -0,0 +1,41 @@ +namespace Aspire.CommunityToolkit.Marten; + +/// +/// Provides the client configuration settings for connecting to a PostgreSQL database using Marten. +/// +public sealed class MartenSettings +{ + /// + /// The connection string of the PostgreSQL database to connect to. + /// + public string? ConnectionString { get; set; } + + /// + /// Gets or sets a boolean value that indicates whether the database health check is disabled or not. + /// + /// + /// The default value is . + /// + public bool DisableHealthChecks { get; set; } + + /// + /// Gets or sets a integer value that indicates the database health check timeout in milliseconds. + /// + public int? HealthCheckTimeout { get; set; } + + /// + /// Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is disabled or not. + /// + /// + /// The default value is . + /// + public bool DisableTracing { get; set; } + + /// + /// Gets or sets a boolean value that indicates whether the OpenTelemetry metrics are disabled or not. + /// + /// + /// The default value is . + /// + public bool DisableMetrics { get; set; } +} \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 572ab675..2ff1ed2b 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -21,7 +21,7 @@ embedded true - ../../docs/integrations + README.md ../../nuget aspire integration communitytoolkit dotnetcommunitytoolkit $(AdditionalPackageTags) @@ -38,7 +38,7 @@ - + true / diff --git a/src/HealthChecksExtensions.cs b/src/HealthChecksExtensions.cs new file mode 100644 index 00000000..c4ba8860 --- /dev/null +++ b/src/HealthChecksExtensions.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Hosting; +using System.Diagnostics.CodeAnalysis; + +namespace Aspire; + +[Experimental("CTASPIRE001", UrlFormat = "https://aka.ms/communitytoolkit/aspire/diagnostics#{0}")] +internal static class HealthChecksExtensions +{ + /// + /// Adds a HealthCheckRegistration if one hasn't already been added to the builder. + /// + public static void TryAddHealthCheck(this IHostApplicationBuilder builder, HealthCheckRegistration healthCheckRegistration) + { + builder.TryAddHealthCheck(healthCheckRegistration.Name, hcBuilder => hcBuilder.Add(healthCheckRegistration)); + } + + /// + /// Invokes the action if the given hasn't already been added to the builder. + /// + public static void TryAddHealthCheck(this IHostApplicationBuilder builder, string name, Action addHealthCheck) + { + var healthCheckKey = $"Aspire.HealthChecks.{name}"; + if (!builder.Properties.ContainsKey(healthCheckKey)) + { + builder.Properties[healthCheckKey] = true; + addHealthCheck(builder.Services.AddHealthChecks()); + } + } +} From 8ee8f572c80fcb322cbfcb00cd4c9334b7869a3c Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Tue, 22 Oct 2024 21:11:37 +0330 Subject: [PATCH 02/10] revert removed package refrence --- Directory.Packages.props | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Directory.Packages.props b/Directory.Packages.props index f5906031..a5197be4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -39,5 +39,10 @@ + + + + + \ No newline at end of file From 717374d8f56b45fa43dc866873a389f08d58bc0e Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Tue, 22 Oct 2024 21:24:47 +0330 Subject: [PATCH 03/10] Update namespaces and fix client registration --- CommunityToolkit.Aspire.sln | 15 ++++++++--- Directory.Packages.props | 1 + .../CommunityToolkit.Aspire.Marten.csproj} | 0 .../MartenApplicationBuilderExtensions.cs | 26 +++++++++++++------ .../MartenSettings.cs | 2 +- .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 15 +++++++++++ src/CommunityToolkit.Aspire.Marten/README.md | 1 + 8 files changed, 48 insertions(+), 13 deletions(-) rename src/{Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj => CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj} (100%) rename src/{Aspire.CommunityToolkit.Marten => CommunityToolkit.Aspire.Marten}/MartenApplicationBuilderExtensions.cs (87%) rename src/{Aspire.CommunityToolkit.Marten => CommunityToolkit.Aspire.Marten}/MartenSettings.cs (96%) create mode 100644 src/CommunityToolkit.Aspire.Marten/PublicAPI.Shipped.txt create mode 100644 src/CommunityToolkit.Aspire.Marten/PublicAPI.Unshipped.txt create mode 100644 src/CommunityToolkit.Aspire.Marten/README.md diff --git a/CommunityToolkit.Aspire.sln b/CommunityToolkit.Aspire.sln index e06dc52e..938fe4b2 100644 --- a/CommunityToolkit.Aspire.sln +++ b/CommunityToolkit.Aspire.sln @@ -7,7 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{414151D4-700 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Java", "src\CommunityToolkit.Aspire.Hosting.Java\CommunityToolkit.Aspire.Hosting.Java.csproj", "{DAA67050-44B3-458F-9818-5877D606866A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps", "src\CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps\CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps.csproj", "{125DFA83-328D-4F8B-91EC-3057FFF410BE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps", "src\CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps\CommunityToolkit.Aspire.Hosting.Azure.StaticWebApps.csproj", "{125DFA83-328D-4F8B-91EC-3057FFF410BE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{8519CC01-1370-47C8-AD94-B0F326B1563F}" EndProject @@ -77,16 +77,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Oll EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.Tests", "tests\CommunityToolkit.Aspire.Hosting.Meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.Tests.csproj", "{C715669D-FBDE-4BFF-B9A3-75615D3C179A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Meilisearch.Tests", "tests\CommunityToolkit.Aspire.Meilisearch.Tests\CommunityToolkit.Aspire.Meilisearch.Tests.csproj", "{0AACC135-9624-423D-8988-69701C0FE428}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Meilisearch.Tests", "tests\CommunityToolkit.Aspire.Meilisearch.Tests\CommunityToolkit.Aspire.Meilisearch.Tests.csproj", "{0AACC135-9624-423D-8988-69701C0FE428}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meilisearch", "meilisearch", "{561CEB82-3D97-49D0-932E-664E6779FC61}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost", "examples\meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost\CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost.csproj", "{6B9357F7-014F-4725-AF3E-0B8EA17B62C5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost", "examples\meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost\CommunityToolkit.Aspire.Hosting.Meilisearch.AppHost.csproj", "{6B9357F7-014F-4725-AF3E-0B8EA17B62C5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults", "examples\meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults\CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults.csproj", "{E4E93A24-0A97-419F-836C-EAA23D0FFF81}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults", "examples\meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults\CommunityToolkit.Aspire.Hosting.Meilisearch.ServiceDefaults.csproj", "{E4E93A24-0A97-419F-836C-EAA23D0FFF81}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hosting.Meilisearch.ApiService", "examples\meilisearch\CommunityToolkit.Aspire.Hosting.Meilisearch.ApiService\CommunityToolkit.Aspire.Hosting.Meilisearch.ApiService.csproj", "{F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten", "src\CommunityToolkit.Aspire.Marten\CommunityToolkit.Aspire.Marten.csproj", "{DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -225,6 +227,10 @@ Global {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E}.Release|Any CPU.Build.0 = Release|Any CPU + {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -269,6 +275,7 @@ Global {6B9357F7-014F-4725-AF3E-0B8EA17B62C5} = {561CEB82-3D97-49D0-932E-664E6779FC61} {E4E93A24-0A97-419F-836C-EAA23D0FFF81} = {561CEB82-3D97-49D0-932E-664E6779FC61} {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E} = {561CEB82-3D97-49D0-932E-664E6779FC61} + {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0} diff --git a/Directory.Packages.props b/Directory.Packages.props index a5197be4..16c813cf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -40,6 +40,7 @@ + diff --git a/src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj b/src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj similarity index 100% rename from src/Aspire.CommunityToolkit.Marten/Aspire.CommunityToolkit.Marten.csproj rename to src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj diff --git a/src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs similarity index 87% rename from src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs rename to src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs index a64d278a..ee445c09 100644 --- a/src/Aspire.CommunityToolkit.Marten/MartenApplicationBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs @@ -1,14 +1,12 @@ using Aspire; -using Aspire.CommunityToolkit.Marten; +using CommunityToolkit.Aspire.Marten; using HealthChecks.NpgSql; using Marten; -using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Logging; using Npgsql; -using Weasel.Core; namespace Microsoft.Extensions.Hosting; @@ -139,12 +137,24 @@ private static void RegisterMartenServices(this IHostApplicationBuilder builder, if (serviceKey is null) { - builder.Services.AddMarten(storeOption => + builder.Services.AddSingleton(sp => { - ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); + var store = DocumentStore.For((storeOption) => + { + ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); - configureStoreOptions?.Invoke(storeOption); - storeOption.Connection(settings.ConnectionString!); + configureStoreOptions?.Invoke(storeOption); + storeOption.Connection(settings.ConnectionString!); + }); + return store; + }); + builder.Services.AddSingleton(sp => + { + return sp.GetRequiredService().LightweightSession(); + }); + builder.Services.AddScoped(sp => + { + return sp.GetRequiredService().QuerySession(); }); } else @@ -164,7 +174,7 @@ private static void RegisterMartenServices(this IHostApplicationBuilder builder, { return sp.GetRequiredService().LightweightSession(); }); - builder.Services.AddScoped((sp) => + builder.Services.AddKeyedScoped(serviceKey,(sp,_) => { return sp.GetRequiredService().QuerySession(); }); diff --git a/src/Aspire.CommunityToolkit.Marten/MartenSettings.cs b/src/CommunityToolkit.Aspire.Marten/MartenSettings.cs similarity index 96% rename from src/Aspire.CommunityToolkit.Marten/MartenSettings.cs rename to src/CommunityToolkit.Aspire.Marten/MartenSettings.cs index 1186ca6e..74ea18fd 100644 --- a/src/Aspire.CommunityToolkit.Marten/MartenSettings.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenSettings.cs @@ -1,4 +1,4 @@ -namespace Aspire.CommunityToolkit.Marten; +namespace CommunityToolkit.Aspire.Marten; /// /// Provides the client configuration settings for connecting to a PostgreSQL database using Marten. diff --git a/src/CommunityToolkit.Aspire.Marten/PublicAPI.Shipped.txt b/src/CommunityToolkit.Aspire.Marten/PublicAPI.Shipped.txt new file mode 100644 index 00000000..7dc5c581 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Marten/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/CommunityToolkit.Aspire.Marten/PublicAPI.Unshipped.txt b/src/CommunityToolkit.Aspire.Marten/PublicAPI.Unshipped.txt new file mode 100644 index 00000000..eed81e91 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Marten/PublicAPI.Unshipped.txt @@ -0,0 +1,15 @@ +CommunityToolkit.Aspire.Marten.MartenSettings +CommunityToolkit.Aspire.Marten.MartenSettings.ConnectionString.get -> string? +CommunityToolkit.Aspire.Marten.MartenSettings.ConnectionString.set -> void +CommunityToolkit.Aspire.Marten.MartenSettings.DisableHealthChecks.get -> bool +CommunityToolkit.Aspire.Marten.MartenSettings.DisableHealthChecks.set -> void +CommunityToolkit.Aspire.Marten.MartenSettings.DisableMetrics.get -> bool +CommunityToolkit.Aspire.Marten.MartenSettings.DisableMetrics.set -> void +CommunityToolkit.Aspire.Marten.MartenSettings.DisableTracing.get -> bool +CommunityToolkit.Aspire.Marten.MartenSettings.DisableTracing.set -> void +CommunityToolkit.Aspire.Marten.MartenSettings.HealthCheckTimeout.get -> int? +CommunityToolkit.Aspire.Marten.MartenSettings.HealthCheckTimeout.set -> void +CommunityToolkit.Aspire.Marten.MartenSettings.MartenSettings() -> void +Microsoft.Extensions.Hosting.MartenApplicationBuilderExtensions +static Microsoft.Extensions.Hosting.MartenApplicationBuilderExtensions.AddKeyedMartenClient(this Microsoft.Extensions.Hosting.IHostApplicationBuilder! builder, string! name, System.Action? configureSettings = null, System.Action? configureStoreOptions = null) -> void +static Microsoft.Extensions.Hosting.MartenApplicationBuilderExtensions.AddMartenClient(this Microsoft.Extensions.Hosting.IHostApplicationBuilder! builder, string! connectionName, System.Action? configureSettings = null, System.Action? configureStoreOptions = null) -> void \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Marten/README.md b/src/CommunityToolkit.Aspire.Marten/README.md new file mode 100644 index 00000000..f87f5c14 --- /dev/null +++ b/src/CommunityToolkit.Aspire.Marten/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file From 8f5b6f1a5e6cdf9e6ad7f30e0b9d79e01da27883 Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Tue, 22 Oct 2024 21:28:21 +0330 Subject: [PATCH 04/10] add packge descripion --- .../CommunityToolkit.Aspire.Marten.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj b/src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj index d7d8e611..8f4d9f6e 100644 --- a/src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj +++ b/src/CommunityToolkit.Aspire.Marten/CommunityToolkit.Aspire.Marten.csproj @@ -2,6 +2,7 @@ postgres marten + A .NET Aspire client integration for the Marten library. From 7c4d72288db33b2dbeecc5967804d7ec0ece4edb Mon Sep 17 00:00:00 2001 From: "alireza.baloochi1380@gmail.com" Date: Tue, 22 Oct 2024 22:41:20 +0330 Subject: [PATCH 05/10] Add some tests --- CommunityToolkit.Aspire.sln | 7 + Directory.Packages.props | 1 + .../MartenApplicationBuilderExtensions.cs | 10 +- .../AspireMartenExtensionsTest.cs | 150 ++++++++++++++++++ ...ommunityToolkit.Aspire.Marten.Tests.csproj | 18 +++ .../ConfigurationTests.cs | 29 ++++ .../MartenClientPublicApiTests.cs | 88 ++++++++++ .../PostgreSQLContainerFixture.cs | 32 ++++ .../PostgresContainerImageTags.cs | 13 ++ 9 files changed, 343 insertions(+), 5 deletions(-) create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/AspireMartenExtensionsTest.cs create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/ConfigurationTests.cs create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/MartenClientPublicApiTests.cs create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/PostgreSQLContainerFixture.cs create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/PostgresContainerImageTags.cs diff --git a/CommunityToolkit.Aspire.sln b/CommunityToolkit.Aspire.sln index 938fe4b2..082b1fcc 100644 --- a/CommunityToolkit.Aspire.sln +++ b/CommunityToolkit.Aspire.sln @@ -89,6 +89,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hos EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten", "src\CommunityToolkit.Aspire.Marten\CommunityToolkit.Aspire.Marten.csproj", "{DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Marten.Tests", "tests\CommunityToolkit.Aspire.Marten.Tests\CommunityToolkit.Aspire.Marten.Tests.csproj", "{8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -231,6 +233,10 @@ Global {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Debug|Any CPU.Build.0 = Debug|Any CPU {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Release|Any CPU.ActiveCfg = Release|Any CPU {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}.Release|Any CPU.Build.0 = Release|Any CPU + {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -276,6 +282,7 @@ Global {E4E93A24-0A97-419F-836C-EAA23D0FFF81} = {561CEB82-3D97-49D0-932E-664E6779FC61} {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E} = {561CEB82-3D97-49D0-932E-664E6779FC61} {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} + {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B} = {899F0713-7FC6-4750-BAFC-AC650B35B453} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0} diff --git a/Directory.Packages.props b/Directory.Packages.props index 16c813cf..ba8e50da 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -45,5 +45,6 @@ + \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs index ee445c09..030a2018 100644 --- a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs @@ -114,17 +114,17 @@ private static void AddMartenClient( serviceKey is null ? "Aspire.Marten" : $"Aspire.Marten_{connectionName}", sp => new NpgSqlHealthCheck( new NpgSqlHealthCheckOptions(serviceKey is null - ? sp.GetRequiredService() - : sp.GetRequiredKeyedService(serviceKey))), + ? sp.GetRequiredKeyedService("Aspire.Marten") + : sp.GetRequiredKeyedService($"Aspire.Marten_{connectionName}"))), failureStatus: default, tags: default, - timeout: default)); + timeout: settings.HealthCheckTimeout > 0 ? TimeSpan.FromMilliseconds(settings.HealthCheckTimeout.Value) : null)); } } private static void RegisterMartenServices(this IHostApplicationBuilder builder, MartenSettings settings, string configurationSectionName, string connectionName, object? serviceKey, Action? configureStoreOptions) { - + builder.Services.AddKeyedSingleton(serviceKey is null ? "Aspire.Marten" : $"Aspire.Marten_{connectionName}", (serviceProvider, _) => { ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); @@ -174,7 +174,7 @@ private static void RegisterMartenServices(this IHostApplicationBuilder builder, { return sp.GetRequiredService().LightweightSession(); }); - builder.Services.AddKeyedScoped(serviceKey,(sp,_) => + builder.Services.AddKeyedScoped(serviceKey, (sp, _) => { return sp.GetRequiredService().QuerySession(); }); diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/AspireMartenExtensionsTest.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/AspireMartenExtensionsTest.cs new file mode 100644 index 00000000..98604cb3 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/AspireMartenExtensionsTest.cs @@ -0,0 +1,150 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Components.Common.Tests; +using Marten; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Hosting; +using Npgsql; +using Xunit; + +namespace CommunityToolkit.Aspire.Marten.Tests; + +public class AspireMartenClientExtensionsTest(PostgreSQLContainerFixture containerFixture) : IClassFixture +{ + private const string DefaultConnectionName = "postgres"; + + private string DefaultConnectionString => + RequiresDockerAttribute.IsSupported ? containerFixture.GetConnectionString() : "Host=localhost;Database=test_aspire_marten"; + + [Theory] + [InlineData(true)] + [InlineData(false)] + [RequiresDocker] + public async Task AddMartenClient_HealthCheckShouldBeRegisteredWhenEnabled(bool useKeyed) + { + var key = DefaultConnectionName; + + var builder = CreateBuilder(DefaultConnectionString); + + if (useKeyed) + { + builder.AddKeyedMartenClient(key, settings => + { + settings.DisableHealthChecks = false; + }); + } + else + { + builder.AddMartenClient(DefaultConnectionName, settings => + { + settings.DisableHealthChecks = false; + }); + } + + using var host = builder.Build(); + + var healthCheckService = host.Services.GetRequiredService(); + + var healthCheckReport = await healthCheckService.CheckHealthAsync(); + + var healthCheckName = useKeyed ? $"Aspire.Marten_{key}" : "Aspire.Marten"; + + Assert.Contains(healthCheckReport.Entries, x => x.Key == healthCheckName); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void AddMartenClient_HealthCheckShouldNotBeRegisteredWhenDisabled(bool useKeyed) + { + var builder = CreateBuilder(DefaultConnectionString); + + if (useKeyed) + { + builder.AddKeyedMartenClient(DefaultConnectionName, settings => + { + settings.DisableHealthChecks = true; + }); + } + else + { + builder.AddMartenClient(DefaultConnectionName, settings => + { + settings.DisableHealthChecks = true; + }); + } + + using var host = builder.Build(); + + var healthCheckService = host.Services.GetService(); + + Assert.Null(healthCheckService); + } + + [Fact] + public void CanAddMultipleKeyedServices() + { + var builder = Host.CreateEmptyApplicationBuilder(null); + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair("ConnectionStrings:postgres1", "Host=localhost1;Database=test_aspire_marten"), + new KeyValuePair("ConnectionStrings:postgres2", "Host=localhost2;Database=test_aspire_marten"), + new KeyValuePair("ConnectionStrings:postgres3", "Host=localhost3;Database=test_aspire_marten"), + ]); + + builder.AddMartenClient("postgres1"); + builder.AddKeyedMartenClient("postgres2"); + builder.AddKeyedMartenClient("postgres3"); + + using var host = builder.Build(); + + var documentStore1 = host.Services.GetRequiredService(); + var documentStore2 = host.Services.GetRequiredKeyedService("postgres2"); + var documentStore3 = host.Services.GetRequiredKeyedService("postgres3"); + + Assert.NotSame(documentStore1, documentStore2); + Assert.NotSame(documentStore1, documentStore3); + Assert.NotSame(documentStore2, documentStore3); + + var documentSession1 = host.Services.GetRequiredService(); + var documentSession2 = host.Services.GetRequiredKeyedService("postgres2"); + var documentSession3 = host.Services.GetRequiredKeyedService("postgres3"); + + Assert.NotSame(documentSession1, documentSession2); + Assert.NotSame(documentSession1, documentSession3); + Assert.NotSame(documentSession2, documentSession3); + + var querySession1 = host.Services.GetRequiredService(); + var querySession2 = host.Services.GetRequiredKeyedService("postgres2"); + var querySession3 = host.Services.GetRequiredKeyedService("postgres3"); + + Assert.NotSame(querySession1, querySession2); + Assert.NotSame(querySession1, querySession3); + Assert.NotSame(querySession2, querySession3); + + var npgsql1 = host.Services.GetRequiredKeyedService("Aspire.Marten"); + var npgsql2 = host.Services.GetRequiredKeyedService("Aspire.Marten_postgres2"); + var npgsql3 = host.Services.GetRequiredKeyedService("Aspire.Marten_postgres3"); + + Assert.NotSame(npgsql1, npgsql2); + Assert.NotSame(npgsql1, npgsql3); + Assert.NotSame(npgsql2, npgsql3); + + Assert.Equal(builder.Configuration["ConnectionStrings:postgres1"], npgsql1.ConnectionString); + Assert.Equal(builder.Configuration["ConnectionStrings:postgres2"], npgsql2.ConnectionString); + Assert.Equal(builder.Configuration["ConnectionStrings:postgres3"], npgsql3.ConnectionString); + + } + + private static HostApplicationBuilder CreateBuilder(string connectionString) + { + var builder = Host.CreateEmptyApplicationBuilder(null); + + builder.Configuration.AddInMemoryCollection([ + new KeyValuePair($"ConnectionStrings:{DefaultConnectionName}", connectionString) + ]); + return builder; + } +} diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj new file mode 100644 index 00000000..9b17cca5 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/ConfigurationTests.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/ConfigurationTests.cs new file mode 100644 index 00000000..320f9792 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/ConfigurationTests.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace CommunityToolkit.Aspire.Marten.Tests; + +public class ConfigurationTests +{ + [Fact] + public void ConnectionStringIsNullByDefault() => + Assert.Null(new MartenSettings().ConnectionString); + + [Fact] + public void HealthChecksEnabledByDefault() => + Assert.False(new MartenSettings().DisableHealthChecks); + + [Fact] + public void HealthCheckTimeoutIsNullByDefault() => + Assert.Null(new MartenSettings().HealthCheckTimeout); + + [Fact] + public void TracingEnabledByDefault() => + Assert.False(new MartenSettings().DisableTracing); + + [Fact] + public void MetricsEnabledByDefault() => + Assert.False(new MartenSettings().DisableMetrics); +} diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/MartenClientPublicApiTests.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/MartenClientPublicApiTests.cs new file mode 100644 index 00000000..922cc695 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/MartenClientPublicApiTests.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Hosting; +using Xunit; + +namespace CommunityToolkit.Aspire.Marten.Tests; + +public class MartenClientPublicApiTests +{ + [Fact] + public void AddMartenClientShouldThrowWhenBuilderIsNull() + { + IHostApplicationBuilder builder = null!; + + var connectionName = "postgres"; + + var action = () => builder.AddMartenClient(connectionName); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void AddMartenClientShouldThrowWhenNameIsNull() + { + var builder = Host.CreateEmptyApplicationBuilder(null); + + string connectionName = null!; + + var action = () => builder.AddMartenClient(connectionName); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(connectionName), exception.ParamName); + } + + [Fact] + public void AddMartenClientShouldThrowWhenNameIsEmpty() + { + var builder = Host.CreateEmptyApplicationBuilder(null); + + string connectionName = ""; + + var action = () => builder.AddMartenClient(connectionName); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(connectionName), exception.ParamName); + } + + [Fact] + public void AddKeyedMartenClientShouldThrowWhenBuilderIsNull() + { + IHostApplicationBuilder builder = null!; + + var connectionName = "postgres"; + + var action = () => builder.AddKeyedMartenClient(connectionName); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void AddKeyedMartenClientShouldThrowWhenNameIsNull() + { + var builder = Host.CreateEmptyApplicationBuilder(null); + + string name = null!; + + var action = () => builder.AddKeyedMartenClient(name); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + [Fact] + public void AddKeyedMartenClientShouldThrowWhenNameIsEmpty() + { + var builder = Host.CreateEmptyApplicationBuilder(null); + + string name = ""; + + var action = () => builder.AddKeyedMartenClient(name); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } +} diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/PostgreSQLContainerFixture.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/PostgreSQLContainerFixture.cs new file mode 100644 index 00000000..493fbc3f --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/PostgreSQLContainerFixture.cs @@ -0,0 +1,32 @@ +using Aspire.Components.Common.Tests; +using Testcontainers.PostgreSql; +using Xunit; + +namespace CommunityToolkit.Aspire.Marten.Tests; + +public sealed class PostgreSQLContainerFixture : IAsyncLifetime +{ + public PostgreSqlContainer? Container { get; private set; } + + public string GetConnectionString() => Container?.GetConnectionString() ?? + throw new InvalidOperationException("The test container was not initialized."); + + public async Task InitializeAsync() + { + if (RequiresDockerAttribute.IsSupported) + { + Container = new PostgreSqlBuilder() + .WithImage($"{PostgresContainerImageTags.Registry}/{PostgresContainerImageTags.Image}:{PostgresContainerImageTags.Tag}") + .Build(); + await Container.StartAsync(); + } + } + + public async Task DisposeAsync() + { + if (Container is not null) + { + await Container.DisposeAsync(); + } + } +} diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/PostgresContainerImageTags.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/PostgresContainerImageTags.cs new file mode 100644 index 00000000..b9bd12b8 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/PostgresContainerImageTags.cs @@ -0,0 +1,13 @@ +namespace CommunityToolkit.Aspire.Marten.Tests; + +internal static class PostgresContainerImageTags +{ + /// docker.io + public const string Registry = "netaspireci.azurecr.io"; + + /// library/postgres + public const string Image = "library/postgres"; + + /// 17.0 + public const string Tag = "17.0"; +} From ef3d13de0eb5a2f35e89401a6258811c691b3098 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 25 Oct 2024 00:40:59 +0330 Subject: [PATCH 06/10] Add conformance tests --- .../MartenApplicationBuilderExtensions.cs | 8 +- .../ConformanceTests.cs | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs diff --git a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs index 030a2018..51c4c01e 100644 --- a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs @@ -92,19 +92,15 @@ private static void AddMartenClient( .WithTracing(tracing => { tracing.AddSource("Marten"); - }) - .WithMetrics(metrics => - { - metrics.AddMeter("Marten"); }); } if (!settings.DisableMetrics) { builder.Services.AddOpenTelemetry() - .WithTracing(tracing => + .WithMetrics(metrics => { - tracing.AddSource("Marten"); + metrics.AddMeter("Marten"); }); } diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs new file mode 100644 index 00000000..206f805a --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Components.Common.Tests; +using Aspire.Components.ConformanceTests; +using CommunityToolkit.Aspire.Marten; +using CommunityToolkit.Aspire.Marten.Tests; +using Marten; +using Microsoft.DotNet.RemoteExecutor; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Npgsql; +using Xunit; + +namespace CommunityToolkit.Aspire.Meilisearch.Tests; + +public class ConformanceTests(PostgreSQLContainerFixture containerFixture) : ConformanceTests, IClassFixture +{ + protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton; + + protected override string ActivitySourceName => "Marten"; + + protected override string[] RequiredLogCategories => []; + + protected override bool CanConnectToServer => RequiresDockerAttribute.IsSupported; + + protected override bool SupportsKeyedRegistrations => true; + + protected override string? ConfigurationSectionName => "Aspire:Marten"; + + protected override void PopulateConfiguration(ConfigurationManager configuration, string? key = null) + { + var connectionString = RequiresDockerAttribute.IsSupported ? + $"{containerFixture.GetConnectionString()}" : + "Host=localhost;Database=test_aspire_marten1"; + + configuration.AddInMemoryCollection( + [ + new KeyValuePair(CreateConfigKey("Aspire:Marten", key, "ConnectionString"), connectionString), + new KeyValuePair($"ConnectionStrings:{key}", $"{connectionString}") + ]); + } + + protected override void RegisterComponent(HostApplicationBuilder builder, Action? configure = null, string? key = null) + { + if (key is null) + { + builder.AddMartenClient("postgres", configureSettings: configure); + } + else + { + builder.AddKeyedMartenClient(key, configureSettings: configure); + } + } + + protected override string ValidJsonConfig => """ + { + "Aspire": { + "Marten": { + "Client": { + "ConnectionString": "Host=localhost;Database=test_aspire_marten1" + } + } + } + } + """; + + protected override (string json, string error)[] InvalidJsonToErrorMessage => new[] + { + ("""{"Aspire": { "Marten":{ "Client": { "ConnectionString": 3 }}}}""", "Value is \"integer\" but should be \"string\""), + }; + + protected override void SetHealthCheck(MartenSettings options, bool enabled) + { + options.DisableHealthChecks = !enabled; + } + + protected override void SetMetrics(MartenSettings options, bool enabled) + { + options.DisableMetrics = !enabled; + } + + protected override void SetTracing(MartenSettings options, bool enabled) + { + options.DisableTracing = !enabled; + } + + protected override void TriggerActivity(DocumentStore service) + { + using var command = new NpgsqlCommand("Select 1;"); + using var session = service.QuerySession(); + session.Execute(command); + } +} From c573619b2534fba774d35878ad45991ddc65a9ee Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 25 Oct 2024 01:32:31 +0330 Subject: [PATCH 07/10] Add example project --- CommunityToolkit.Aspire.sln | 26 +++- Directory.Packages.props | 2 + ...ityToolkit.Aspire.Marten.ApiService.csproj | 14 +++ .../Movie.cs | 8 ++ .../Program.cs | 47 +++++++ .../Properties/launchSettings.json | 38 ++++++ .../appsettings.json | 9 ++ ...munityToolkit.Aspire.Marten.AppHost.csproj | 21 ++++ .../Program.cs | 10 ++ .../Properties/launchSettings.json | 29 +++++ .../appsettings.json | 9 ++ ...olkit.Aspire.Marten.ServiceDefaults.csproj | 22 ++++ .../Extensions.cs | 117 ++++++++++++++++++ 13 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ApiService/CommunityToolkit.Aspire.Marten.ApiService.csproj create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Movie.cs create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Properties/launchSettings.json create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ApiService/appsettings.json create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.AppHost/CommunityToolkit.Aspire.Marten.AppHost.csproj create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Program.cs create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Properties/launchSettings.json create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.AppHost/appsettings.json create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/CommunityToolkit.Aspire.Marten.ServiceDefaults.csproj create mode 100644 examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/Extensions.cs diff --git a/CommunityToolkit.Aspire.sln b/CommunityToolkit.Aspire.sln index 082b1fcc..e930c879 100644 --- a/CommunityToolkit.Aspire.sln +++ b/CommunityToolkit.Aspire.sln @@ -89,7 +89,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Hos EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten", "src\CommunityToolkit.Aspire.Marten\CommunityToolkit.Aspire.Marten.csproj", "{DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Marten.Tests", "tests\CommunityToolkit.Aspire.Marten.Tests\CommunityToolkit.Aspire.Marten.Tests.csproj", "{8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten.Tests", "tests\CommunityToolkit.Aspire.Marten.Tests\CommunityToolkit.Aspire.Marten.Tests.csproj", "{8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "marten", "marten", "{89330EB0-DD97-43F1-93AE-8CAAD820F3D5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten.AppHost", "examples\marten\CommunityToolkit.Aspire.Marten.AppHost\CommunityToolkit.Aspire.Marten.AppHost.csproj", "{49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Aspire.Marten.ApiService", "examples\marten\CommunityToolkit.Aspire.Marten.ApiService\CommunityToolkit.Aspire.Marten.ApiService.csproj", "{E022414D-36D8-436A-A66A-BEE337FEA712}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Marten.ServiceDefaults", "examples\marten\CommunityToolkit.Aspire.Marten.ServiceDefaults\CommunityToolkit.Aspire.Marten.ServiceDefaults.csproj", "{67CEEED4-72DA-4B09-93CE-D4313E3F410D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -237,6 +245,18 @@ Global {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Debug|Any CPU.Build.0 = Debug|Any CPU {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Release|Any CPU.ActiveCfg = Release|Any CPU {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B}.Release|Any CPU.Build.0 = Release|Any CPU + {49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3}.Release|Any CPU.Build.0 = Release|Any CPU + {E022414D-36D8-436A-A66A-BEE337FEA712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E022414D-36D8-436A-A66A-BEE337FEA712}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E022414D-36D8-436A-A66A-BEE337FEA712}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E022414D-36D8-436A-A66A-BEE337FEA712}.Release|Any CPU.Build.0 = Release|Any CPU + {67CEEED4-72DA-4B09-93CE-D4313E3F410D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67CEEED4-72DA-4B09-93CE-D4313E3F410D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67CEEED4-72DA-4B09-93CE-D4313E3F410D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67CEEED4-72DA-4B09-93CE-D4313E3F410D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -283,6 +303,10 @@ Global {F6A9CC5C-91A2-4AAB-AEC9-8007A62A081E} = {561CEB82-3D97-49D0-932E-664E6779FC61} {DFF1D3F3-31D3-44EA-ADB9-4BD7F7AF626D} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1} {8FC3E08E-8CEF-4D9A-9013-0B6AFE1BB05B} = {899F0713-7FC6-4750-BAFC-AC650B35B453} + {89330EB0-DD97-43F1-93AE-8CAAD820F3D5} = {8519CC01-1370-47C8-AD94-B0F326B1563F} + {49669F3F-A5E4-4ABD-8CAE-C14E9D5C70B3} = {89330EB0-DD97-43F1-93AE-8CAAD820F3D5} + {E022414D-36D8-436A-A66A-BEE337FEA712} = {89330EB0-DD97-43F1-93AE-8CAAD820F3D5} + {67CEEED4-72DA-4B09-93CE-D4313E3F410D} = {89330EB0-DD97-43F1-93AE-8CAAD820F3D5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {08B1D4B8-D2C5-4A64-BB8B-E1A2B29525F0} diff --git a/Directory.Packages.props b/Directory.Packages.props index 398f907f..5acf4f2c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,6 +7,7 @@ + @@ -37,6 +38,7 @@ + diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/CommunityToolkit.Aspire.Marten.ApiService.csproj b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/CommunityToolkit.Aspire.Marten.ApiService.csproj new file mode 100644 index 00000000..92b7ac7a --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/CommunityToolkit.Aspire.Marten.ApiService.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Movie.cs b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Movie.cs new file mode 100644 index 00000000..babd63fc --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Movie.cs @@ -0,0 +1,8 @@ +namespace CommunityToolkit.Aspire.Marten.ApiService; + +public class Movie +{ + public string? Id { get; set; } + public string? Title { get; set; } + public List? Genres { get; set; } +} \ No newline at end of file diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs new file mode 100644 index 00000000..3877410d --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs @@ -0,0 +1,47 @@ +using CommunityToolkit.Aspire.Marten.ApiService; +using Marten; +using Marten.Services; + +var builder = WebApplication.CreateBuilder(args); + +builder.AddServiceDefaults(); + +builder.AddMartenClient("postgres", configureStoreOptions: (storeOptions) => +{ + storeOptions.OpenTelemetry.TrackConnections = TrackLevel.Verbose; + + storeOptions.OpenTelemetry.TrackEventCounters(); +}); + +var app = builder.Build(); + +app.MapDefaultEndpoints(); + +app.MapGet("/create", async (DocumentStore documentStore) => +{ + using var session = documentStore.LightweightSession(); + + var documents = new Movie[] { + new() { Id = "1", Title = "Carol", Genres = ["Romance", "Drama"] }, + new() { Id = "2", Title = "Wonder Woman", Genres = ["Action", "Adventure"] }, + new() { Id = "3", Title = "Life of Pi", Genres = ["Adventure", "Drama"] }, + new() { Id = "4", Title = "Mad Max: Fury Road", Genres = ["Adventure", "Science Fiction"] }, + new() { Id = "5", Title = "Moana", Genres = ["Fantasy", "Action"] }, + new() { Id = "6", Title = "Philadelphia", Genres = ["Drama"] } + }; + + session.Store(documents); + await session.SaveChangesAsync(); +}); + +app.MapGet("/get", async (DocumentStore documentStore) => +{ + using var session = documentStore.QuerySession(); + + var data = await session.Query() + .ToListAsync(); + + return data; +}); + +app.Run(); diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Properties/launchSettings.json b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Properties/launchSettings.json new file mode 100644 index 00000000..1500f8c2 --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:44703", + "sslPort": 44332 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5038", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7061;http://localhost:5038", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/appsettings.json b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/CommunityToolkit.Aspire.Marten.AppHost.csproj b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/CommunityToolkit.Aspire.Marten.AppHost.csproj new file mode 100644 index 00000000..07537b8a --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/CommunityToolkit.Aspire.Marten.AppHost.csproj @@ -0,0 +1,21 @@ + + + + Exe + net8.0 + enable + enable + true + 1fa0b68a-1f54-478f-858a-af0982b87863 + + + + + + + + + + + + diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Program.cs b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Program.cs new file mode 100644 index 00000000..51b2fa16 --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Program.cs @@ -0,0 +1,10 @@ +var builder = DistributedApplication.CreateBuilder(args); + +var postgres = builder.AddPostgres("pg"); +var db = postgres.AddDatabase("postgres"); + +builder.AddProject("communitytoolkit-aspire-marten-apiservice") + .WithReference(db); + + +builder.Build().Run(); diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Properties/launchSettings.json b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Properties/launchSettings.json new file mode 100644 index 00000000..180cfaef --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:17095;http://localhost:15105", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21279", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22168" + } + }, + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:15105", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19184", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20278" + } + } + } +} diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/appsettings.json b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/appsettings.json new file mode 100644 index 00000000..31c092aa --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.AppHost/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + } +} diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/CommunityToolkit.Aspire.Marten.ServiceDefaults.csproj b/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/CommunityToolkit.Aspire.Marten.ServiceDefaults.csproj new file mode 100644 index 00000000..2388aea6 --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/CommunityToolkit.Aspire.Marten.ServiceDefaults.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/Extensions.cs b/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/Extensions.cs new file mode 100644 index 00000000..b34d7625 --- /dev/null +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ServiceDefaults/Extensions.cs @@ -0,0 +1,117 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.ServiceDiscovery; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.Hosting; +// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// This project should be referenced by each service project in your solution. +// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults +public static class Extensions +{ + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation(); + }) + .WithTracing(tracing => + { + tracing.AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } +} From 3f0f6a683b809f41ea716d127d59134a34b5d543 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 25 Oct 2024 01:42:45 +0330 Subject: [PATCH 08/10] Add AppHost test --- .../AppHostTests.cs | 28 +++++++++++++++++++ ...ommunityToolkit.Aspire.Marten.Tests.csproj | 1 + .../ConformanceTests.cs | 1 - 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/CommunityToolkit.Aspire.Marten.Tests/AppHostTests.cs diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/AppHostTests.cs new file mode 100644 index 00000000..792a0c57 --- /dev/null +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/AppHostTests.cs @@ -0,0 +1,28 @@ +using CommunityToolkit.Aspire.Testing; +using Aspire.Components.Common.Tests; +using FluentAssertions; +using System.Net.Http.Json; + +namespace CommunityToolkit.Aspire.Marten.Tests; + +[RequiresDocker] +public class AppHostTests(AspireIntegrationTestFixture fixture) : IClassFixture> +{ + [Fact] + public async Task ApiServiceCreateData() + { + var resourceName = "communitytoolkit-aspire-marten-apiservice"; + await fixture.ResourceNotificationService.WaitForResourceAsync(resourceName, KnownResourceStates.Running).WaitAsync(TimeSpan.FromMinutes(1)); + var httpClient = fixture.CreateHttpClient(resourceName); + + var createResponse = await httpClient.GetAsync("/create"); + createResponse.StatusCode.Should().Be(HttpStatusCode.OK); + + var getResponse = await httpClient.GetAsync("/get"); + getResponse.StatusCode.Should().Be(HttpStatusCode.OK); + + var data = await getResponse.Content.ReadFromJsonAsync>(); + Assert.NotNull(data); + Assert.NotEmpty(data); + } +} \ No newline at end of file diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj index 9b17cca5..c85535b3 100644 --- a/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj @@ -11,6 +11,7 @@ + diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs b/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs index 206f805a..cc5e9522 100644 --- a/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/ConformanceTests.cs @@ -6,7 +6,6 @@ using CommunityToolkit.Aspire.Marten; using CommunityToolkit.Aspire.Marten.Tests; using Marten; -using Microsoft.DotNet.RemoteExecutor; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; From cab6de83c322f12f181a476246cfff7c4e5b9e42 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 25 Oct 2024 02:03:38 +0330 Subject: [PATCH 09/10] Make assembly experimental --- .../Program.cs | 2 + .../AssemblyInfo.cs | 3 + .../MartenApplicationBuilderExtensions.cs | 56 ++++++++++++++----- ...ommunityToolkit.Aspire.Marten.Tests.csproj | 4 ++ 4 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs diff --git a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs index 3877410d..5483db6d 100644 --- a/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs +++ b/examples/marten/CommunityToolkit.Aspire.Marten.ApiService/Program.cs @@ -2,6 +2,8 @@ using Marten; using Marten.Services; +#pragma warning disable CTASPIREMARTEN001 + var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); diff --git a/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs b/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs new file mode 100644 index 00000000..a31da57d --- /dev/null +++ b/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Diagnostics.CodeAnalysis; + +[assembly: Experimental("CTASPIREMARTEN001", UrlFormat = "https://aka.ms/dotnet/aspire/diagnostics#{0}")] \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs index 51c4c01e..1a2267a1 100644 --- a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs @@ -11,19 +11,21 @@ namespace Microsoft.Extensions.Hosting; /// -/// TODO +/// Provides extension methods for adding and configuring Marten in an . /// public static class MartenApplicationBuilderExtensions { private const string DefaultConfigSectionName = "Aspire:Marten"; /// - /// TODO + /// Registers as a singleton in the services provided by the . /// - /// - /// - /// - /// + /// Reads the configuration from "Aspire:Marten" section. + /// The to read config from and add services to. + /// The connection name to use to find a connection string. + /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration. + /// An optional action to configure . + /// If required ConnectionString is not provided in configuration section public static void AddMartenClient( this IHostApplicationBuilder builder, string connectionName, @@ -38,12 +40,15 @@ public static void AddMartenClient( } /// - /// TOOD + /// Registers as a keyed singleton for the given in the services provided by the . /// - /// - /// - /// - /// + /// Reads the configuration from "Aspire:Marten" section. + /// The to read config from and add services to. + /// The connection name to use to find a connection string. + /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration. + /// An optional action to configure . + /// If required ConnectionString is not provided in configuration section + public static void AddKeyedMartenClient( this IHostApplicationBuilder builder, string name, @@ -61,6 +66,15 @@ public static void AddKeyedMartenClient( serviceKey: name); } + /// + /// Adds a Marten client to the application builder with the specified configuration. + /// + /// The to add the Marten client to. + /// The name of the configuration section to use. + /// An optional action to configure . + /// An optional action to configure . + /// The name of the connection string to use. + /// An optional service key for the Marten client. private static void AddMartenClient( this IHostApplicationBuilder builder, string configurationSectionName, @@ -85,7 +99,6 @@ private static void AddMartenClient( builder.RegisterMartenServices(settings, configurationSectionName, connectionName, serviceKey, configureStoreOptions); - if (!settings.DisableTracing) { builder.Services.AddOpenTelemetry() @@ -118,9 +131,17 @@ private static void AddMartenClient( } } + /// + /// Registers Marten services with the specified settings and configuration. + /// + /// The to register the services with. + /// The to use. + /// The name of the configuration section to use. + /// The name of the connection string to use. + /// An optional service key for the Marten client. + /// An optional action to configure . private static void RegisterMartenServices(this IHostApplicationBuilder builder, MartenSettings settings, string configurationSectionName, string connectionName, object? serviceKey, Action? configureStoreOptions) { - builder.Services.AddKeyedSingleton(serviceKey is null ? "Aspire.Marten" : $"Aspire.Marten_{connectionName}", (serviceProvider, _) => { ValidateConnectionString(settings.ConnectionString, connectionName, DefaultConfigSectionName); @@ -177,6 +198,13 @@ private static void RegisterMartenServices(this IHostApplicationBuilder builder, } } + /// + /// Validates the specified connection string. + /// + /// The connection string to validate. + /// The name of the connection string. + /// The default configuration section name. + /// Thrown if the connection string is null or whitespace. private static void ValidateConnectionString(string? connectionString, string connectionName, string defaultConfigSectionName) { if (string.IsNullOrWhiteSpace(connectionString)) @@ -184,4 +212,4 @@ private static void ValidateConnectionString(string? connectionString, string co throw new InvalidOperationException($"ConnectionString is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'ConnectionString' key in '{defaultConfigSectionName}' configuration section."); } } -} \ No newline at end of file +} diff --git a/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj index c85535b3..83bc29b3 100644 --- a/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj +++ b/tests/CommunityToolkit.Aspire.Marten.Tests/CommunityToolkit.Aspire.Marten.Tests.csproj @@ -4,6 +4,10 @@ net8.0 enable enable + + $(NoWarn); + CTASPIREMARTEN001; + From 54eb781f069844760128383ca3dcc539b9fa01ce Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Fri, 25 Oct 2024 14:16:01 +0330 Subject: [PATCH 10/10] Address PR feedback --- docs/diagnostics.md | 3 +++ src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs | 3 --- .../MartenApplicationBuilderExtensions.cs | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) delete mode 100644 src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs diff --git a/docs/diagnostics.md b/docs/diagnostics.md index 9f4264f8..d7c7d9f4 100644 --- a/docs/diagnostics.md +++ b/docs/diagnostics.md @@ -10,3 +10,6 @@ In these cases, refer to the `` docs section of the API for more inform Once a release of .NET Aspire with that API is available, the API in the .NET Aspire Community Toolkit will be marked as obsolete and will be removed in a future release. +## CTASPIREMARTEN001 + +The `CommunityToolkit.Aspire.Marten` package may introduce significant or breaking changes in its feature versions, as it does not encompass all `Marten` functionalities, including features like `AsyncDaemon`. diff --git a/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs b/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs deleted file mode 100644 index a31da57d..00000000 --- a/src/CommunityToolkit.Aspire.Marten/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -[assembly: Experimental("CTASPIREMARTEN001", UrlFormat = "https://aka.ms/dotnet/aspire/diagnostics#{0}")] \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs index 1a2267a1..5e77652f 100644 --- a/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs +++ b/src/CommunityToolkit.Aspire.Marten/MartenApplicationBuilderExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Logging; using Npgsql; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.Hosting; @@ -26,6 +27,7 @@ public static class MartenApplicationBuilderExtensions /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration. /// An optional action to configure . /// If required ConnectionString is not provided in configuration section + [Experimental("CTASPIREMARTEN001", UrlFormat = "https://aka.ms/communitytoolkit/aspire/diagnostics#{0}")] public static void AddMartenClient( this IHostApplicationBuilder builder, string connectionName, @@ -49,6 +51,7 @@ public static void AddMartenClient( /// An optional action to configure . /// If required ConnectionString is not provided in configuration section + [Experimental("CTASPIREMARTEN001", UrlFormat = "https://aka.ms/communitytoolkit/aspire/diagnostics#{0}")] public static void AddKeyedMartenClient( this IHostApplicationBuilder builder, string name,