File: Routing\Internal\OrderedGroups\OrderedGroupsRoutingStrategy.cs
Web Access
Project: src\src\Libraries\Microsoft.Extensions.Http.Resilience\Microsoft.Extensions.Http.Resilience.csproj (Microsoft.Extensions.Http.Resilience)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Http.Resilience.Internal;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Shared.Diagnostics;
 
namespace Microsoft.Extensions.Http.Resilience.Routing.Internal.OrderedGroups;
 
internal sealed class OrderedGroupsRoutingStrategy : RequestRoutingStrategy, IResettable
{
    private readonly ObjectPool<OrderedGroupsRoutingStrategy> _pool;
    private int _lastUsedIndex;
    private IList<UriEndpointGroup>? _groups;
 
    public OrderedGroupsRoutingStrategy(Randomizer randomizer, ObjectPool<OrderedGroupsRoutingStrategy> pool)
        : base(randomizer)
    {
        _pool = pool;
    }
 
    public void Initialize(IList<UriEndpointGroup> groups)
    {
        _ = TryReset();
 
        _groups = groups;
    }
 
    public override bool TryGetNextRoute([NotNullWhen(true)] out Uri? nextRoute)
    {
        if (_groups == null)
        {
            Throw.InvalidOperationException("The routing strategy is not initialized.");
        }
 
        if (TryGetNextGroup(out var group))
        {
            nextRoute = group!.Endpoints.SelectByWeight(e => e.Weight, Randomizer!).Uri!;
            return true;
        }
 
        nextRoute = null;
        return false;
    }
 
    public override void Dispose() => _pool.Return(this);
 
    public override bool TryReset()
    {
        _groups = null;
        _lastUsedIndex = 0;
        return true;
    }
 
    private bool TryGetNextGroup(out UriEndpointGroup? nextGroup)
    {
        if (_lastUsedIndex >= _groups!.Count)
        {
            nextGroup = null;
            return false;
        }
 
        nextGroup = _groups[_lastUsedIndex];
        _lastUsedIndex++;
        return true;
    }
}