Redis yok. RabbitMQ yok.
Sadece System.Threading.Channels.
DSO.Core.QueueWorker; API'lerinizin uzun süren işlemleri arka plana devredip anında 202 Accepted dönmesini sağlayan, harici bağımlılık gerektirmeyen, in-memory bir iş kuyruğu ve sonuç takip kütüphanesidir.
Prod'a hazır, kurulumu beş dakika.
Sıfır dış bağımlılıkla, tek bir NuGet paketi bile eklemeden; sadece .NET'in kendi araçlarıyla çalışır.
Yüksek Performanslı Channel Kuyruğu
Lock-free ve yüksek performanslı System.Threading.Channels altyapısı üzerine kurulu.
Paralellik Sınırı
SemaphoreSlim ile kaynak kullanımını kısıtlayın; aynı anda en fazla 4 veya 10 iş çalışsın.
Akıllı Kapasite Yönetimi
MaxStoreCapacity aşıldığında, hedef kapasiteye ulaşana kadar en eski tamamlanmış işleri otomatik temizler.
Zamana Dayalı Otomatik Temizlik
Tamamlandıktan sonra RetentionTime süresi geçen işler periyodik olarak bellekten kaldırılır.
Dinamik Runtime Konfigürasyon
TTL, kapasite sınırı gibi tüm özellikleri uygulamayı yeniden başlatmadan API üzerinden değiştirin.
Thread-Safe Sonuç Deposu
ConcurrentDictionary ile Pending, Processing, Completed, Failed durumlarını anlık takip edin.
Dört bileşen, tek yön akış.
İstek kuyruğa girer, worker sırayla işler, sonuç deposu her adımı raporlar.
Program.cs'e üç kayıt, kuyruk hazır.
Servisleri DI konteynerine ekleyin, ardından controller'larınızdan işi kuyruğa alıp durumunu sorgulayın.
using BackgroundQueue;
var builder = WebApplication.CreateBuilder(args);
// 1. Ayarları Yapılandırın
var queueOptions = new QueueWorkerOptions
{
MaxConcurrency = 4, // Aynı anda çalışacak maksimum paralel iş sayısı
EnableCapacityEviction = true, // Kapasite aşımında tamamlananları silme
MaxStoreCapacity = 50, // Depoda tutulacak maksimum iş sayısı
EnableTtlCleanup = true, // Zamana dayalı otomatik temizlik
RetentionTime = TimeSpan.FromMinutes(10), // İş tamamlandıktan sonra saklanacağı süre
CleanupInterval = TimeSpan.FromSeconds(30) // TTL kontrol sıklığı
};
// 2. Servisleri DI Konteynerine Ekleyin
builder.Services.AddSingleton(queueOptions);
builder.Services.AddSingleton<JobResultStore>();
builder.Services.AddSingleton<IBackgroundJobQueue, BackgroundJobQueue>();
// 3. Arka Plan Hosted Servisleri Başlatın
builder.Services.AddHostedService<QueueWorkerService>(); // İşleri tüketen Worker
builder.Services.AddHostedService<JobCleanupService>(); // TTL Temizlik yapan Zamanlayıcı
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthorization();
app.MapControllers();
app.Run();
[ApiController]
[Route("api/jobs")]
public class JobsController : ControllerBase
{
private readonly IBackgroundJobQueue _queue;
private readonly JobResultStore _resultStore;
public JobsController(IBackgroundJobQueue queue, JobResultStore resultStore)
{
_queue = queue;
_resultStore = resultStore;
}
// İş Ekleme
[HttpPost("process-data")]
public IActionResult CreateJob([FromQuery] int seconds = 5)
{
Guid jobId = _queue.Enqueue(async (cancellationToken) =>
{
// Uzun süren asenkron operasyonunuz
await Task.Delay(TimeSpan.FromSeconds(seconds), cancellationToken);
return new
{
ProcessedItems = 1500,
Status = "Success",
CompletedAt = DateTime.UtcNow
};
});
return Accepted(new { JobId = jobId, Message = "İşleme alındı." });
}
// İş Durumu Sorgulama
[HttpGet("{jobId:guid}")]
public IActionResult GetStatus(Guid jobId)
{
var status = _resultStore.Get(jobId);
if (status == null)
return NotFound("İş kaydı bulunamadı veya süresi dolduğu için silindi.");
return Ok(status);
}
// Tüm İşleri Listeleme
[HttpGet("all")]
public IActionResult GetAll() => Ok(_resultStore.GetAll());
}
[ApiController]
[Route("api/jobs/config")]
public class JobConfigController : ControllerBase
{
private readonly QueueWorkerOptions _options;
public JobConfigController(QueueWorkerOptions options) => _options = options;
// Mevcut Ayarları Getir
[HttpGet]
public IActionResult GetConfig() => Ok(_options);
// TTL Özelliğini Aç/Kapat veya Süreyi Değiştir
[HttpPost("ttl")]
public IActionResult ToggleTtl([FromQuery] bool enable, [FromQuery] int? retentionSeconds = null)
{
_options.EnableTtlCleanup = enable;
if (retentionSeconds.HasValue)
_options.RetentionTime = TimeSpan.FromSeconds(retentionSeconds.Value);
return Ok(new { _options.EnableTtlCleanup, RetentionSeconds = _options.RetentionTime.TotalSeconds });
}
// Kapasite Sınırlamasını Aç/Kapat veya Limiti Değiştir
[HttpPost("capacity")]
public IActionResult ToggleCapacity([FromQuery] bool enable, [FromQuery] int? maxCapacity = null)
{
_options.EnableCapacityEviction = enable;
if (maxCapacity.HasValue)
_options.MaxStoreCapacity = maxCapacity.Value;
return Ok(new { _options.EnableCapacityEviction, _options.MaxStoreCapacity });
}
}
Bellek kendi kendini yönetir.
İki bağımsız mekanizma, isteğe bağlı olarak birlikte veya ayrı ayrı çalışır.
Kapasite Temizlik Mantığı
EnableCapacityEviction = true ve MaxStoreCapacity = 3 olduğunu varsayalım:
- Anlık yoğunlukta 6 iş eklendiyse ve hepsi hâlâ çalışıyorsa, hiçbir kayıt silinmez.
- İşler tamamlandıkça ve yeni iş eklendikçe, depo boyutu hedef kapasiteye (3) inene kadar tamamlanan işler en eskiden başlayarak sırayla silinir.
TTL Temizlik Mantığı
EnableTtlCleanup = true ve RetentionTime = 1 dk olduğunu varsayalım:
- Bir iş 14:00:00'da tamamlandığında,
JobCleanupServicetarafından 14:01:00 itibarıyla otomatik olarak bellekten kaldırılır. - Kontrol sıklığı
CleanupIntervalparametresiyle ayarlanır.
Kuyruğa ilk işinizi eklemeye hazır mısınız?
MIT lisanslı — ticari ya da bireysel projelerinizde dilediğiniz gibi kullanabilir, geliştirebilirsiniz.