Skip to content

Show waiting dependency details in dashboard#17089

Merged
adamint merged 22 commits into
microsoft:mainfrom
adamint:dev/adamint/waiting-state-dependency-details
May 19, 2026
Merged

Show waiting dependency details in dashboard#17089
adamint merged 22 commits into
microsoft:mainfrom
adamint:dev/adamint/waiting-state-dependency-details

Conversation

@adamint
Copy link
Copy Markdown
Member

@adamint adamint commented May 14, 2026

Description

When a resource is waiting on dependencies, the dashboard currently shows a generic waiting state without naming the resources that are still blocking startup. This change publishes a resource.waitingFor snapshot property while dependency waits are active and uses it to show the waiting dependencies in the resource details state description.

User-facing usage

image image

When the dependency resource is visible in the dashboard, its name is rendered as an inline link to that resource. Replicated dependencies use resolved replica names, so each replica disappears from the waiting list as it satisfies the wait condition.

The same metadata is also included in cancellation diagnostics for waits, so timeout/cancellation messages show the state, health, and exit code of resources that were still blocking the wait.

Implementation details:

  • Adds KnownProperties.Resource.WaitingFor and helper support for setting/removing resource snapshot properties.
  • Publishes and updates resource.waitingFor while dependency waits are active, including per-replica updates for replicated dependencies.
  • Clears stale waiting metadata when a resource leaves the waiting state.
  • Adds dashboard rendering for linked dependency names in the resource details state description.
  • Regenerates dashboard localization files for the new neutral waiting string.

Fixes #16774

Validation:

  • ./restore.sh
  • MSBUILDTERMINALLOGGER=false ./dotnet.sh build src/Aspire.Dashboard/Aspire.Dashboard.csproj /t:UpdateXlf /p:SkipNativeBuild=true
  • MSBUILDTERMINALLOGGER=false ./dotnet.sh test --project tests/Aspire.Hosting.Tests/Aspire.Hosting.Tests.csproj --no-launch-profile -- --filter-method "*.WaitForDependenciesPublishesAndUpdatesWaitingForDependencies" --filter-method "*.WaitForDependenciesPublishesResolvedWaitingForDependenciesForReplicas" --filter-method "*.PublishUpdateClearsWaitingForDependenciesWhenResourceLeavesWaiting" --filter-method "*.CancellationMessageIncludesWaitingForDependencies" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • MSBUILDTERMINALLOGGER=false ./dotnet.sh test --project tests/Aspire.Dashboard.Tests/Aspire.Dashboard.Tests.csproj --no-launch-profile -- --filter-class "*.ResourceStateViewModelTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • MSBUILDTERMINALLOGGER=false ./dotnet.sh test --project tests/Aspire.Dashboard.Components.Tests/Aspire.Dashboard.Components.Tests.csproj --no-launch-profile -- --filter-method "*.Render_StateDescription_ShowsWaitingForDependenciesAsResourceDetailEntry" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • git --no-pager diff --check

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

Copilot AI review requested due to automatic review settings May 14, 2026 18:21
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

This PR improves the Aspire Dashboard’s “Waiting” experience by publishing a new resource.waitingFor snapshot property while dependency waits are active, then using it to show which dependency resources are still blocking startup (including replica-resolved names and links when available). It also incorporates the same metadata into wait cancellation/timeout diagnostics.

Changes:

  • Adds KnownProperties.Resource.WaitingFor plus shared snapshot helpers to set/remove resource snapshot properties.
  • Updates ResourceNotificationService.WaitForDependenciesAsync to publish/update/clear resource.waitingFor during waits and to include waiting dependency details in cancellation messages.
  • Updates dashboard rendering to display “Waiting for dependencies: …” (with inline resource links when possible) and regenerates localization resources; adds/updates tests accordingly.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/ResourceNotificationTests.cs Adds tests asserting resource.waitingFor is published/updated/cleared and included in cancellation diagnostics.
tests/Aspire.Dashboard.Tests/Model/ResourceStateViewModelTests.cs Adds coverage for waiting tooltip formatting when waiting dependencies are present.
tests/Aspire.Dashboard.Components.Tests/Controls/ResourceDetailsTests.cs Adds component test ensuring the resource details panel renders waiting dependency names and links.
src/Shared/Model/KnownProperties.cs Adds KnownProperties.Resource.WaitingFor constant (resource.waitingFor).
src/Shared/CustomResourceSnapshotExtensions.cs Adds RemoveResourceProperty helper for snapshot property cleanup.
src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs Publishes/updates/clears resource.waitingFor during dependency waits; clears stale waiting metadata when leaving Waiting; enriches cancellation messages with waiting dependency details.
src/Aspire.Dashboard/Resources/xlf/Columns.cs.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.de.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.es.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.fr.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.it.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.ja.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.ko.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.pl.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.pt-BR.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.ru.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.tr.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.zh-Hans.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/xlf/Columns.zh-Hant.xlf Adds new localization unit for “Waiting for dependencies: {0}.”
src/Aspire.Dashboard/Resources/Columns.resx Adds the new neutral waiting string resource and comment describing {0}.
src/Aspire.Dashboard/Resources/Columns.Designer.cs Regenerates designer accessor for StateColumnResourceWaitingFor.
src/Aspire.Dashboard/Model/ResourceViewModelExtensions.cs Adds TryGetWaitingForDependencies extension for reading waiting dependency list from resource properties.
src/Aspire.Dashboard/Model/ResourceStateViewModel.cs Updates waiting tooltip to include dependency list when resource.waitingFor is present.
src/Aspire.Dashboard/Components/Controls/ResourceDetails.razor.cs Routes state-description rendering through a custom value component that can link waiting dependencies.
src/Aspire.Dashboard/Components/Controls/PropertyValues/ResourceStateDescriptionValue.razor.cs New component: splits localized waiting format into prefix/suffix and builds linked/non-linked dependency entries.
src/Aspire.Dashboard/Components/Controls/PropertyValues/ResourceStateDescriptionValue.razor New component markup: renders prefix + comma-separated dependency links/text + suffix with highlighting.
Files not reviewed (1)
  • src/Aspire.Dashboard/Resources/Columns.Designer.cs: Language not supported

Comment thread tests/Aspire.Dashboard.Components.Tests/Controls/ResourceDetailsTests.cs Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 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 -- 17089

Or

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

@adamint adamint marked this pull request as draft May 14, 2026 19:04
Comment thread src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs
@adamint
Copy link
Copy Markdown
Member Author

adamint commented May 14, 2026

PR testing update: ran the pr-testing workflow in the repo-local container runner for PR #17089.

Result: passed for the targeted container smoke scenario. I did not find a PR behavior issue in the waiting dependency flow.

Verification:

  • Installed the PR CLI using the dogfood command from the PR comment unchanged.
  • Installed CLI reported version 13.4.0-pr.17089.g39547d09, matching PR head 39547d092aea79e4131b3a5b23af233af5ecf984.
  • Created a fresh aspire-empty C# app from the PR hive.
  • Added a temp explicit-start container manualgate and a dependent container using WaitForStart(manualgate).
  • Ran the AppHost inside a persistent container runner session.
  • Before starting manualgate, aspire describe --format Json showed the dependent resource in Waiting with properties.resource.waitingFor set to the resolved manualgate-* resource name, and the expected WaitFor relationship.
  • After aspire resource <manualgate> start, aspire describe --format Json showed both resources Running, and resource.waitingFor was no longer present on the dependent resource.
  • Stopped the AppHost with aspire stop and cleaned up the leftover tunnel proxy container.

Setup notes from the container run:

  • The repo-local runner image did not include .NET SDK 10.0.100, so the first AppHost start failed with C# AppHost requires .NET SDK version 10.0.100 or later. Detected: (not found).. I installed the SDK into the temporary mounted workspace and reran.
  • The generated script AppHost needed a temp-only NuGet.config pointing at /workspace/.aspire/hives/pr-17089/packages; otherwise dotnet build searched only nuget.org for Aspire.AppHost.Sdk/13.4.0-pr.17089.g39547d09.

Those setup notes did not appear to be regressions in this PR's waiting dependency changes.

@adamint adamint marked this pull request as ready for review May 14, 2026 20:45
@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

Comment thread playground/TestShop/BasketService/appsettings.json Outdated
@davidfowl
Copy link
Copy Markdown
Contributor

PR testing results

✅ Verified PR #17089 with the dogfood CLI.

  • Installed CLI: 13.4.0-pr.17089.g39547d09
  • PR head: 39547d092aea79e4131b3a5b23af233af5ecf984
  • Version check: matched the PR head short SHA

Scenarios exercised:

  1. Created a fresh Aspire app from the PR hive and added a target executable waiting on two custom dependencies.
  2. Confirmed the target entered Waiting with resource.waitingFor: "blocked-a, blocked-b".
  3. Ran an adversarial hanging-wait case and confirmed aspire wait timed out while the dependency stayed blocked.
  4. Partially unblocked one dependency and confirmed the waiting metadata updated to resource.waitingFor: "blocked-b" instead of staying stale.
  5. Opened the dashboard resource details page and confirmed it rendered: Waiting for dependencies: blocked-b.

Targeted regression tests passed:

Aspire.Hosting.Tests: 7/7 passed
Aspire.Dashboard.Tests ResourceStateViewModelTests: 16/16 passed
Aspire.Dashboard.Components.Tests ResourceDetails waiting dependency test: 1/1 passed

Overall result: ✅ verified.

Copy link
Copy Markdown
Contributor

@davidfowl davidfowl left a comment

Choose a reason for hiding this comment

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

Undo the HTTP2 change in basket service and remove the Start anyway from the details tab.

@adamint
Copy link
Copy Markdown
Member Author

adamint commented May 15, 2026

Addressed in a1238ec: removed the BasketService HTTP/2 override and hid the Start command from the resource details menu while keeping it available in the resources list/context menu.

@adamint adamint enabled auto-merge (squash) May 15, 2026 21:50
}
},
"AllowedHosts": "*",
"Kestrel": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

????

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The removed Kestrel HTTP/2-only default was blocking the new HTTP health check on BasketService. This playground change needs WithHttpHealthCheck("/health", endpointName: "http") so the dashboard can show healthy/starting dependency details for the waiting-state demo.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, but this breaks the basket service. It needs HTTP/2

Image

@JamesNK JamesNK disabled auto-merge May 15, 2026 23:16
Comment thread src/Aspire.Dashboard/Model/ResourceMenuBuilder.cs
Comment thread playground/TestShop/TestShop.AppHost/AppHost.cs
@JamesNK
Copy link
Copy Markdown
Member

JamesNK commented May 15, 2026

The resource names should be resolved so they don't include the suffix if it isn't a replica:

image

i.e. messaging-abcxyz should be messaging

@JamesNK
Copy link
Copy Markdown
Member

JamesNK commented May 15, 2026

This content shouldn't just show up in the dashboard UI. It is useful for AI. Always keep this in mind that dashboard content that is useful for people is also useful for AI.

Do state details show up in JSON returned from aspire describe? They should. Maybe that would be a different issue/PR.

Also, when you choose export JSON for a resource in the dashboard these values should be in the JSON (resource names probably don't need to be resolved in AI/JSON content).

For some reason waitingFor is null here:

image

@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

@adamint
Copy link
Copy Markdown
Member Author

adamint commented May 18, 2026

@JamesNK addressed the remaining waiting dependency feedback in 9c20407.

  • Dashboard waiting text now resolves suffixed resource names to the display name when the dependency is not part of a replica set, while keeping unique suffixed names for replicas.
  • Resource JSON now has an explicit waitingFor field populated from dashboard export/AI context and from aspire describe/CLI resource snapshots.
  • Added dashboard/resource-details/export and CLI mapper coverage for these cases.

@adamint adamint enabled auto-merge (squash) May 18, 2026 20:04
adamint and others added 2 commits May 18, 2026 16:04
…g-state-dependency-details

# Conflicts:
#	tests/Aspire.Cli.Tests/Backchannel/ResourceSnapshotMapperTests.cs
@adamint adamint merged commit 99f07e3 into microsoft:main May 19, 2026
298 checks passed
@microsoft-github-policy-service microsoft-github-policy-service Bot added this to the 13.4 milestone May 19, 2026
private void AddCommandMenuItems(List<MenuButtonItem> menuItems, ResourceViewModel resource, EventCallback<CommandViewModel> commandSelected, Func<ResourceViewModel, CommandViewModel, bool> isCommandExecuting, bool showStartCommand)
{
var menuCommands = resource.Commands
.Where(c => showStartCommand || !c.Name.Equals(CommandViewModel.StartCommand, StringComparisons.CommandName))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this still here? The start command is not added to the menu:

Image

? resource.Properties.OrderBy(p => p.Key).ToDistinctDictionary(
p => p.Key,
p => p.Value.Value.TryConvertToString(out var value) ? value : null)
p => ConvertPropertyValueToJsonNode(p.Value.Value))
Copy link
Copy Markdown
Member

@JamesNK JamesNK May 19, 2026

Choose a reason for hiding this comment

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

If I export backsetcache.json I get many nulls. See resource.appArgsSensitivit and container.ports:

{
  "name": "basketcache-fudydpcx",
  "displayName": "basketcache",
  "resourceType": "Container",
  "uid": "basketcache-fudydpcx",
  "state": "RuntimeUnhealthy",
  "creationTimestamp": "2026-05-19T04:58:38+00:00",
  "source": "docker.io/library/redis:8.6",
  "urls": [
    {
      "name": "secondary",
      "url": "tcp://localhost:58333/"
    },
    {
      "name": "tcp",
      "url": "rediss://localhost:58335/"
    }
  ],
  "volumes": [
    {
      "source": "testshop.apphost-8e2ec1c54c-basketcache-data",
      "target": "/data",
      "mountType": "volume"
    }
  ],
  "properties": {
    "container.args": [],
    "container.command": "/bin/sh",
    "container.id": null,
    "container.image": "docker.io/library/redis:8.6",
    "container.lifetime": "Session",
    "container.ports": [
      null,
      null
    ],
    "resource.appArgs": [
      "redis-server",
      "--requirepass",
      "$REDIS_PASSWORD",
      "--save",
      "60",
      "1",
      "--tls-port",
      "6379",
      "--port",
      "6380",
      "--tls-ca-cert-file",
      "/usr/lib/ssl/aspire/cert.pem",
      "--tls-cert-file",
      "/usr/lib/ssl/aspire/private/C2D9E727877F50178B850CE95801C230203C8C2D.crt",
      "--tls-key-file",
      "/usr/lib/ssl/aspire/private/C2D9E727877F50178B850CE95801C230203C8C2D.key",
      "--tls-auth-clients",
      "no"
    ],
    "resource.appArgsSensitivity": [
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null
    ],
    "resource.connectionString": "localhost:58335,password=-hAd+t1xBM{mNm}RF0j!Q~,ssl=true",
    "resource.createTime": "2026-05-19T04:58:38.0000000Z",
    "resource.displayName": "basketcache",
    "resource.exitCode": null,
    "resource.healthState": null,
    "resource.name": "basketcache-fudydpcx",
    "resource.startTime": null,
    "resource.state": "RuntimeUnhealthy",
    "resource.stopTime": null,
    "resource.type": "Container",
    "resource.uid": "basketcache-fudydpcx"
  },
  "environment": {
    "REDIS_PASSWORD": "-hAd+t1xBM{mNm}RF0j!Q~",
    "SSL_CERT_DIR": "/usr/lib/ssl/aspire/certs:/etc/ssl/certs:/usr/local/share/ca-certificates:/etc/pki/tls/certs"
  },
  "healthReports": {
    "basketcache_check": {
      "description": "",
      "exceptionMessage": ""
    }
  },
  "commands": {}
}

Compare with before:

{
  "name": "basketcache-fturxbyq",
  "displayName": "basketcache",
  "resourceType": "Container",
  "uid": "basketcache-fturxbyq",
  "state": "RuntimeUnhealthy",
  "creationTimestamp": "2026-05-19T05:17:54+00:00",
  "source": "docker.io/library/redis:8.6",
  "urls": [
    {
      "name": "secondary",
      "url": "tcp://localhost:51760/"
    },
    {
      "name": "tcp",
      "url": "rediss://localhost:51756/"
    }
  ],
  "volumes": [
    {
      "source": "testshop.apphost-8e2ec1c54c-basketcache-data",
      "target": "/data",
      "mountType": "volume"
    }
  ],
  "properties": {
    "container.args": null,
    "container.command": "/bin/sh",
    "container.id": null,
    "container.image": "docker.io/library/redis:8.6",
    "container.lifetime": "Session",
    "container.ports": null,
    "resource.appArgs": null,
    "resource.appArgsSensitivity": null,
    "resource.connectionString": "localhost:51756,password=-hAd+t1xBM{mNm}RF0j!Q~,ssl=true",
    "resource.createTime": "2026-05-19T05:17:54.0000000Z",
    "resource.displayName": "basketcache",
    "resource.exitCode": null,
    "resource.healthState": null,
    "resource.name": "basketcache-fturxbyq",
    "resource.startTime": null,
    "resource.state": "RuntimeUnhealthy",
    "resource.stopTime": null,
    "resource.type": "Container",
    "resource.uid": "basketcache-fturxbyq"
  },
  "environment": {
    "REDIS_PASSWORD": "-hAd+t1xBM{mNm}RF0j!Q~",
    "SSL_CERT_DIR": "/usr/lib/ssl/aspire/certs:/etc/ssl/certs:/usr/local/share/ca-certificates:/etc/pki/tls/certs"
  },
  "healthReports": {
    "basketcache_check": {
      "description": "",
      "exceptionMessage": ""
    }
  },
  "commands": {}
}

Not correctly converting JSON properties was here earlier, I can see container.ports is null when it should have value [ 6380, 6379 ] but it's now much worse.

<value>Resource is waiting for dependencies.</value>
</data>
<data name="StateColumnResourceWaitingFor" xml:space="preserve">
<value>Waiting for dependencies: {0}.</value>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Don't put fullstop in messages than end with :

/// This allows for extensibility without changing the schema.
/// </summary>
public Dictionary<string, string?> Properties { get; init; } = [];
public Dictionary<string, JsonNode?> Properties { get; init; } = [];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens to old aspire CLI versions? I'm guessing they'll error.

Copy link
Copy Markdown
Member

@JamesNK JamesNK left a comment

Choose a reason for hiding this comment

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

Post-merge review: 4 issues found — 1 data loss bug (NumberValue/BoolValue not handled in JSON export), 1 breaking wire format change (Properties dict type), 1 formatting issue (trailing period), 1 performance concern (repeated ToArray allocation in tooltip path).

<value>Resource is waiting for dependencies.</value>
</data>
<data name="StateColumnResourceWaitingFor" xml:space="preserve">
<value>Waiting for dependencies: {0}.</value>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: The period after {0} reads awkwardly because the interpolated value is a list following a colon (e.g., "Waiting for dependencies: nginx, redis."). Consider removing the trailing period: "Waiting for dependencies: {0}".

return array;
}

return null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Bug: ConvertPropertyValueToJsonNode doesn't handle NumberValue or BoolValue. The TryConvertToString extension only returns true for Value.KindOneofCase.StringValue. Properties with numeric values (e.g., container.ports holding port numbers like 6379) or boolean values fall through to return null, silently losing data in the exported JSON.

Fix:

private static JsonNode? ConvertPropertyValueToJsonNode(Google.Protobuf.WellKnownTypes.Value value)
{
    if (value.TryConvertToString(out var stringValue))
    {
        return JsonValue.Create(stringValue);
    }

    if (value.HasNumberValue)
    {
        return JsonValue.Create(value.NumberValue);
    }

    if (value.HasBoolValue)
    {
        return JsonValue.Create(value.BoolValue);
    }

    if (value.ListValue is not null)
    {
        var array = new JsonArray();
        foreach (var element in value.ListValue.Values)
        {
            array.Add(ConvertPropertyValueToJsonNode(element));
        }

        return array;
    }

    return null;
}

/// This allows for extensibility without changing the schema.
/// </summary>
public Dictionary<string, string?> Properties { get; init; } = [];
public Dictionary<string, JsonNode?> Properties { get; init; } = [];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Breaking wire format change: Properties changed from Dictionary<string, string?> to Dictionary<string, JsonNode?>. Older Aspire CLI versions that deserialize this field as Dictionary<string, string?> will fail when they receive array-valued or object-valued properties. Is there versioning or capability negotiation to handle this, or will older CLI versions need to be updated?

dependencies = default;
return false;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Performance: TryGetResolvedWaitingForDependencies calls allResources.ToArray() on every invocation. In Resources.razor, this is passed via _resourceByName.Values in the column's TooltipText callback, meaning it allocates a new array on every tooltip hover for every resource row. Consider accepting IReadOnlyCollection<ResourceViewModel> or caching the materialized collection to avoid repeated allocations during rendering.

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.

aspire wait <resource> --project x.csproj reports 'no running apphosts found'

5 participants