Skip to content

Instantly share code, notes, and snippets.

@runceel
Last active September 23, 2021 06:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runceel/d975f3e92975b98cd638d25e98fe3776 to your computer and use it in GitHub Desktop.
Save runceel/d975f3e92975b98cd638d25e98fe3776 to your computer and use it in GitHub Desktop.
var dataService = new DataService();
dataService.AddWorker(new Worker(1));
dataService.AddWorker(new Worker(2));
dataService.AddWorker(new Worker(3));
dataService.AddWorker(new Worker(4));
var frontend1 = new FrontendInfo("tsushi01", "FE1");
var frontend2 = new FrontendInfo("tsushi02", "FE2");
// 適当に空いてるワーカーを返してもらう
Console.WriteLine(dataService.GetAvailableWorker(frontend1));
Console.WriteLine(dataService.GetAvailableWorker(frontend2));
// 再要求しても同じワーカーが返ってくるはず
Console.WriteLine(dataService.GetAvailableWorker(frontend1));
Console.WriteLine(dataService.GetAvailableWorker(frontend2));
record Worker(int Id);
record FrontendInfo(string HostName, string FrontEnd);
class DataService
{
// ロック用
private readonly object _syncRoot = new();
// 誰も使ってないワーカー管理
private readonly Queue<Worker> _availableWorkers= new();
// フロントエンドに割り当て済みのワーカー管理
private readonly Dictionary<FrontendInfo, Worker> _assignedWorkers = new();
public Worker? GetAvailableWorker(FrontendInfo frontend)
{
lock(_syncRoot)
{
var worker = GetWorkerForFrontend(frontend);
if (worker == null)
{
worker = AssignWorker(frontend);
}
return worker;
}
}
// Frontend がワーカーが不要になったときに返却
public void ReleaseWorker(FrontendInfo frontend)
{
lock(_syncRoot)
{
if (_assignedWorkers.TryGetValue(frontend, out var worker))
{
_assignedWorkers.Remove(frontend);
_availableWorkers.Append(worker);
}
}
}
// データサービスが管理する Worker を追加
public void AddWorker(Worker worker)
{
lock(_syncRoot)
{
_availableWorkers.Append(worker);
}
}
// 誰も使ってない Worker を Frontend に割り当てる
private Worker? AssignWorker(FrontendInfo frontend)
{
if (_availableWorkers.Count == 0)
{
return null;
}
var worker = _availableWorkers.Dequeue();
_assignedWorkers.Add(frontend, worker);
return worker;
}
// Frontend に対して既に割り当て済みの Worker があったらそれを返す
private Worker? GetWorkerForFrontend(FrontendInfo frontend)
{
_ = _assignedWorkers.TryGetValue(frontend, out var worker);
return worker;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment