From 7c0c0d8b598741b4588934648cc44c7aa5a4c4e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 30 Sep 2024 12:08:55 +0000 Subject: [PATCH 1/7] Update .NET SDK Update .NET SDK to version 9.0.100-rtm.24479.2. --- updated-dependencies: - dependency-name: Microsoft.NET.Sdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: github-actions[bot] --- global.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index 9ace0177b48..52ded1fe7bb 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "9.0.100-rc.2.24468.2" + "version": "9.0.100-rtm.24479.2" }, "tools": { - "dotnet": "9.0.100-rc.2.24468.2", + "dotnet": "9.0.100-rtm.24479.2", "runtimes": { "dotnet/x64": [ "8.0.0", From 06e66b73f4b46aed3a698e3c0b984f384febd27b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:30:45 +0000 Subject: [PATCH 2/7] Update dependencies from https://github.com/dotnet/arcade build 20240925.3 (#5458) [main] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- global.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ae5cafe2d4b..674eca8d91e 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -138,13 +138,13 @@ - + https://github.com/dotnet/arcade - 8c08d889b3c0b3f19398faceaccd74d0f184a3fb + 69abe6b2063083c0b35fc3a5b16cb2bdbaf5e8b0 - + https://github.com/dotnet/arcade - 8c08d889b3c0b3f19398faceaccd74d0f184a3fb + 69abe6b2063083c0b35fc3a5b16cb2bdbaf5e8b0 diff --git a/global.json b/global.json index 44d535df314..556fb52a7df 100644 --- a/global.json +++ b/global.json @@ -16,7 +16,7 @@ "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.2.0", - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24463.3", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24463.3" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24475.3", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24475.3" } } From 7a193a0db9130d4d8cdd0395e4a38597ee7bad7b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:41:06 +0000 Subject: [PATCH 3/7] Update dependencies from https://github.com/dotnet/arcade build 20240923.1 (#5459) [dev] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- global.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2d806523a16..e4dcd0226ff 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -170,13 +170,13 @@ - + https://github.com/dotnet/arcade - 04b9022eba9c184a8036328af513c22e6949e8b6 + 1230437de1ab7b3e15fe7cdfe7ffce2f65449959 - + https://github.com/dotnet/arcade - 04b9022eba9c184a8036328af513c22e6949e8b6 + 1230437de1ab7b3e15fe7cdfe7ffce2f65449959 diff --git a/global.json b/global.json index 9ace0177b48..bb3ad2432d7 100644 --- a/global.json +++ b/global.json @@ -18,7 +18,7 @@ "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.2.0", - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24466.2", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24466.2" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24473.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24473.1" } } From 18002bee78062a2455d9a6f492695240a9a838f0 Mon Sep 17 00:00:00 2001 From: Iliar Turdushev Date: Tue, 1 Oct 2024 11:53:25 +0200 Subject: [PATCH 4/7] Add methods allowing retrieval of HttpRequestMessage from ResilienceContext (#5460) Fixes #4957 - Adds extension methods allowing retrieval of the request message from resilience context - Replaces usage of ResilienceKeys.RequestMessage variable with corresponding Get/Set methods --- .../RequestMessageSnapshotStrategy.cs | 4 +- ...enceHttpClientBuilderExtensions.Hedging.cs | 2 +- .../Internal/ResilienceKeys.cs | 2 +- .../HttpResilienceContextExtensions.cs | 46 +++++++++++ .../Resilience/ResilienceHandler.cs | 9 +-- .../Internal/RoutingResilienceStrategy.cs | 5 +- .../RequestMessageSnapshotStrategyTests.cs | 12 ++- .../HttpResilienceContextExtensionsTests.cs | 77 +++++++++++++++++++ .../Resilience/ResilienceHandlerTest.cs | 3 +- .../Routing/RoutingResilienceStrategyTests.cs | 13 +++- 10 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpResilienceContextExtensions.cs create mode 100644 test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/HttpResilienceContextExtensionsTests.cs diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/Internals/RequestMessageSnapshotStrategy.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/Internals/RequestMessageSnapshotStrategy.cs index 8f484f1cbcd..9b4fe7e9c8d 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/Internals/RequestMessageSnapshotStrategy.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Hedging/Internals/RequestMessageSnapshotStrategy.cs @@ -20,7 +20,9 @@ protected override async ValueTask> ExecuteCore RequestMessage = new("Resilience.Http.RequestMessage"); + public static readonly ResiliencePropertyKey RequestMessage = new("Resilience.Http.RequestMessage"); public static readonly ResiliencePropertyKey RoutingStrategy = new("Resilience.Http.RequestRoutingStrategy"); diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpResilienceContextExtensions.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpResilienceContextExtensions.cs new file mode 100644 index 00000000000..b04bd37a2ad --- /dev/null +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/HttpResilienceContextExtensions.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Net.Http; +using Microsoft.Extensions.Http.Resilience.Internal; +using Microsoft.Shared.DiagnosticIds; +using Microsoft.Shared.Diagnostics; +using Polly; + +namespace Polly; + +/// +/// Provides utility methods for working with . +/// +[Experimental(diagnosticId: DiagnosticIds.Experiments.Resilience, UrlFormat = DiagnosticIds.UrlFormat)] +public static class HttpResilienceContextExtensions +{ + /// + /// Gets the request message from the . + /// + /// The resilience context. + /// + /// The request message. + /// If the request message is not present in the the method returns . + /// + /// is . + public static HttpRequestMessage? GetRequestMessage(this ResilienceContext context) + { + _ = Throw.IfNull(context); + return context.Properties.GetValue(ResilienceKeys.RequestMessage, default); + } + + /// + /// Sets the request message on the . + /// + /// The resilience context. + /// The request message. + /// is . + public static void SetRequestMessage(this ResilienceContext context, HttpRequestMessage? requestMessage) + { + _ = Throw.IfNull(context); + context.Properties.Set(ResilienceKeys.RequestMessage, requestMessage); + } +} diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/ResilienceHandler.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/ResilienceHandler.cs index 41a408fa718..aff82260365 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/ResilienceHandler.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Resilience/ResilienceHandler.cs @@ -58,7 +58,7 @@ protected override async Task SendAsync(HttpRequestMessage ResilienceContext context = GetOrSetResilienceContext(request, cancellationToken, out bool created); TrySetRequestMetadata(context, request); - SetRequestMessage(context, request); + context.SetRequestMessage(request); try { @@ -117,7 +117,7 @@ protected override HttpResponseMessage Send(HttpRequestMessage request, Cancella ResilienceContext context = GetOrSetResilienceContext(request, cancellationToken, out bool created); TrySetRequestMetadata(context, request); - SetRequestMessage(context, request); + context.SetRequestMessage(request); try { @@ -165,11 +165,8 @@ private static void TrySetRequestMetadata(ResilienceContext context, HttpRequest } } - private static void SetRequestMessage(ResilienceContext context, HttpRequestMessage request) - => context.Properties.Set(ResilienceKeys.RequestMessage, request); - private static HttpRequestMessage GetRequestMessage(ResilienceContext context, HttpRequestMessage request) - => context.Properties.GetValue(ResilienceKeys.RequestMessage, request); + => context.GetRequestMessage() ?? request; private static void RestoreResilienceContext(ResilienceContext context, HttpRequestMessage request, bool created) { diff --git a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/Internal/RoutingResilienceStrategy.cs b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/Internal/RoutingResilienceStrategy.cs index 0aefc6cf171..2054cbcccbc 100644 --- a/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/Internal/RoutingResilienceStrategy.cs +++ b/src/Libraries/Microsoft.Extensions.Http.Resilience/Routing/Internal/RoutingResilienceStrategy.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Net.Http; using System.Threading.Tasks; using Microsoft.Extensions.Http.Resilience.Internal; using Microsoft.Shared.Diagnostics; @@ -26,7 +27,9 @@ protected override async ValueTask> ExecuteCore @@ -39,5 +39,15 @@ public void ExecuteAsync_RequestMessageNotFound_Throws() strategy.Invoking(s => s.Execute(() => { })).Should().Throw(); } + [Fact] + public void ExecuteAsync_RequestMessageIsNull_Throws() + { + var strategy = Create(); + var context = ResilienceContextPool.Shared.Get(); + context.SetRequestMessage(null); + + strategy.Invoking(s => s.Execute(_ => { }, context)).Should().Throw(); + } + private static ResiliencePipeline Create() => new ResiliencePipelineBuilder().AddStrategy(_ => new RequestMessageSnapshotStrategy(), Mock.Of()).Build(); } diff --git a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/HttpResilienceContextExtensionsTests.cs b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/HttpResilienceContextExtensionsTests.cs new file mode 100644 index 00000000000..9cd1255c992 --- /dev/null +++ b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/HttpResilienceContextExtensionsTests.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Net.Http; +using Microsoft.Extensions.Http.Resilience.Internal; +using Polly; +using Xunit; + +namespace Microsoft.Extensions.Http.Resilience.Test.Resilience; + +public class HttpResilienceContextExtensionsTests +{ + [Fact] + public void GetRequestMessage_ResilienceContextIsNull_Throws() + { + ResilienceContext context = null!; + Assert.Throws(context.GetRequestMessage); + } + + [Fact] + public void GetRequestMessage_RequestMessageIsMissing_ReturnsNull() + { + var context = ResilienceContextPool.Shared.Get(); + + Assert.Null(context.GetRequestMessage()); + } + + [Fact] + public void GetRequestMessage_RequestMessageIsNull_ReturnsNull() + { + var context = ResilienceContextPool.Shared.Get(); + context.Properties.Set(ResilienceKeys.RequestMessage, null); + + Assert.Null(context.GetRequestMessage()); + } + + [Fact] + public void GetRequestMessage_RequestMessageIsPresent_ReturnsRequestMessage() + { + var context = ResilienceContextPool.Shared.Get(); + using var request = new HttpRequestMessage(); + context.Properties.Set(ResilienceKeys.RequestMessage, request); + + Assert.Same(request, context.GetRequestMessage()); + } + + [Fact] + public void SetRequestMessage_ResilienceContextIsNull_Throws() + { + ResilienceContext context = null!; + using var request = new HttpRequestMessage(); + + Assert.Throws(() => context.SetRequestMessage(request)); + } + + [Fact] + public void SetRequestMessage_RequestMessageIsNull_SetsNullRequestMessage() + { + var context = ResilienceContextPool.Shared.Get(); + context.SetRequestMessage(null); + + Assert.True(context.Properties.TryGetValue(ResilienceKeys.RequestMessage, out HttpRequestMessage? request)); + Assert.Null(request); + } + + [Fact] + public void SetRequestMessage_RequestMessageIsNotNull_SetsRequestMessage() + { + var context = ResilienceContextPool.Shared.Get(); + using var request = new HttpRequestMessage(); + context.SetRequestMessage(request); + + Assert.True(context.Properties.TryGetValue(ResilienceKeys.RequestMessage, out HttpRequestMessage? actualRequest)); + Assert.Same(request, actualRequest); + } +} diff --git a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/ResilienceHandlerTest.cs b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/ResilienceHandlerTest.cs index 8a1831d67b8..9de72555401 100644 --- a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/ResilienceHandlerTest.cs +++ b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Resilience/ResilienceHandlerTest.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using FluentAssertions; using Microsoft.Extensions.Http.Diagnostics; -using Microsoft.Extensions.Http.Resilience.Internal; using Microsoft.Extensions.Http.Resilience.Test.Helpers; using Polly; using Xunit; @@ -108,7 +107,7 @@ public async Task Send_EnsureInvoker(bool executionContextSet, bool asynchronous handler.InnerHandler = new TestHandlerStub((r, _) => { r.GetResilienceContext().Should().NotBeNull(); - r.GetResilienceContext()!.Properties.GetValue(ResilienceKeys.RequestMessage, null!).Should().BeSameAs(r); + r.GetResilienceContext()!.GetRequestMessage().Should().BeSameAs(r); return Task.FromResult(new HttpResponseMessage { StatusCode = HttpStatusCode.Created }); }); diff --git a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Routing/RoutingResilienceStrategyTests.cs b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Routing/RoutingResilienceStrategyTests.cs index 341d32087f8..ed1a6d5c6b2 100644 --- a/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Routing/RoutingResilienceStrategyTests.cs +++ b/test/Libraries/Microsoft.Extensions.Http.Resilience.Tests/Routing/RoutingResilienceStrategyTests.cs @@ -4,7 +4,6 @@ using System; using System.Net.Http; using FluentAssertions; -using Microsoft.Extensions.Http.Resilience.Internal; using Microsoft.Extensions.Http.Resilience.Routing.Internal; using Moq; using Polly; @@ -22,6 +21,16 @@ public void NoRequestMessage_Throws() strategy.Invoking(s => s.Execute(() => { })).Should().Throw().WithMessage("The HTTP request message was not found in the resilience context."); } + [Fact] + public void RequestMessageIsNull_Throws() + { + var strategy = Create(() => Mock.Of()); + var context = ResilienceContextPool.Shared.Get(); + context.SetRequestMessage(null); + + strategy.Invoking(s => s.Execute(_ => { }, context)).Should().Throw().WithMessage("The HTTP request message was not found in the resilience context."); + } + [Fact] public void NoRoutingProvider_Ok() { @@ -29,7 +38,7 @@ public void NoRoutingProvider_Ok() var strategy = Create(null); var context = ResilienceContextPool.Shared.Get(); - context.Properties.Set(ResilienceKeys.RequestMessage, request); + context.SetRequestMessage(request); strategy.Invoking(s => s.Execute(_ => { }, context)).Should().NotThrow(); } From bc9bbd213d2256383997c7c16aa1401d7995ae01 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Wed, 2 Oct 2024 14:48:53 -0700 Subject: [PATCH 5/7] Getting ready to merge dev into main --- Directory.Build.props | 1 - Directory.Build.targets | 2 -- eng/Net9Workarounds.props | 7 ---- eng/Net9Workarounds.targets | 67 ------------------------------------- eng/Versions.props | 5 ++- 5 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 eng/Net9Workarounds.props delete mode 100644 eng/Net9Workarounds.targets diff --git a/Directory.Build.props b/Directory.Build.props index fef9d781511..7e4dc9ad808 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,6 @@ - diff --git a/Directory.Build.targets b/Directory.Build.targets index 5ee66133050..5fcf797523c 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -8,8 +8,6 @@ - - $(MSBuildWarningsAsMessages);NETSDK1138;MSB3270 diff --git a/eng/Net9Workarounds.props b/eng/Net9Workarounds.props deleted file mode 100644 index 676bad31897..00000000000 --- a/eng/Net9Workarounds.props +++ /dev/null @@ -1,7 +0,0 @@ - - - - false - true - - \ No newline at end of file diff --git a/eng/Net9Workarounds.targets b/eng/Net9Workarounds.targets deleted file mode 100644 index c92595dd496..00000000000 --- a/eng/Net9Workarounds.targets +++ /dev/null @@ -1,67 +0,0 @@ - - - - 99.9 - - true - - - - - - - - - - $(MicrosoftNETCoreAppRuntimewinx64Version) - $(MicrosoftNETCoreAppRefVersion) - - $(MicrosoftNETCoreAppRuntimeVersion) - - - - $(MicrosoftAspNetCoreAppRuntimewinx64Version) - $(MicrosoftAspNetCoreAppRefVersion) - - $(MicrosoftNETCoreAppRuntimeVersion) - - - - $(MicrosoftNETCoreAppRuntimewinx64Version) - - - - $(MicrosoftNETCoreAppRuntimewinx64Version) - - - - $(MicrosoftAspNetCoreAppRuntimewinx64Version) - - - - \ No newline at end of file diff --git a/eng/Versions.props b/eng/Versions.props index e5209b4f90b..0d718b9059b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -8,11 +8,10 @@ $(MajorVersion).$(MinorVersion).$(PatchVersion) true $(MajorVersion).$(MinorVersion).0.0 - true - false + true From bc90b9f4342cfa95b58cbb81172a0e41e0431e36 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Wed, 2 Oct 2024 17:21:17 -0700 Subject: [PATCH 6/7] Fix build --- github-merge-flow.jsonc | 9 +++++---- .../Microsoft.AspNetCore.HeaderParsing.csproj | 5 ++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/github-merge-flow.jsonc b/github-merge-flow.jsonc index 2045a8a6989..3071846fbe1 100644 --- a/github-merge-flow.jsonc +++ b/github-merge-flow.jsonc @@ -2,9 +2,10 @@ { "merge-flow-configurations": { // Automate opening PRs to merge extensions main branch back to dev - "main":{ - "MergeToBranch": "dev", - "ExtraSwitches": "-QuietComments" - } + // Disable this for now as dev branch has been merged to main + // "main":{ + // "MergeToBranch": "dev", + // "ExtraSwitches": "-QuietComments" + // } } } \ No newline at end of file diff --git a/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj b/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj index dfff6aaffa1..6993d36408f 100644 --- a/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj +++ b/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj @@ -8,11 +8,14 @@ $(NetCoreTargetFrameworks) - true true true true true + + + false + $(NoWarn);IL2026 From e11fb6176dbab6b027c946ff030dc14e666e1838 Mon Sep 17 00:00:00 2001 From: Jose Perez Rodriguez Date: Thu, 3 Oct 2024 10:02:14 -0700 Subject: [PATCH 7/7] Fix correctness build --- .../Microsoft.AspNetCore.HeaderParsing.csproj | 5 +---- .../Microsoft.Extensions.Compliance.Redaction.csproj | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj b/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj index 6993d36408f..dfff6aaffa1 100644 --- a/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj +++ b/src/Libraries/Microsoft.AspNetCore.HeaderParsing/Microsoft.AspNetCore.HeaderParsing.csproj @@ -8,14 +8,11 @@ $(NetCoreTargetFrameworks) + true true true true true - - - false - $(NoWarn);IL2026 diff --git a/src/Libraries/Microsoft.Extensions.Compliance.Redaction/Microsoft.Extensions.Compliance.Redaction.csproj b/src/Libraries/Microsoft.Extensions.Compliance.Redaction/Microsoft.Extensions.Compliance.Redaction.csproj index 8a6a526acc1..d331d10ff32 100644 --- a/src/Libraries/Microsoft.Extensions.Compliance.Redaction/Microsoft.Extensions.Compliance.Redaction.csproj +++ b/src/Libraries/Microsoft.Extensions.Compliance.Redaction/Microsoft.Extensions.Compliance.Redaction.csproj @@ -7,12 +7,15 @@ true - true true true true true true + + + false + $(NoWarn);IL2026