Add project files.

This commit is contained in:
EugeneTes
2026-01-13 09:06:47 +01:00
parent dd935fe1fa
commit 7390693f50
187 changed files with 83457 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
using System.Threading.Tasks;
public interface IPrintService
{
Task<bool> PrintAsync(string printerIp, PrintJob job);
}

View File

@@ -0,0 +1,14 @@
public class PrintJob
{
public string AreaId { get; set; }
public string Document { get; set; }
public DateTime QueuedAt { get; set; }
public int RetryCount { get; set; }
public PrintJob()
{
AreaId = Guid.NewGuid().ToString();
QueuedAt = DateTime.UtcNow;
RetryCount = 0;
}
}

View File

@@ -0,0 +1,66 @@
using Microsoft.Extensions.Logging;
public class PrintServer
{
private readonly IPrintService _printService;
private readonly ILogger _logger;
private readonly Dictionary<string, PrinterQueue> _printerQueues;
public PrintServer(IPrintService printService, ILogger logger)
{
_printService = printService;
_logger = logger;
_printerQueues = new Dictionary<string, PrinterQueue>();
}
public void RegisterPrinter(string printerIp)
{
if (_printerQueues.ContainsKey(printerIp))
return;
var queue = new PrinterQueue(printerIp, _printService,_logger);
_printerQueues[printerIp] = queue;
queue.Start();
Console.WriteLine($"Printer {printerIp} registered");
}
public void UnregisterPrinter(string printerIp)
{
if (_printerQueues.TryGetValue(printerIp, out var queue))
{
queue.StopAsync().Wait();
_printerQueues.Remove(printerIp);
Console.WriteLine($"Printer {printerIp} unregistered");
}
}
public void SubmitJob(string printerIp, PrintJob job)
{
if (_printerQueues.TryGetValue(printerIp, out var queue))
{
queue.Enqueue(job);
}
else
{
_logger.LogWarning( $"Printer {printerIp} not found. Job cannot be submitted.");
}
}
public Dictionary<string, int> GetQueueStatus()
{
var status = new Dictionary<string, int>();
foreach (var kvp in _printerQueues)
{
status[kvp.Key] = kvp.Value.QueueLength;
}
return status;
}
public async Task ShutdownAsync()
{
var stopTasks = _printerQueues.Values.Select(q => q.StopAsync());
await Task.WhenAll(stopTasks);
Console.WriteLine("Print server shut down");
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
public class PrinterQueue
{
public string PrinterIp { get; }
private readonly ConcurrentQueue<PrintJob> _queue;
private readonly ConcurrentStack<PrintJob> _priorityQueue; // For failed jobs
private readonly SemaphoreSlim _signal;
private readonly CancellationTokenSource _cancellationTokenSource;
private Task _processingTask;
private readonly IPrintService _printService;
private readonly ILogger _logger;
public bool IsProcessing { get; private set; }
public int QueueLength => _queue.Count + _priorityQueue.Count;
public PrinterQueue(string printerIp, IPrintService printService, ILogger logger)
{
PrinterIp = printerIp;
_queue = new ConcurrentQueue<PrintJob>();
_priorityQueue = new ConcurrentStack<PrintJob>();
_signal = new SemaphoreSlim(0);
_cancellationTokenSource = new CancellationTokenSource();
_printService = printService;
_logger = logger;
}
public void Enqueue(PrintJob job)
{
_queue.Enqueue(job);
_signal.Release(); // Signal that there's work to do
_logger.LogInformation("Job {JobId} queued for printer {PrinterId}. Queue length: {QueueLength}", job.AreaId, PrinterIp, QueueLength);
}
public void Start()
{
if (_processingTask != null)
return;
IsProcessing = true;
_processingTask = Task.Run(() => ProcessQueueAsync(_cancellationTokenSource.Token));
_logger.LogInformation("Printer queue {PrinterId} started", PrinterIp);
}
private void EnqueuePriority(PrintJob job)
{
_priorityQueue.Push(job);
_signal.Release();
_logger.LogInformation("Job {JobId} priority queued for printer {PrinterId}. Queue length: {QueueLength}", job.AreaId, PrinterIp, QueueLength);
}
private async Task ProcessQueueAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
// Wait for signal that there's work or cancellation
await _signal.WaitAsync(cancellationToken);
PrintJob job = null;
if (!_priorityQueue.TryPop(out job))
{
_queue.TryDequeue(out job);
}
if (job!=null)
{
_logger.LogInformation("Processing job {JobId} on printer {PrinterId}", job.AreaId, PrinterIp);
try
{
// Call the actual print function
bool success = await _printService.PrintAsync(PrinterIp, job);
if (!success)
{
// Re-queue with retry logic
job.RetryCount++;
_logger.LogWarning("Job {JobId} failed, retrying ({RetryCount}/3)", job.AreaId, job.RetryCount);
await Task.Delay(5000, cancellationToken); // Wait before retry
EnqueuePriority(job);
}
else
{
_logger.LogInformation("Job {JobId} completed successfully on printer {PrinterId}", job.AreaId, PrinterIp);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing job {JobId}", job.AreaId);
// Handle exception (retry, log, etc.)
}
}
}
catch (OperationCanceledException)
{
break;
}
}
IsProcessing = false;
_logger.LogInformation("Printer queue {PrinterId} stopped", PrinterIp);
}
public async Task StopAsync()
{
_cancellationTokenSource.Cancel();
_signal.Release(); // Release to unblock the wait
if (_processingTask != null)
{
await _processingTask;
}
}
public List<PrintJob> GetPendingJobs()
{
return new List<PrintJob>(_queue);
}
}