Verschwundene Dateien werden gemeldet, nicht stillschweigend gelöscht
Vorher räumte der Scan jede Datei weg, die er nicht mehr sah, und mit der letzten Datei fiel der Titel samt Sehfortschritt aller Benutzer. Für eine wirklich gelöschte Datei ist das richtig. Für eine Platte im Ruhezustand, ein noch nicht eingehängtes Volume oder einen umbenannten Ordner ist es Datenverlust — und für den Scan sehen alle vier Fälle gleich aus. Jetzt trägt MediaFile ein MissingSince. Der Eintrag bleibt stehen, steht in der Verwaltung unter "Nicht mehr gefunden", und gelöscht wird auf Ansage. Taucht die Datei wieder auf, verschwindet die Markierung von selbst. Dazu die Notbremse, und sie ist der eigentliche Grund für den ganzen Punkt: Fehlt der Wurzelpfad, oder liegt dort keine einzige Mediendatei mehr, obwohl vorher welche da waren, bricht der Lauf ab und sagt warum. Ohne sie erklärte ein nicht eingehängtes Volume beim Start des NAS den gesamten Bestand für verschwunden — bei 458 Titeln. Der Abschnitt in der Verwaltung erscheint nur, wenn es etwas zu melden gibt. Ein dauerhaft leerer wäre Rauschen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
01ff41fd71
commit
8b67a7ec88
@@ -107,8 +107,16 @@ public class ScanTests
|
||||
Assert.That((await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies"))!.Total, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
/// <summary>Eine verschwundene Datei wird gemeldet, nicht stillschweigend gelöscht.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Vorher fiel hier der Titel samt Sehfortschritt.</b> Das ist für eine
|
||||
/// wirklich gelöschte Datei richtig — und falsch für jeden anderen Grund,
|
||||
/// aus dem eine Datei kurz nicht da ist. Beides sieht für den Scan gleich
|
||||
/// aus, also entscheidet jetzt der Administrator.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Eine_geloeschte_Datei_verschwindet_aus_der_Mediathek()
|
||||
public async Task Eine_verschwundene_Datei_wird_gemeldet_statt_geloescht()
|
||||
{
|
||||
Datei("The Matrix (1999).mkv");
|
||||
Datei("Inception (2010).mkv");
|
||||
@@ -120,11 +128,86 @@ public class ScanTests
|
||||
File.Delete(Path.Combine(_bestand, "Inception (2010).mkv"));
|
||||
var danach = await Scannen(client, bibliothek);
|
||||
|
||||
Assert.That(danach.Removed, Is.EqualTo(1));
|
||||
Assert.That(danach.Missing, Is.EqualTo(1));
|
||||
Assert.That((await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies"))!.Total,
|
||||
Is.EqualTo(2), "Der Titel bleibt stehen, bis jemand ihn entfernt.");
|
||||
|
||||
var vermisst = await client.GetFromJsonAsync<List<VermissteDatei>>("/api/v1/libraries/missing");
|
||||
Assert.That(vermisst, Has.Count.EqualTo(1));
|
||||
Assert.That(vermisst![0].Title, Is.EqualTo("Inception"));
|
||||
|
||||
// Und erst auf Ansage ist er wirklich weg.
|
||||
(await client.DeleteAsync("/api/v1/libraries/missing")).EnsureSuccessStatusCode();
|
||||
var filme = await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies");
|
||||
Assert.That(filme!.Items.Select(m => m.Title), Is.EqualTo(new[] { "The Matrix" }));
|
||||
}
|
||||
|
||||
/// <summary>Kommt die Datei zurück, verschwindet die Markierung von selbst.</summary>
|
||||
[Test]
|
||||
public async Task Eine_zurueckgekehrte_Datei_gilt_wieder_als_da()
|
||||
{
|
||||
// Zwei Dateien, damit der Ordner nicht leer wird — sonst greift die
|
||||
// Notbremse aus dem Test darunter, und zwar zu Recht.
|
||||
Datei("Inception (2010).mkv");
|
||||
Datei("The Matrix (1999).mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var (client, bibliothek) = await MitBibliothek(server, "Movies");
|
||||
await Scannen(client, bibliothek);
|
||||
|
||||
var pfad = Path.Combine(_bestand, "Inception (2010).mkv");
|
||||
var inhalt = await File.ReadAllBytesAsync(pfad);
|
||||
File.Delete(pfad);
|
||||
await Scannen(client, bibliothek);
|
||||
Assert.That(await client.GetFromJsonAsync<List<VermissteDatei>>("/api/v1/libraries/missing"),
|
||||
Has.Count.EqualTo(1));
|
||||
|
||||
await File.WriteAllBytesAsync(pfad, inhalt);
|
||||
await Scannen(client, bibliothek);
|
||||
|
||||
Assert.That(await client.GetFromJsonAsync<List<VermissteDatei>>("/api/v1/libraries/missing"),
|
||||
Is.Empty);
|
||||
}
|
||||
|
||||
/// <summary>Die Notbremse: ein leerer Ordner bricht ab, statt alles zu verwerfen.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Der teuerste denkbare Fehler.</b> Ist das Volume beim Start des NAS
|
||||
/// noch nicht eingehängt, liegt der Ordner leer da — und ohne diese Prüfung
|
||||
/// gälte der gesamte Bestand als verschwunden.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public async Task Ein_ploetzlich_leerer_Ordner_bricht_den_Scan_ab()
|
||||
{
|
||||
Datei("The Matrix (1999).mkv");
|
||||
Datei("Inception (2010).mkv");
|
||||
|
||||
using var server = new FlaroServer();
|
||||
var (client, bibliothek) = await MitBibliothek(server, "Movies");
|
||||
await Scannen(client, bibliothek);
|
||||
|
||||
foreach (var d in Directory.EnumerateFiles(_bestand, "*", SearchOption.AllDirectories))
|
||||
File.Delete(d);
|
||||
|
||||
var angestossen = await client.PostAsync($"/api/v1/libraries/{bibliothek}/scan", null);
|
||||
Assert.That(angestossen.StatusCode, Is.EqualTo(HttpStatusCode.Accepted));
|
||||
|
||||
ScanStatus? stand = null;
|
||||
for (var versuch = 0; versuch < 600; versuch++)
|
||||
{
|
||||
stand = await client.GetFromJsonAsync<ScanStatus>($"/api/v1/libraries/{bibliothek}/scan");
|
||||
if (stand!.State is "failed" or "finished") break;
|
||||
await Task.Delay(50);
|
||||
}
|
||||
|
||||
Assert.That(stand!.State, Is.EqualTo("failed"));
|
||||
Assert.That(stand.Error, Does.Contain("abgebrochen"));
|
||||
Assert.That((await client.GetFromJsonAsync<Page<MovieResponse>>("/api/v1/movies"))!.Total,
|
||||
Is.EqualTo(2), "Es darf nichts verändert worden sein.");
|
||||
Assert.That(await client.GetFromJsonAsync<List<VermissteDatei>>("/api/v1/libraries/missing"),
|
||||
Is.Empty, "Auch nicht als vermisst markiert.");
|
||||
}
|
||||
|
||||
/// <summary>Das Aufräumen darf nicht wegräumen, was derselbe Lauf schrieb.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
|
||||
Reference in New Issue
Block a user