Module search_me.balancers

Expand source code
# -*- coding: utf-8 -*-
from abc import abstractmethod
from collections import defaultdict
from functools import reduce
from itertools import cycle
from math import gcd as mgcd
from search_me.tools import count_calls


__all__ = ("RR", "DWRR")


class AR:
    """Abstract class describes protocol of balance strategies
    """

    def __init__(self):
        """Init
        """
        self.calls = defaultdict(int)

    def __iter__(self):
        """Iterator must-have method

        Returns
        -------
        Iterator
            Iterator
        """
        return next(self)

    @abstractmethod
    def __next__(self):
        """Iterator must-have method

        Raises
        ------
        NotImplementedError
            Should be implemented in nested class
        """
        raise NotImplementedError()


class RR(AR):
    """Round Robin

    Parameters
    ----------
    AR : class
        Abstract Robin
    """

    def __init__(self, *data):
        """Init
        """
        super().__init__()
        self.__cycle = cycle(data)

    @count_calls
    def __next__(self):
        """Get next item

        Returns
        -------
        Any
            Next item
        """
        item = next(self.__cycle)
        return item


class WRR(AR):
    """Weighted Round Robin

    Parameters
    ----------
    AR : class
        Abstract Robin
    """

    def __init__(self, *data):
        """Init
        """
        super().__init__()
        self.weights = list(data)
        self.size = len(data)
        self.max_w = max(data, key=lambda x: x[1])[1]
        self.gcd = reduce(mgcd, (w for _, w in data))
        self.cur_idx = -1
        self.cur_w = 0

    @count_calls
    def __next__(self):
        """Get next item

        Returns
        -------
        Any
            Next item
        """
        while True:
            self.cur_idx = (self.cur_idx + 1) % self.size
            if self.cur_idx == 0:
                self.cur_w = self.cur_w - self.gcd
                if self.cur_w <= 0:
                    self.cur_w = self.max_w
                    if self.cur_w == 0:
                        return
            item, w = self.weights[self.cur_idx]
            if w >= self.cur_w:
                return item


class DWRR(AR):
    """Dynamic Weighted Round Robin

    Parameters
    ----------
    AR : class
        Abstract Robin
    """

    def __init__(self, *data):
        """Init
        """
        super().__init__()
        self.weights = {d: 1000 for d in data}
        self.size = len(data)
        self.cur_idx = -1
        self.cur_w = 0

    @count_calls
    def __next__(self):
        """Get next item

        Returns
        -------
        Any
            Next item
        """
        while True:
            self.cur_idx = (self.cur_idx + 1) % self.size
            if self.cur_idx == 0:
                self.cur_w = self.cur_w - self.gcd
                if self.cur_w <= 0:
                    self.cur_w = self.max_w
                    if self.cur_w == 0:
                        return
            item, w = self.data_w[self.cur_idx]
            if w >= self.cur_w:
                return item

    def recalc_weights(self, item, w_value):
        """Recalc weights for item

        Parameters
        ----------
        item : str
            item name
        w_value : int
            Weight
        """
        self.weights[item] += w_value

    @property
    def data_w(self):
        """Data weights

        Returns
        -------
        List
            List of data tuples
        """
        return list(self.weights.items())

    @property
    def max_w(self):
        """Get max weight

        Returns
        -------
        int
            Max weight
        """
        return max(self.data_w, key=lambda x: x[1])[1]

    @property
    def gcd(self):
        """Reduced gcd

        Returns
        -------
        int
            GCD
        """
        return reduce(mgcd, (w for _, w in self.data_w))

Classes

class DWRR (*data)

Dynamic Weighted Round Robin

Parameters

AR : class
Abstract Robin
Init
 
Expand source code
class DWRR(AR):
    """Dynamic Weighted Round Robin

    Parameters
    ----------
    AR : class
        Abstract Robin
    """

    def __init__(self, *data):
        """Init
        """
        super().__init__()
        self.weights = {d: 1000 for d in data}
        self.size = len(data)
        self.cur_idx = -1
        self.cur_w = 0

    @count_calls
    def __next__(self):
        """Get next item

        Returns
        -------
        Any
            Next item
        """
        while True:
            self.cur_idx = (self.cur_idx + 1) % self.size
            if self.cur_idx == 0:
                self.cur_w = self.cur_w - self.gcd
                if self.cur_w <= 0:
                    self.cur_w = self.max_w
                    if self.cur_w == 0:
                        return
            item, w = self.data_w[self.cur_idx]
            if w >= self.cur_w:
                return item

    def recalc_weights(self, item, w_value):
        """Recalc weights for item

        Parameters
        ----------
        item : str
            item name
        w_value : int
            Weight
        """
        self.weights[item] += w_value

    @property
    def data_w(self):
        """Data weights

        Returns
        -------
        List
            List of data tuples
        """
        return list(self.weights.items())

    @property
    def max_w(self):
        """Get max weight

        Returns
        -------
        int
            Max weight
        """
        return max(self.data_w, key=lambda x: x[1])[1]

    @property
    def gcd(self):
        """Reduced gcd

        Returns
        -------
        int
            GCD
        """
        return reduce(mgcd, (w for _, w in self.data_w))

Ancestors

  • search_me.balancers.AR

Instance variables

var data_w

Data weights

Returns

List
List of data tuples
Expand source code
@property
def data_w(self):
    """Data weights

    Returns
    -------
    List
        List of data tuples
    """
    return list(self.weights.items())
var gcd

Reduced gcd

Returns

int
GCD
Expand source code
@property
def gcd(self):
    """Reduced gcd

    Returns
    -------
    int
        GCD
    """
    return reduce(mgcd, (w for _, w in self.data_w))
var max_w

Get max weight

Returns

int
Max weight
Expand source code
@property
def max_w(self):
    """Get max weight

    Returns
    -------
    int
        Max weight
    """
    return max(self.data_w, key=lambda x: x[1])[1]

Methods

def recalc_weights(self, item, w_value)

Recalc weights for item

Parameters

item : str
item name
w_value : int
Weight
Expand source code
def recalc_weights(self, item, w_value):
    """Recalc weights for item

    Parameters
    ----------
    item : str
        item name
    w_value : int
        Weight
    """
    self.weights[item] += w_value
class RR (*data)

Round Robin

Parameters

AR : class
Abstract Robin
Init
 
Expand source code
class RR(AR):
    """Round Robin

    Parameters
    ----------
    AR : class
        Abstract Robin
    """

    def __init__(self, *data):
        """Init
        """
        super().__init__()
        self.__cycle = cycle(data)

    @count_calls
    def __next__(self):
        """Get next item

        Returns
        -------
        Any
            Next item
        """
        item = next(self.__cycle)
        return item

Ancestors

  • search_me.balancers.AR