Stufe 4c (#764): Kommentare in C#, WebUI-Skripten, CSS und HTML auf Englisch
Rund 2.600 Kommentarblöcke in 310 C#-Dateien übersetzt, Begründungen vollständig erhalten: blockweise gleiche Anzahl wie vorher, kein Block unter 60 % seiner Länge, der Code außerhalb der Kommentare per Tokenizer byte-identisch geprüft. Zitate deutscher Oberflächentexte und Testdaten bleiben deutsch. WebUI: Kommentare in JS/CSS/HTML übersetzt, JSDoc-@param an die in 4b umbenannten Parameter angeglichen. Dabei behoben: - 4b hatte "tag" (HTML-Tag) als deutsches "Tag" gelesen und zu "dayValue" gemacht (makeElement, svg, Tagesübersicht) - zurück auf tag/day. - Aufgaben "InProgress" bekamen die Plakettenart "laufend", für die es nie eine CSS-Klasse gab - jetzt "success" wie laufende Instanzen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
da4ceac7d5
commit
837a634a22
@@ -7,16 +7,15 @@ using Shouldly;
|
||||
namespace ClawdDotNet.Manager.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// „Autostart durch Manager" — der Schalter, der eine Instanz am Laufen hält (#528).
|
||||
/// "Autostart by manager" — the switch that keeps an instance running (#528).
|
||||
///
|
||||
/// <para><b>Zwei Dinge in einem Schalter, weil es dieselbe Zusage ist:</b> Der Manager
|
||||
/// startet die Instanz beim Hochkommen, und er startet sie nach einem Absturz wieder. Ohne
|
||||
/// den Schalter rührt er nichts an — ein Manager, der nach einem Neustart der Maschine
|
||||
/// alles hochfährt, was er findet, startet auch das, was jemand mit Absicht angehalten
|
||||
/// hat.</para>
|
||||
/// <para><b>Two things in one switch, because it is the same promise:</b> the manager
|
||||
/// starts the instance when coming up, and it starts it again after a crash. Without
|
||||
/// the switch it touches nothing — a manager that boots everything it finds after a restart of the machine
|
||||
/// also starts what someone stopped on purpose.</para>
|
||||
///
|
||||
/// <para><b>Und der Sicherungsautomat ist der eigentliche Inhalt.</b> Wieder hochzufahren
|
||||
/// ist die einfache Hälfte; die schwierige ist zu erkennen, wann man es lassen muss.</para>
|
||||
/// <para><b>And the circuit breaker is the actual content.</b> Booting again
|
||||
/// is the easy half; the hard one is recognizing when to stop.</para>
|
||||
/// </summary>
|
||||
public sealed class AutostartTests : IAsyncDisposable
|
||||
{
|
||||
@@ -41,9 +40,9 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
Directory.CreateDirectory(_root);
|
||||
_verzeichnisse = new InstanceDirectoryManager(Path.Combine(_root, "Instances"));
|
||||
|
||||
// Der Socket antwortet nur, wenn wirklich ein Prozess laeuft - sonst hiesse eine
|
||||
// vorab hinterlegte Antwort "laeuft schon", und der Manager wuerde uebernehmen
|
||||
// statt zu starten.
|
||||
// The socket only answers if a process is really running - otherwise an
|
||||
// answer stored in advance would mean "already running", and the manager would take over
|
||||
// instead of starting.
|
||||
_kanal.Launcher = _launcher;
|
||||
}
|
||||
|
||||
@@ -51,7 +50,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
try { Directory.Delete(_root, recursive: true); }
|
||||
catch { /* Ein liegengebliebener Testordner faerbt keinen Lauf rot. */ }
|
||||
catch { /* A leftover test folder does not turn a run red. */ }
|
||||
}
|
||||
|
||||
private ManagerCore Manager(RestartPolicy? policy = null)
|
||||
@@ -64,7 +63,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
restartPolicy: policy);
|
||||
}
|
||||
|
||||
/// <summary>Legt eine Instanz an und setzt den Schalter in ihrer Instanzdatei.</summary>
|
||||
/// <summary>Creates an instance and sets the switch in its instance file.</summary>
|
||||
private string Instanz(string name, bool autostart)
|
||||
{
|
||||
var pfad = _verzeichnisse.CreateInstance(name);
|
||||
@@ -83,7 +82,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
InstanceEventKind.Crashed, Path.GetFullPath(pfad), name, 4711, 137,
|
||||
"unerwartet beendet", DateTimeOffset.UtcNow);
|
||||
|
||||
// ─── Beim Hochkommen ───
|
||||
// ─── When coming up ───
|
||||
|
||||
[Fact]
|
||||
public async Task Eine_Instanz_mit_Autostart_wird_beim_Hochfahren_gestartet()
|
||||
@@ -110,8 +109,8 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Was schon läuft, wird nicht noch einmal gestartet: Ein zweiter Prozess auf derselben
|
||||
/// <c>state.db</c> wäre das Gegenteil von hilfreich.
|
||||
/// What is already running is not started again: a second process on the same
|
||||
/// <c>state.db</c> would be the opposite of helpful.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Was_schon_laeuft_wird_nicht_noch_einmal_gestartet()
|
||||
@@ -143,7 +142,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
manager.Instances.Instances.Single(i => i.Name == "Ohne").AutostartByManager.ShouldBeFalse();
|
||||
}
|
||||
|
||||
// ─── Nach einem Absturz ───
|
||||
// ─── After a crash ───
|
||||
|
||||
[Fact]
|
||||
public async Task Nach_einem_Absturz_wird_wieder_gestartet()
|
||||
@@ -155,7 +154,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
|
||||
var vorher = _launcher.Starts;
|
||||
|
||||
// Der Prozess ist weg; die Aufsicht hat es gemeldet.
|
||||
// The process is gone; supervision has reported it.
|
||||
_launcher.Last!.Exit(137);
|
||||
await manager.RestartAfterCrashAsync(Absturz(pfad, "Alpha"));
|
||||
|
||||
@@ -178,14 +177,14 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eine verstummte Instanz wird beendet und neu gestartet — aber erst, nachdem der
|
||||
/// alte Prozess nachweislich weg ist.
|
||||
/// A silent instance is ended and restarted — but only after the
|
||||
/// old process is provably gone.
|
||||
///
|
||||
/// <para><b>Der Fall wird hier wirklich hergestellt und nicht behauptet.</b> Der
|
||||
/// Prozess lebt weiter, nur der Socket schweigt — genau die Lage aus #529. Ein Test,
|
||||
/// der stattdessen das Ereignis von Hand baut und die Neustartmethode aufruft, prüft
|
||||
/// die eine Hälfte, die ohnehin funktioniert, und lässt die gefährliche aus: dass vor
|
||||
/// dem Start niemand mehr auf der Datenbank sitzt.</para>
|
||||
/// <para><b>The case is really produced here and not claimed.</b> The
|
||||
/// process lives on, only the socket is silent — exactly the situation from #529. A test
|
||||
/// that instead builds the event by hand and calls the restart method checks
|
||||
/// the half that works anyway, and leaves out the dangerous one: that before
|
||||
/// the start nobody sits on the database any more.</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Eine_verstummte_Instanz_wird_erst_beendet_und_dann_neu_gestartet()
|
||||
@@ -198,24 +197,24 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
var alt = _launcher.Last.ShouldNotBeNull();
|
||||
_launcher.Starts.ShouldBe(1);
|
||||
|
||||
// Ab jetzt haengt sie: Der Prozess lebt, der Socket antwortet nicht mehr.
|
||||
// From now on it hangs: the process lives, the socket no longer answers.
|
||||
_kanal.Verstummen(pfad);
|
||||
|
||||
var aufsicht = manager.Instances.SupervisorFor(pfad).ShouldNotBeNull();
|
||||
|
||||
// Drei Durchgaenge bis zum Alarm - vorher wird nichts unternommen.
|
||||
// Three passes until the alarm - nothing is done before that.
|
||||
for (var i = 0; i < 3; i++) await aufsicht.CheckAsync();
|
||||
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Silent);
|
||||
alt.WasKilled.ShouldBeFalse("Vor Ablauf der Frist wird nicht abgeschossen.");
|
||||
|
||||
// Die Frist laeuft ab (SilentKillGrace: 300ms).
|
||||
// The deadline expires (SilentKillGrace: 300ms).
|
||||
await Task.Delay(400);
|
||||
await aufsicht.CheckAsync();
|
||||
|
||||
alt.WasKilled.ShouldBeTrue("Nach der Frist wird der haengende Prozess beendet.");
|
||||
|
||||
// Der Absturzweg startet neu - und der neue Prozess ist ein anderer.
|
||||
// The crash path restarts - and the new process is a different one.
|
||||
await Warte(() => _launcher.Starts >= 2);
|
||||
|
||||
_launcher.Last.ShouldNotBeNull().Id.ShouldNotBe(alt.Id);
|
||||
@@ -223,11 +222,11 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eine Instanz, die aufräumt, wird nicht abgeschossen — auch wenn es dauert.
|
||||
/// An instance that is cleaning up is not killed — even if it takes a while.
|
||||
///
|
||||
/// <para>Sie antwortet ja; sie tut genau das, worum gebeten wurde. Der Unterschied
|
||||
/// zwischen „hängt" und „räumt auf" ist der ganze Grund, warum der Puls mehr sagt als
|
||||
/// „jemand hat geantwortet".</para>
|
||||
/// <para>It does answer; it is doing exactly what it was asked to do. The difference
|
||||
/// between "hangs" and "cleans up" is the whole reason why the pulse says more than
|
||||
/// "someone answered".</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Wer_aufraeumt_gilt_nicht_als_verstummt()
|
||||
@@ -259,11 +258,11 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nach der Grenze setzt der Manager aus.
|
||||
/// After the limit the manager pauses.
|
||||
///
|
||||
/// <para>Was an einer kaputten Konfiguration scheitert, scheitert beim zehnten Versuch
|
||||
/// genauso — dann hat man statt einer toten Instanz eine tote Instanz, ein volles
|
||||
/// Protokoll und einen Bugtracker voller Wiederholungen.</para>
|
||||
/// <para>What fails because of a broken configuration fails the same way on the tenth attempt
|
||||
/// — then instead of a dead instance you have a dead instance, a full
|
||||
/// log and a bug tracker full of repetitions.</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Nach_drei_Neustarts_im_Zeitfenster_setzt_der_Manager_aus()
|
||||
@@ -285,8 +284,8 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wer von Hand startet, hat entweder etwas geändert oder weiß, was er tut. Ihm die
|
||||
/// Versuche von vorhin anzurechnen hieße, ihn für den Absturz zu bestrafen.
|
||||
/// Whoever starts by hand has either changed something or knows what they are doing. Charging them with
|
||||
/// the earlier attempts would mean punishing them for the crash.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Ein_Start_von_Hand_raeumt_den_Zaehler_ab()
|
||||
@@ -304,7 +303,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
|
||||
var erschoepft = _launcher.Starts;
|
||||
|
||||
// Ein neuer Manager faengt bei null an - genau wie ein Start von Hand.
|
||||
// A new manager starts at zero - just like a start by hand.
|
||||
await using var frisch = Manager(new RestartPolicy(3, TimeSpan.FromMinutes(10)));
|
||||
await frisch.StartAsync();
|
||||
|
||||
@@ -315,7 +314,7 @@ public sealed class AutostartTests : IAsyncDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Der Sicherungsautomat für sich genommen.</summary>
|
||||
/// <summary>The circuit breaker on its own.</summary>
|
||||
public sealed class RestartLedgerTests
|
||||
{
|
||||
private sealed class Uhr(DateTimeOffset jetzt) : TimeProvider
|
||||
@@ -349,8 +348,8 @@ public sealed class RestartLedgerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Das Zeitfenster wandert: Eine Instanz, die einmal im Monat abstürzt und wieder
|
||||
/// hochkommt, läuft nie in die Grenze — eine, die im Minutentakt fällt, sofort.
|
||||
/// The time window moves: an instance that crashes once a month and comes back
|
||||
/// up never runs into the limit — one that falls every minute does immediately.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Alte_Versuche_fallen_aus_dem_Fenster()
|
||||
@@ -383,12 +382,12 @@ public sealed class RestartLedgerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ein Start, der auf einen veralteten Merkzettel trifft.
|
||||
/// A start that meets an outdated note.
|
||||
///
|
||||
/// <para><b>Der Defekt, den erst die Autostart-Tests gezeigt haben.</b> Zwischen zwei
|
||||
/// Aufsichtsdurchgängen liegen Sekunden, und in denen kann eine Instanz wegbrechen. Wer in
|
||||
/// dieser Lücke „starten" verlangte, bekam „läuft schon" — einen Erfolg, hinter dem nichts
|
||||
/// stand. Der nächste Durchgang meldete dann einen Absturz, den niemand mehr erwartete.</para>
|
||||
/// <para><b>The defect that only the autostart tests revealed.</b> Between two
|
||||
/// supervision passes there are seconds, and in them an instance can break away. Whoever
|
||||
/// asked to "start" in this gap got "already running" — a success with nothing
|
||||
/// behind it. The next pass then reported a crash nobody expected any more.</para>
|
||||
/// </summary>
|
||||
public sealed class StaleStateTests : IAsyncDisposable
|
||||
{
|
||||
@@ -409,7 +408,7 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
try { Directory.Delete(_root, recursive: true); }
|
||||
catch { /* Ein liegengebliebener Testordner faerbt keinen Lauf rot. */ }
|
||||
catch { /* A leftover test folder does not turn a run red. */ }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -421,7 +420,7 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
await using var aufsicht = new InstanceSupervisor(
|
||||
dir, _launcher, _kanal, NullLogger.Instance,
|
||||
new SupervisionOptions(
|
||||
TimeSpan.FromSeconds(30), // absichtlich traege: kein Durchgang dazwischen
|
||||
TimeSpan.FromSeconds(30), // deliberately sluggish: no pass in between
|
||||
TimeSpan.FromMilliseconds(600),
|
||||
3,
|
||||
TimeSpan.FromMilliseconds(300),
|
||||
@@ -431,8 +430,8 @@ public sealed class StaleStateTests : IAsyncDisposable
|
||||
(await aufsicht.StartAsync()).ShouldBeTrue();
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running);
|
||||
|
||||
// Die Instanz bricht weg. Die Aufsicht hat es noch nicht bemerkt - der naechste
|
||||
// Durchgang kaeme erst in dreissig Sekunden.
|
||||
// The instance breaks away. Supervision has not noticed yet - the next
|
||||
// pass would only come in thirty seconds.
|
||||
_launcher.Last!.Exit(137);
|
||||
aufsicht.Condition.ShouldBe(InstanceCondition.Running, "Noch nichts bemerkt.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user