using Microsoft.AspNetCore.Http; namespace ClawdDotNet.Manager.Web; /// /// Welche Instanz eine Anfrage meint. /// /// Der Ordnername ist die Kennung. Er ist eindeutig — zwei Instanzen können /// nicht im selben Verzeichnis liegen —, er ist stabil, und er ist lesbar. Die /// Instanzkennung aus der Konfiguration wäre ebenfalls eindeutig, aber man müsste jede /// Instanzdatei lesen, um von ihr auf ein Verzeichnis zu kommen; der Manager hat den Pfad /// ohnehin in der Hand. /// /// Und wenn nichts dabeisteht? Läuft genau eine Instanz, ist sie gemeint — /// alles andere wäre Förmlichkeit gegenüber dem Normalfall. Laufen mehrere, wird /// nachgefragt statt geraten: Eine Anfrage an die falsche Instanz ist schlimmer als eine /// abgelehnte. /// internal static class InstanceRouting { /// Die Kopfzeile, mit der die Weboberfläche die Instanz benennt. public const string HeaderName = "X-Instanz"; public static string IdOf(ManagedInstance instance) => Path.GetFileName(instance.Directory); /// Die gemeinte Instanz, oder eine Begründung, warum keine bestimmbar ist. public static (ManagedInstance? Instance, string? Problem) Resolve( InstanceRegistry registry, HttpContext context) { var alle = registry.Instances; if (context.Request.Headers.TryGetValue(HeaderName, out var genannt) && !string.IsNullOrWhiteSpace(genannt)) { var id = genannt.ToString().Trim(); var treffer = alle.FirstOrDefault( i => string.Equals(IdOf(i), id, StringComparison.OrdinalIgnoreCase)); return treffer is null ? (null, $"Es gibt keine Instanz '{id}'.") : (treffer, null); } var laufend = alle.Where(i => i.Condition == InstanceCondition.Running).ToList(); return laufend.Count switch { 1 => (laufend[0], null), 0 => (null, "Es läuft keine Instanz."), _ => (null, $"Es laufen {laufend.Count} Instanzen. " + $"Welche gemeint ist, gehört in die Kopfzeile {HeaderName}.") }; } }