Revize 22c09a00
Přidáno uživatelem Jakub Šilhavý před více než 2 roky(ů)
client/src/usb_detector/api_client.py | ||
---|---|---|
6 | 6 |
from requests import HTTPError, ConnectionError |
7 | 7 |
from requests.exceptions import InvalidSchema |
8 | 8 |
|
9 |
_uri = None |
|
10 |
_cache = None |
|
11 |
_config = None |
|
9 |
|
|
10 |
_uri = None # server uri (url, port, and endpoint) |
|
11 |
_cache = None # cache (failed payloads) |
|
12 |
_config = None # instance of Config |
|
12 | 13 |
|
13 | 14 |
|
14 | 15 |
def api_client_set_config(config): |
16 |
"""Initializes the client API module. |
|
17 |
|
|
18 |
This function is meant to be called prior to calling any other function |
|
19 |
of the API module. It stores the instance of Config (config manager) |
|
20 |
into a private variable. It also initializes the cache for unsuccessful |
|
21 |
payloads and constructs a URI (endpoint on the server side). |
|
22 |
|
|
23 |
:param config: instance of Config which holds all values defined |
|
24 |
in the configuration file. |
|
25 |
""" |
|
26 |
# Store the variables globally within the module (file). |
|
15 | 27 |
global _config, _cache, _uri |
28 |
|
|
29 |
# Store the instance of Config and initialize the cache. |
|
16 | 30 |
_config = config |
17 | 31 |
_cache = _init_cache() |
32 |
|
|
33 |
# Creates the URI which is made of the server url, port, and path (endpoint). |
|
18 | 34 |
_uri = config.server_url + ":" + config.server_port + config.server_endpoint |
19 | 35 |
|
20 | 36 |
|
21 | 37 |
def _init_cache(): |
38 |
""" Initializes and returns a disk-based cache. |
|
39 |
|
|
40 |
The cache holds payloads that the application failed |
|
41 |
to send to the server. It periodically attempts to resent |
|
42 |
them to the server. All parameters can be seen in the |
|
43 |
configuration file. |
|
44 |
|
|
45 |
:return: instance of a new cache (Deque - FIFO) |
|
46 |
""" |
|
22 | 47 |
return Deque(directory=_config.cache_dir) |
23 | 48 |
|
24 | 49 |
|
25 | 50 |
def send_data(payload: dict): |
51 |
"""Sends a payload off to the server. |
|
52 |
|
|
53 |
This function is called whenever a USB is connected |
|
54 |
or disconnected. If there is no internet connection or the |
|
55 |
server is not up and running, the payload will be stored |
|
56 |
into the disk cache. |
|
57 |
|
|
58 |
:param payload: |
|
59 |
""" |
|
60 |
# Make sure that the URI has been constructed properly. |
|
61 |
# It's supposed to be done by calling the api_client_set_config function |
|
62 |
# with appropriate parameters. |
|
26 | 63 |
if _uri is None: |
27 | 64 |
logging.warning(f"sending payload = {payload} failed because uri is set to None") |
28 | 65 |
_cache_failed_payload(payload) |
... | ... | |
40 | 77 |
|
41 | 78 |
|
42 | 79 |
def _cache_failed_payload(payload: dict): |
80 |
""" Caches a payload. |
|
81 |
|
|
82 |
This function is called when the application fails to send a payload |
|
83 |
to the server. The payload gets stored into a file-based cache from which |
|
84 |
it will be periodically retrieved as the client will attempt to send |
|
85 |
it to the server again. All parameters regarding the cache can be found |
|
86 |
in the configuration file. |
|
87 |
|
|
88 |
:param payload: payload to be cached |
|
89 |
""" |
|
90 |
# If the cache is "full", discard the oldest record. |
|
43 | 91 |
if len(_cache) >= _config.cache_max_entries: |
44 | 92 |
oldest_payload = _cache.pop() |
45 | 93 |
logging.warning(f"cache is full - discarding payload = {oldest_payload}") |
46 | 94 |
|
95 |
# Store the payload into the cache. |
|
47 | 96 |
logging.info(f"adding payload = {payload} into cache") |
48 | 97 |
_cache.append(payload) |
49 | 98 |
|
50 | 99 |
|
51 | 100 |
def _resend_cached_payloads(): |
101 |
"""Reattempts to send cached payloads to the server (API). |
|
102 |
|
|
103 |
In the configuration file, there is a predefined number of |
|
104 |
payloads that can be sent to the server with each call of this function. |
|
105 |
This function is called periodically from api_client_run in order |
|
106 |
to resend failed payloads to the server. |
|
107 |
|
|
108 |
""" |
|
109 |
# Calculate how many payload will be sent to the server |
|
52 | 110 |
retries = min(_config.cache_max_retries, len(_cache)) |
53 | 111 |
logging.info(f"emptying the cache ({retries} records)") |
112 |
|
|
113 |
# Send the payloads to the server one by one. |
|
54 | 114 |
for _ in range(0, retries): |
55 | 115 |
payload = _cache.pop() |
56 | 116 |
send_data(payload) |
57 | 117 |
|
58 | 118 |
|
59 | 119 |
def api_client_run(): |
120 |
""" Keeps resending failed payloads to the server. |
|
121 |
|
|
122 |
This function is instantiated as a thread that periodically |
|
123 |
calls the _resend_cached_payloads function in order to empty |
|
124 |
the cache (failed payloads). The period can be set in the |
|
125 |
configuration file. |
|
126 |
""" |
|
60 | 127 |
while True: |
128 |
# Resend a predefined amount of failed payloads to the server. |
|
61 | 129 |
_resend_cached_payloads() |
130 |
|
|
131 |
# Sleep for a predefined amount of seconds. |
|
62 | 132 |
sleep(_config.cache_retry_period_seconds) |
Také k dispozici: Unified diff
re #9422 Commented both config files and api_client.py.