MIT Lisanslı · .NET 6 / 8 / 10

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.

$ git clone https://github.com/DSOpenServer/DSO.Core.QueueWorker.git
İş Akışı — Canlı Önizleme
Pending Queued Processing Completed
API / Client
Enqueue()
BackgroundJobQueue
Channel<T>
QueueWorkerService
SemaphoreSlim
JobResultStore
ConcurrentDictionary
Öne Çıkan Özellikler

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.

Mimari Yapı

Dört bileşen, tek yön akış.

İstek kuyruğa girer, worker sırayla işler, sonuç deposu her adımı raporlar.

[ API / Client ] ──(Enqueue)──► [ BackgroundJobQueue ] ──(Channel)──► [ QueueWorkerService ] │ │ │ (Executes Work) │ │ └──(Query Status / Dynamic Config)──► [ JobResultStore ] ◄───────────────┘
Kurulum ve Kullanım

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 });
    }
}
Temizlik Mantığı

Bellek kendi kendini yönetir.

İki bağımsız mekanizma, isteğe bağlı olarak birlikte veya ayrı ayrı çalışır.

MaxStoreCapacity

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.
RetentionTime

TTL Temizlik Mantığı

EnableTtlCleanup = true ve RetentionTime = 1 dk olduğunu varsayalım:

  • Bir iş 14:00:00'da tamamlandığında, JobCleanupService tarafından 14:01:00 itibarıyla otomatik olarak bellekten kaldırılır.
  • Kontrol sıklığı CleanupInterval parametresiyle 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.