Skip to content

Fix Redis persistent lifetime startup#17827

Merged
danegsta merged 2 commits into
mainfrom
danegsta/fix-redis-persistent-lifetime
Jun 2, 2026
Merged

Fix Redis persistent lifetime startup#17827
danegsta merged 2 commits into
mainfrom
danegsta/fix-redis-persistent-lifetime

Conversation

@danegsta
Copy link
Copy Markdown
Member

@danegsta danegsta commented Jun 2, 2026

Description

Redis persistent containers could deadlock before container creation when Redis TLS startup arguments resolved allocated endpoint ports. Those arguments configure the ports Redis listens on inside the container, so they should use endpoint target ports instead of public/allocated ports, which may differ and may not be available before a proxyless persistent container exists.

This updates Redis TLS startup arguments to use target-port bindings for both the primary TLS endpoint and secondary non-TLS endpoint. With this change, the reported AppHost shape starts Redis instead of waiting forever on endpoint allocation:

builder.AddRedis("redis")
       .WithLifetime(ContainerLifetime.Persistent);

Fixes: #17822

Validation:

  • dotnet test --project tests/Aspire.Hosting.Redis.Tests/Aspire.Hosting.Redis.Tests.csproj --no-launch-profile -- --filter-method "*.RedisWithCertificateUsesTargetPortsForCommandLineArgs" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • dotnet test --project tests/Aspire.Hosting.Redis.Tests/Aspire.Hosting.Redis.Tests.csproj --no-launch-profile -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Use Redis endpoint target ports for TLS startup arguments so container command-line evaluation does not wait for allocated public ports before the container exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17827

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17827"

@danegsta danegsta marked this pull request as ready for review June 2, 2026 05:52
Copilot AI review requested due to automatic review settings June 2, 2026 05:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a deadlock when a Redis container with TLS configured is started with ContainerLifetime.Persistent. The TLS startup arguments (--tls-port/--port) were resolving EndpointProperty.Port (the host-side allocated port), which is unavailable before the container exists in proxyless persistent mode, causing endpoint allocation to wait forever. Since these arguments configure ports inside the container, they must use EndpointProperty.TargetPort instead.

Changes:

  • Switch Redis TLS startup arg port references from EndpointProperty.Port to EndpointProperty.TargetPort for both primary (TLS) and secondary (non-TLS) endpoints.
  • Add a regression test (RedisWithCertificateUsesTargetPortsForCommandLineArgs) asserting the args resolve to the container target ports 6379/6380.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs Use EndpointProperty.TargetPort for --tls-port and --port Redis args.
tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs Adds test verifying TLS args use target ports under persistent lifetime.

Use a bounded wait around the Redis argument evaluation regression test so the test fails promptly if endpoint resolution deadlocks again.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

CLI E2E Tests unknown — 110 passed, 0 failed, 2 unknown (commit c122c70)

View all recordings
Status Test Recording Job Artifacts
AddPackageInteractiveWhileAppHostRunningDetached Recording #79011027492 Logs
AddPackageWhileAppHostRunningDetached Recording #79011027492 Logs
AgentCommands_AllHelpOutputs_AreCorrect Recording #79011027167 Logs
AgentInitCommand_DefaultSelection_InstallsDefaultSkills Recording #79011027167 Logs
AgentInitCommand_MigratesDeprecatedConfig Recording #79011027167 Logs
AgentInitCommand_NonInteractive_BundleOnlySkillsBeyondCliCatalog_AreInstallable Recording #79011027167 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp Recording #79011027357 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_DevLocalhost Recording #79011027357 Logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_Isolated Recording #79011027357 Logs
AllPublishMethodsBuildDockerImages Recording #79011027445 Logs
AspireAddAndStartWorkAgainstLegacyAppHostTs Recording #79011027395 Logs
AspireAddPackageVersionToDirectoryPackagesProps Recording #79011027432 Logs
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost Recording #79011027603 Logs
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles Recording #79011027459 Logs
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive Recording #79011027459 Logs
AspireStartUpdatesStaleTypeScriptAppHostPath Recording #79011026940 Logs
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps Recording #79011027432 Logs
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent Recording #79011027432 Logs
Banner_DisplayedOnFirstRun Recording #79011027305 Logs
Banner_DisplayedWithExplicitFlag Recording #79011027305 Logs
Banner_NotDisplayedWithNoLogoFlag Recording #79011027305 Logs
CertificatesClean_RemovesCertificates Recording #79011027554 Logs
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate Recording #79011027554 Logs
CertificatesTrust_WithUntrustedCert_TrustsCertificate Recording #79011027554 Logs
ConfigSetGet_CreatesNestedJsonFormat Recording #79011027230 Logs
CreateAndRunAspireStarterProject Recording #79011027376 Logs
CreateAndRunAspireStarterProjectWithBundle Recording #79011027318 Logs
CreateAndRunEmptyAppHostProject Recording #79011027470 Logs
CreateAndRunJavaEmptyAppHostProject Recording #79011027251 Logs
CreateAndRunJsReactProject Recording #79011027451 Logs
CreateAndRunPolyglotAppHostWithDevLocalhostUrls Recording #79011027376 Logs
CreateAndRunPythonReactProject Recording #79011027239 Logs
CreateAndRunTypeScriptEmptyAppHostProject Recording #79011027489 Logs
CreateAndRunTypeScriptStarterProject Recording #79011027483 Logs
CreateJavaAppHostWithViteApp Recording #79011027579 Logs
CreateTypeScriptAppHostWithViteApp_AllowsGuestAppPackageManagerToDiffer Recording #79011027342 Logs
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain Recording #79011027342 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces Recording #79011026831 Logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces_DevLocalhost Recording #79011026831 Logs
DashboardRunWithOtelTracesReturnsNoTraces Recording #79011026831 Logs
DashboardRunWithOtelTracesReturnsNoTraces_DevLocalhost Recording #79011026831 Logs
DeployK8sBasicApiService Recording #79011027504 Logs
DeployK8sWithExternalHelmChart Recording #79011027289 Logs
DeployK8sWithGarnet Recording #79011027482 Logs
DeployK8sWithMongoDB Recording #79011027178 Logs
DeployK8sWithMySql Recording #79011027312 Logs
DeployK8sWithPostgres Recording #79011027303 Logs
DeployK8sWithRabbitMQ Recording #79011027392 Logs
DeployK8sWithRedis Recording #79011027371 Logs
DeployK8sWithSqlServer Recording #79011027105 Logs
DeployK8sWithValkey Recording #79011027452 Logs
DeployTypeScriptAppToKubernetes Recording #79011027430 Logs
DescribeCommandResolvesReplicaNames Recording #79011027396 Logs
DescribeCommandShowsRunningResources Recording #79011027396 Logs
DetachFormatJsonProducesValidJson Recording #79011027326 Logs
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance Recording #79011027326 Logs
DoPublishAndDeployListStepsWork Recording #79011027045 Logs
DocsCommand_RendersInteractiveMarkdownFromLocalSource Recording #79011027355 Logs
DoctorCommand_DetectsDeprecatedAgentConfig Recording #79011027167 Logs
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain Recording #79011026929 Logs
DoctorCommand_WithSslCertDir_ShowsTrusted Recording #79011026929 Logs
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted Recording #79011026929 Logs
GatewayWithoutExternalEndpoint_FailsPublishWithGuidance Recording #79011027345 Logs
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain Recording #79011027342 Logs
GlobalMigration_HandlesCommentsAndTrailingCommas Recording #79011027230 Logs
GlobalMigration_HandlesMalformedLegacyJson Recording #79011027230 Logs
GlobalMigration_PreservesAllValueTypes Recording #79011027230 Logs
GlobalMigration_SkipsWhenNewConfigExists Recording #79011027230 Logs
GlobalSettings_MigratedFromLegacyFormat Recording #79011027230 Logs
IngressWithoutExternalEndpoint_FailsPublishWithGuidance Recording #79011027345 Logs
InitTypeScriptAppHost_AugmentsExistingViteRepoInWorkspaceSubdirectory Recording #79011027342 Logs
InteractiveCSharpInitCreatesExpectedFiles Recording #79011027098 Logs
InvalidAppHostPathWithComments_IsHealedOnRun Recording #79011027308 Logs
JavaScriptHostingApisRunFromTypeScriptAppHost Recording #79011027445 Logs
LatestCliCanStartStableChannelAppHost Recording #79011027376 Logs
LatestCliCanStartStableChannelTypeScriptAppHost Recording #79011027376 Logs
LegacySettingsMigration_AdjustsRelativeAppHostPath Recording #79011026940 Logs
LogsCommandShowsResourceLogs Recording #79011027367 Logs
OtelLogsReturnsStructuredLogsFromStarterApp Recording #79011027224 Logs
OtelLogsReturnsStructuredLogsFromStarterAppIsolated Recording #79011027224 Logs
PsCommandListsRunningAppHost Recording #79011027201 Logs
PsFormatJsonOutputsOnlyJsonToStdout Recording #79011027201 Logs
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts Recording #79011027537 Logs
PublishWithConfigureEnvFileUpdatesEnvOutput Recording #79011027537 Logs
PublishWithDockerComposeServiceCallbackSucceeds Recording #79011027537 Logs
PublishWithoutOutputPathUsesAppHostDirectoryDefault Recording #79011027537 Logs
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries Recording #79011027192 Logs
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput Recording #79011027192 Logs
RestoreGeneratesSdkFiles Recording #79011027334 Logs
RestoreGeneratesSdkFiles_WithConfiguredToolchain Recording #79011027373 Logs
RestoreRefreshesGeneratedSdkAfterAddingIntegration Recording #79011027373 Logs
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes Recording #79011027463 Logs
RunFromParentDirectory_UsesExistingConfigNearAppHost Recording #79011027469 Logs
RunReportsSyntaxErrorsForDotNetAppHost Recording #79011026951 Logs
RunReportsSyntaxErrorsForTypeScriptAppHost Recording #79011026951 Logs
SecretCrudOnDotNetAppHost Recording #79011027364 Logs
SecretCrudOnTypeScriptAppHost Recording #79011027472 Logs
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels Recording #79011027186 Logs
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets Recording #79011027322 Logs
StartReportsSyntaxErrorsForDotNetAppHost Recording #79011026951 Logs
StartReportsSyntaxErrorsForTypeScriptAppHost Recording #79011026951 Logs
StopAllAppHostsFromAppHostDirectory Recording #79011027365 Logs
StopJavaPolyglotAppHostUsingApphostDirectory Recording #79011027480 Logs
StopNonInteractiveSingleAppHost Recording #79011027365 Logs
StopTypeScriptPolyglotAppHostUsingApphostDirectory Recording #79011027307 Logs
StopWithNoRunningAppHostExitsSuccessfully Recording #79011027492 Logs
TypeScriptAppHostRunDoesNotDeadlockWhenLazyOptionsInvokeAsyncCallback Recording #79011027489 Logs
UnAwaitedChainsCompileWithAutoResolvePromises Recording #79011027373 Logs
UpdateProjectChannelToStable_CSharpEmptyAppHost_PreservesAspireConfigChannel Recording #79011027214 Logs
UpdateProjectChannelToStable_CSharpSingleFileInit_PreservesAspireConfigChannel Recording #79011027214 Logs
UpdateProjectChannelToStable_TypeScriptSingleFileInit_PreservesAspireConfigChannel Recording #79011027214 Logs
UpdateProjectChannelToStable_TypeScript_PreviewsStablePackagesAndPreservesChannel Recording #79011027214 Logs

📹 Recordings uploaded automatically from CI run #26801455791

@danegsta
Copy link
Copy Markdown
Member Author

danegsta commented Jun 2, 2026

/backport to release/13.4

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

Started backporting to release/13.4 (link to workflow run)

@danegsta danegsta merged commit 0ac9090 into main Jun 2, 2026
312 checks passed
@danegsta danegsta deleted the danegsta/fix-redis-persistent-lifetime branch June 2, 2026 21:05
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.5 milestone Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redis integration fails to start container when lifetime is set to persistant

3 participants