| File: src\Shared\TerminalHost\TerminalHostMetadata.cs | Web Access |
| Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json.Serialization; namespace Aspire.Shared.TerminalHost; /// <summary> /// Schema for the <c>{replicaId}.metadata.json</c> sidecar that the AppHost writes next /// to each replica's UDS sockets under <c>~/.aspire/trmnl/</c>. /// </summary> /// <remarks> /// <para> /// Written once by <c>TerminalResourceBuilderExtensions.MaterializeTerminalHostsAsync</c> when /// the AppHost materializes each <c>TerminalHostResource</c> /// (during <c>BeforeStartEvent</c>) and deleted on <c>ApplicationStopped</c> alongside the /// <c>.sock</c> files. The descriptor lets external tools enumerate live terminals by /// listing <c>~/.aspire/trmnl/*.metadata.json</c> without needing an active backchannel. /// </para> /// <para> /// All fields capture state known at AppHost startup; runtime-mutable state (current /// dimensions after a downstream resize, attached peer count) is intentionally NOT /// persisted here — that lives inside the terminal-host process and is reachable via the /// control UDS. The on-disk file is read-mostly. /// </para> /// </remarks> internal sealed class TerminalHostMetadata { /// <summary>The metadata schema version understood by this build.</summary> public const int CurrentSchemaVersion = 3; /// <summary> /// Bumped when fields are added or semantics change so older readers can refuse /// unknown schemas instead of silently misinterpreting them. /// </summary> [JsonPropertyName("schemaVersion")] public int SchemaVersion { get; init; } = CurrentSchemaVersion; /// <summary>The replica id (see <see cref="TerminalHostPaths.CreateReplicaId"/>).</summary> [JsonPropertyName("replicaId")] public required string ReplicaId { get; init; } /// <summary>Name of the parent Aspire resource this terminal host serves.</summary> [JsonPropertyName("resourceName")] public required string ResourceName { get; init; } /// <summary>Zero-based replica index within <see cref="ResourceName"/>.</summary> [JsonPropertyName("replicaIndex")] public required int ReplicaIndex { get; init; } /// <summary>Absolute path to the AppHost project that owns this terminal host.</summary> [JsonPropertyName("appHostPath")] public required string AppHostPath { get; init; } /// <summary> /// Process id of the AppHost process. Readers pair it with /// <see cref="AppHostProcessIdentity"/> before deciding ownership. /// </summary> [JsonPropertyName("appHostPid")] public required int AppHostPid { get; init; } /// <summary> /// Opaque same-boot identity of the AppHost process, paired with <see cref="AppHostPid"/> /// so a recycled PID cannot be mistaken for the original owner. Schema-v1 sidecars omit it. /// </summary> [JsonPropertyName("appHostProcessIdentity")] public long? AppHostProcessIdentity { get; init; } /// <summary> /// Process identity name used by schema-v2 sidecars from earlier preview builds. /// Retained so readers can recognize those unscoped sidecars and preserve them safely. /// </summary> [JsonPropertyName("appHostProcessStartTimeUnixMilliseconds")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public long? SchemaV2AppHostProcessIdentity { get; init; } /// <summary> /// Machine or PID-namespace scope in which <see cref="AppHostPid"/> is meaningful. /// Schema-v1 sidecars omit it. /// </summary> [JsonPropertyName("appHostProcessScopeId")] public string? AppHostProcessScopeId { get; init; } /// <summary> /// Linux kernel boot identifier for the owning AppHost. This disambiguates otherwise identical /// boot-relative process identities after a reboot. Other platforms omit it. /// </summary> [JsonPropertyName("appHostBootId")] public string? AppHostBootId { get; init; } /// <summary>UTC timestamp when the sidecar was written.</summary> [JsonPropertyName("createdAtUtc")] public required DateTime CreatedAtUtc { get; init; } /// <summary>Initial terminal width in columns (as configured by <c>WithTerminal(...)</c>).</summary> [JsonPropertyName("columns")] public required int Columns { get; init; } /// <summary>Initial terminal height in rows.</summary> [JsonPropertyName("rows")] public required int Rows { get; init; } /// <summary>Path of the control UDS. Convenience for tools so they don't have to recompute it.</summary> [JsonPropertyName("controlSocketPath")] public required string ControlSocketPath { get; init; } /// <summary>Path of the consumer (viewer-facing) UDS.</summary> [JsonPropertyName("consumerSocketPath")] public required string ConsumerSocketPath { get; init; } }