Passed
Push — master ( e21377...5956eb )
by Dave
01:06
created

backend.when_runrules.gather_broken_rules()   A

Complexity

Conditions 3

Size

Total Lines 7
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
'''
2
# listens for statistics updated and run rules on them
3
# some rules can run just from the last statistics
4
# other rules will need to be enforced from the history of the miner
5
'''
6
import datetime
7
import json
8
from colorama import Fore
9
from helpers.queuehelper import QueueName, QueueEntries
10
from domain.mining import MinerCommand
11
from domain.miningrules import MinerStatisticsRule
12
from domain.logging import MinerLog
13
from backend.fcmcomponent import ComponentName
14
from backend.fcmapp import Component
15
16
class ComponentRunRules(Component):
17
    '''component for running rules'''
18
    def __init__(self):
19
        self.alertstext = ''
20
        super().__init__(componentname=ComponentName.rules, option='')
21
22
    def addalert(self, alertmsg):
23
        self.alertstext += alertmsg
24
        return alertmsg
25
26
RULES = ComponentRunRules()
27
28
def rules(miner, minerstats, minerpool):
29
    '''this runs the rules'''
30
    entries = QueueEntries()
31
    if miner is None or minerstats is None:
32
        return entries
33
    savedminer = RULES.app.getminer(miner)
34
    cmd_restart = MinerCommand('restart', '')
35
    broken = gather_broken_rules(savedminer, minerstats)
36
    if broken:
37
        #TODO: could raise broken rule event???
38
        for rule in broken:
39
            RULES.app.log_mineractivity(make_log_from_rule(rule))
40
            add_entry_for_rule(entries, rule)
41
    return entries
42
43
def gather_broken_rules(savedminer, minerstats):
44
    broken = []
45
    for ruleparms in RULES.app.ruleparameters():
46
        rule = MinerStatisticsRule(savedminer, minerstats, ruleparms)
47
        if rule.isbroken():
48
            broken += rule.brokenrules
49
    return broken
50
51
def add_entry_for_rule(entries, rule):
52
    if rule.action == 'alert':
53
        entries.addalert(RULES.addalert(RULES.app.stamp(rule.parameter)))
54
    elif rule.action == 'restart':
55
        entries.add(QueueName.Q_RESTART, RULES.app.createmessagecommand(rule.miner, cmd_restart))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable cmd_restart does not seem to be defined.
Loading history...
56
        entries.addalert(RULES.addalert(RULES.app.stamp('Restarted {0}'.format(rule.miner.name))))
57
    else:
58
        RULES.app.logerror('did not process broken rule {0}'.format(rule.parameter))
59
60
def make_log_from_rule(rule):
61
    log = MinerLog()
62
    log.createdate = datetime.datetime.utcnow()
63
    log.minerid = rule.miner.key()
64
    log.minername = rule.miner.name
65
    log.action = rule.parameter
66
    return log
67
68
def when_statisticsupdated(channel, method, properties, body):
69
    '''when miner stats are pulled from miner...'''
70
    print("[{0}] Received miner stats".format(RULES.app.now()))
71
    try:
72
        msg = RULES.app.messagedecodeminerstats(body)
73
        entries = dorules(msg.miner, msg.minerstats, msg.minerpool)
74
        RULES.app.enqueue(entries)
75
    except json.decoder.JSONDecodeError as jex:
76
        RULES.app.logexception(jex)
77
        RULES.app.logdebug(RULES.app.exceptionmessage(jex))
78
        RULES.app.logdebug(RULES.app.safestring(body))
79
    except BaseException as ex:
80
        RULES.app.logexception(ex)
81
        RULES.app.logdebug(RULES.app.exceptionmessage(ex))
82
        RULES.app.logdebug(RULES.app.safestring(body))
83
84
def dorules(miner, minerstats, minerpool):
85
    '''run the rules on them'''
86
    RULES.alertstext = ''
87
    entries = rules(miner, minerstats, minerpool)
88
    if RULES.alertstext:
89
        print(Fore.RED + RULES.alertstext)
90
    print("Rules executed for {0}".format(miner.name))
91
    return entries
92
93
def main():
94
    if RULES.app.isrunnow:
95
        for (miner, stats, pool) in RULES.app.getminerstatscached():
96
            rules(miner, stats, pool)
97
        RULES.app.shutdown()
98
    else:
99
        RULES.listeningqueue = RULES.app.listen_to_broadcast(QueueName.Q_STATISTICSUPDATED, when_statisticsupdated)
100
101
if __name__ == "__main__":
102
    main()
103