Drain backend print queue per poll

This commit is contained in:
2026-05-26 09:04:22 +02:00
parent f5f47d404e
commit 91876040f9
3 changed files with 39 additions and 25 deletions
+1 -1
View File
@@ -220,7 +220,7 @@ Der Agent verbindet sich einmalig. Sobald ein neuer Druckauftrag erstellt wird,
data: {"type":"label-job-available"}
```
Der Agent ruft daraufhin sofort `GET /jobs/next` auf. Polling bleibt als Fallback sinnvoll, z. B. alle 30 Sekunden, falls die SSE-Verbindung unterbrochen wurde.
Der Agent ruft daraufhin sofort `GET /jobs/next` auf. Ein Poll-Lauf ruft `/jobs/next` wiederholt auf, bis das Backend `204 No Content` zurückgibt. Polling bleibt als Fallback sinnvoll, z. B. alle 30 Sekunden, falls die SSE-Verbindung unterbrochen wurde.
Es werden keine `agentId`-Parameter ausgewertet; alle verbundenen Agents erhalten das Event.
+3 -3
View File
@@ -9,13 +9,13 @@ Der Agent speichert keine Layouts, keine Nummernserver-Regeln und keine MySQL-Qu
```text
LabelPrintAgent
-> fragt alle X Sekunden PaperlessManager-Backend
-> erhält einen druckfertigen Etikettenjob
-> erhält druckfertige Etikettenjobs, bis kein Job mehr vorhanden ist
-> lädt/liest das Etikettbild
-> druckt über Windows-Drucker
-> meldet Erfolg oder Fehler ans Backend zurück
```
Der Agent unterstützt Server-Sent Events für Push-Benachrichtigungen und nutzt Polling als Fallback.
Der Agent unterstützt Server-Sent Events für Push-Benachrichtigungen und nutzt Polling als Fallback. Jeder Poll-Lauf ruft so lange `/jobs/next` auf, bis das Backend `204 No Content` zurückgibt.
## Backend-Vertrag
@@ -141,7 +141,7 @@ Wichtig:
3. Im Tab `Backend` BaseUrl, AgentId und optional API-Token eintragen.
4. Im Tab `Drucker` den Dymo LabelWriter auswählen.
5. Im Tab `Allgemein` Polling aktivieren und Intervall setzen.
6. Mit `Jetzt prüfen` kann sofort ein einzelner Backend-Poll ausgelöst werden.
6. Mit `Jetzt prüfen` kann sofort ein Poll-Lauf ausgelöst werden; dabei werden alle aktuell verfügbaren Jobs verarbeitet.
## Tray-Status
@@ -62,32 +62,21 @@ public sealed class BackendPollingWorker : IDisposable
return;
}
var job = await _backendClient.GetNextJobAsync(cancellationToken);
if (job is null)
var processedJobs = 0;
while (!cancellationToken.IsCancellationRequested)
{
SetStatus(true, "Backend verbunden. Kein Druckjob vorhanden.");
return;
}
try
{
using var bitmap = await _backendClient.GetLabelImageAsync(job, cancellationToken);
var result = await _printerService.PrintAsync(bitmap, printerName, job.LabelWidthMm, job.LabelHeightMm, cancellationToken);
if (result.Success)
var job = await _backendClient.GetNextJobAsync(cancellationToken);
if (job is null)
{
await _backendClient.ReportPrintedAsync(job.JobId, printerName, cancellationToken);
SetStatus(true, $"Job {job.JobId} erfolgreich gedruckt.");
var message = processedJobs == 0
? "Backend verbunden. Kein Druckjob vorhanden."
: $"Backend verbunden. {processedJobs} Druckjob(s) verarbeitet. Keine weiteren Druckjobs vorhanden.";
SetStatus(true, message);
return;
}
await _backendClient.ReportErrorAsync(job.JobId, printerName, result.ErrorMessage ?? "Druck fehlgeschlagen.", cancellationToken);
SetStatus(false, $"Job {job.JobId} konnte nicht gedruckt werden.");
}
catch (Exception ex)
{
Log.Error(ex, "Could not process backend label job {JobId}", job.JobId);
await _backendClient.ReportErrorAsync(job.JobId, printerName, ex.Message, cancellationToken);
SetStatus(false, $"Job {job.JobId} fehlgeschlagen: {ex.Message}");
processedJobs++;
await ProcessJobAsync(job, printerName, cancellationToken);
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
@@ -101,6 +90,31 @@ public sealed class BackendPollingWorker : IDisposable
}
}
private async Task ProcessJobAsync(BackendLabelJob job, string printerName, CancellationToken cancellationToken)
{
try
{
SetStatus(true, $"Job {job.JobId} wird gedruckt.");
using var bitmap = await _backendClient.GetLabelImageAsync(job, cancellationToken);
var result = await _printerService.PrintAsync(bitmap, printerName, job.LabelWidthMm, job.LabelHeightMm, cancellationToken);
if (result.Success)
{
await _backendClient.ReportPrintedAsync(job.JobId, printerName, cancellationToken);
SetStatus(true, $"Job {job.JobId} erfolgreich gedruckt.");
return;
}
await _backendClient.ReportErrorAsync(job.JobId, printerName, result.ErrorMessage ?? "Druck fehlgeschlagen.", cancellationToken);
SetStatus(false, $"Job {job.JobId} konnte nicht gedruckt werden.");
}
catch (Exception ex)
{
Log.Error(ex, "Could not process backend label job {JobId}", job.JobId);
await _backendClient.ReportErrorAsync(job.JobId, printerName, ex.Message, cancellationToken);
SetStatus(false, $"Job {job.JobId} fehlgeschlagen: {ex.Message}");
}
}
private async Task RunAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)