hat.monitor.server.blessing

Implementation of blessing calculation algorithms

  1"""Implementation of blessing calculation algorithms"""
  2
  3import enum
  4import itertools
  5import time
  6
  7from hat.monitor import common
  8
  9
 10_next_tokens = itertools.count(1)
 11
 12
 13class Algorithm(enum.Enum):
 14    BLESS_ALL = 'BLESS_ALL'
 15    BLESS_ONE = 'BLESS_ONE'
 16
 17
 18def calculate(components: list[common.ComponentInfo],
 19              group_algorithms: dict[str, Algorithm],
 20              default_algorithm: Algorithm
 21              ) -> list[common.ComponentInfo]:
 22    """Calculate blessing
 23
 24    Args:
 25        components: components state with previous blessing tokens
 26        group_algorithms: association of algorithm to group
 27        default_algorithm: default algorithm
 28
 29    Returns:
 30        components state with updated blessing
 31
 32    """
 33    group_components = {}
 34    for c in components:
 35        group_components.setdefault(c.group, []).append(c)
 36
 37    blessings = {}
 38    for group, components_from_group in group_components.items():
 39        algorithm = group_algorithms.get(group, default_algorithm)
 40        for c in _calculate_group(algorithm, components_from_group):
 41            blessings[c.mid, c.cid] = c.blessing_req
 42
 43    result = [c._replace(blessing_req=blessings[c.mid, c.cid])
 44              for c in components]
 45
 46    return result
 47
 48
 49def _calculate_group(algorithm, components):
 50    if algorithm == Algorithm.BLESS_ALL:
 51        return _bless_all(components)
 52
 53    if algorithm == Algorithm.BLESS_ONE:
 54        return _bless_one(components)
 55
 56    raise ValueError('unsupported algorithm')
 57
 58
 59def _bless_all(components):
 60    for c in components:
 61        if not c.blessing_res.ready:
 62            yield c._replace(blessing_req=common.BlessingReq(token=None,
 63                                                             timestamp=None))
 64
 65        elif _has_blessing(c):
 66            yield c
 67
 68        else:
 69            blessing = common.BlessingReq(token=next(_next_tokens),
 70                                          timestamp=time.time())
 71            yield c._replace(blessing_req=blessing)
 72
 73
 74def _bless_one(components):
 75
 76    def highlander_battle(highlander, c):
 77        if not highlander:
 78            return c
 79        if c.rank < highlander.rank:
 80            return c
 81        if c.rank == highlander.rank:
 82            if _has_blessing(c) and not _has_blessing(highlander):
 83                return c
 84            if _has_blessing(c) and _has_blessing(highlander):
 85                if (c.blessing_req.timestamp <
 86                        highlander.blessing_req.timestamp):
 87                    return c
 88            if _has_blessing(c) and _has_blessing(highlander) or (
 89                    not _has_blessing(c) and
 90                    not _has_blessing(highlander)):
 91                if c.mid < highlander.mid:
 92                    return c
 93        return highlander
 94
 95    highlander = None
 96    for c in components:
 97        if not c.blessing_res.ready:
 98            continue
 99        highlander = highlander_battle(highlander, c)
100
101    if highlander and not (highlander.blessing_res.token and
102                           highlander.blessing_res.token ==
103                           highlander.blessing_req.token):
104        for c in components:
105            if c.blessing_res.token and c != highlander:
106                highlander = None
107                break
108
109    for c in components:
110        if c != highlander:
111            blessing = common.BlessingReq(token=None,
112                                          timestamp=None)
113            yield c._replace(blessing_req=blessing)
114
115        elif not _has_blessing(c):
116            blessing = common.BlessingReq(token=next(_next_tokens),
117                                          timestamp=time.time())
118            yield c._replace(blessing_req=blessing)
119
120        else:
121            yield c
122
123
124def _has_blessing(component):
125    return (component.blessing_req.token and
126            component.blessing_req.timestamp)
class Algorithm(enum.Enum):
14class Algorithm(enum.Enum):
15    BLESS_ALL = 'BLESS_ALL'
16    BLESS_ONE = 'BLESS_ONE'

An enumeration.

BLESS_ALL = <Algorithm.BLESS_ALL: 'BLESS_ALL'>
BLESS_ONE = <Algorithm.BLESS_ONE: 'BLESS_ONE'>
Inherited Members
enum.Enum
name
value
def calculate( components: list[hat.monitor.common.ComponentInfo], group_algorithms: dict[str, Algorithm], default_algorithm: Algorithm) -> list[hat.monitor.common.ComponentInfo]:
19def calculate(components: list[common.ComponentInfo],
20              group_algorithms: dict[str, Algorithm],
21              default_algorithm: Algorithm
22              ) -> list[common.ComponentInfo]:
23    """Calculate blessing
24
25    Args:
26        components: components state with previous blessing tokens
27        group_algorithms: association of algorithm to group
28        default_algorithm: default algorithm
29
30    Returns:
31        components state with updated blessing
32
33    """
34    group_components = {}
35    for c in components:
36        group_components.setdefault(c.group, []).append(c)
37
38    blessings = {}
39    for group, components_from_group in group_components.items():
40        algorithm = group_algorithms.get(group, default_algorithm)
41        for c in _calculate_group(algorithm, components_from_group):
42            blessings[c.mid, c.cid] = c.blessing_req
43
44    result = [c._replace(blessing_req=blessings[c.mid, c.cid])
45              for c in components]
46
47    return result

Calculate blessing

Arguments:
  • components: components state with previous blessing tokens
  • group_algorithms: association of algorithm to group
  • default_algorithm: default algorithm
Returns:

components state with updated blessing