Files
InServiceQue/InServiceQue.InMemory/TaskRepositoryInMemory.cs

136 lines
3.2 KiB
C#

using System.Collections.Concurrent;
using System.Data;
using InServiceQue.Core.Models;
using InServiceQue.Core.Repositories;
namespace InServiceQue.InMemory;
public class TaskRepositoryInMemory: ITaskRepository
{
//todo: concurrent access here
private static int _currentShard;
private static ConcurrentDictionary<string, ConcurrentQueue<QueueTask>> _quesByType = new();
public void Dispose()
{
// TODO release managed resources here
}
public void Insert(QueueTask task)
{
if (_quesByType.ContainsKey(task.TaskType))
{
_quesByType.AddOrUpdate(task.TaskType,
(t) => new ConcurrentQueue<QueueTask>(new[] { task }),
(t, queue) =>
{
queue.Enqueue(task);
return queue;
}
);
}
}
public async Task InsertAsync(QueueTask task)
{
Insert(task);
await Task.CompletedTask;
}
public IDbTransaction StartTransaction()
{
return null;
}
public async Task<IDbTransaction> StartTransactionAsync()
{
return await Task.FromResult<IDbTransaction>(null);
}
public void CommitTransaction(IDbTransaction tx)
{
}
public async Task CommitTransactionAsync(IDbTransaction tx)
{
await Task.CompletedTask;
}
public void RollbackTransaction(IDbTransaction tx)
{
}
public async Task RollbackTransactionAsync(IDbTransaction tx)
{
await Task.CompletedTask;
}
public QueueTask? GetNextTask(IDbTransaction tx, string? taskType = null)
{
if (taskType == null)
return GetNextTaskRolling();
QueueTask? task = null;
if (_quesByType.TryGetValue(taskType, out var que))
{
que.TryDequeue(out task);
}
return task;
}
public QueueTask? GetNextTaskRolling()
{
QueueTask? task = null;
var topicsCount = _quesByType.Count;
for (int i = 0; i < topicsCount; i++)
{
//todo: concurrent access
if (i == _currentShard)
{
var keyValuePair = _quesByType.ToArray()[i];
var que = keyValuePair.Value;
que.TryDequeue(out task);
if (que.IsEmpty)
{
_quesByType.TryRemove(keyValuePair);
}
break;
}
}
//todo: concurrent access
_currentShard = _currentShard == topicsCount - 1 ? 0 : _currentShard + 1;
return task;
}
public async Task<QueueTask?> GetNextTaskAsync(IDbTransaction tx, string? taskType = null)
{
if (taskType == null)
return await Task.FromResult(GetNextTaskRolling());
QueueTask? task = null;
if (_quesByType.TryGetValue(taskType, out var que))
{
que.TryDequeue(out task);
}
return await Task.FromResult(task);
}
public void SaveTask(QueueTask task, IDbTransaction tx)
{
}
public async Task SaveTaskAsync(QueueTask task, IDbTransaction tx)
{
await Task.CompletedTask;
}
}