1
- from multiprocessing import Process , Manager , Lock
1
+ #from multiprocessing import Process, Manager, Lock
2
+ import grequests
2
3
import requests
3
4
from time import time , sleep
4
5
import logging
5
6
6
-
7
7
class ClientHandler :
8
8
"""Performs concurrent requests with timeout
9
9
@@ -14,50 +14,22 @@ class ClientHandler:
14
14
def __init__ (self , clients , OPERATION_MODE = 'wait_all' , ** kwargs ):
15
15
self .clients = self .parse_clients (clients )
16
16
self .n_clients = len (clients )
17
- self .OPERATION_MODE = OPERATION_MODE
18
- logging .info (
19
- '[Client Handler] Operation mode: {}' .format (self .OPERATION_MODE ))
20
- default_n_firsts = max (1 , self .n_clients - 2 )
21
- if self .OPERATION_MODE == 'n_firsts' :
22
- self .N_FIRSTS = kwargs .get ('n_firsts' , default_n_firsts )
23
- assert self .N_FIRSTS <= self .n_clients , \
24
- 'n_firsts must be <= than num clients'
25
- logging .info (
26
- '[Client Handler] n_firsts: {}' .format (self .N_FIRSTS ))
27
- elif self .OPERATION_MODE == 'timeout' :
28
- self .WAIT_FROM_N_FIRSTS = kwargs .get ('wait_from_n_firsts' ,
29
- default_n_firsts )
30
- self .TIMEOUT = kwargs .get ('timoeut' , 60 ) # Seconds
31
- elif self .OPERATION_MODE == 'wait_all' :
32
- self .N_FIRSTS = self .n_clients
33
- logging .info ('[Client Handler] Will wait '
34
- 'until {} clients' .format (self .N_FIRSTS ))
35
- else :
17
+ if not OPERATION_MODE == 'wait_all' :
36
18
raise Exception ('Operation mode not accepted' )
37
- self .manager = Manager ()
38
- self .lock = Lock ()
39
- self .last_operation = self .manager .dict ()
40
- self .reset_last_operation ()
41
- self .processes = []
19
+ logging .info (
20
+ '[Client Handler] Operation mode: {}' .format (OPERATION_MODE ))
42
21
43
22
def perform_requests_and_wait (self , endpoint ):
44
- self .perform_parallel_requests (endpoint )
45
- if self .OPERATION_MODE == 'n_firsts' :
46
- if endpoint == 'send_model' :
47
- # TODO: Do this part with redundancy
48
- return self .wait_until ('n_responses' , wait_all = True )
49
- return self .wait_until ('n_responses' )
50
- elif self .OPERATION_MODE == 'timeout' :
51
- self .started = time ()
52
- return self .wait_until ('timeout' )
53
- elif self .OPERATION_MODE == 'wait_all' :
54
- return self .wait_until ('n_responses' , wait_all = True )
55
-
56
- def reset_last_operation (self ):
57
- self .lock .acquire ()
58
- for key in self .clients :
59
- self .last_operation [key ] = None
60
- self .lock .release ()
23
+ client_urls = self .get_client_urls (endpoint )
24
+ rs = (grequests .get (u ) for u in client_urls )
25
+ responses = grequests .map (rs )
26
+ for res in responses :
27
+ if not res or res .status_code != 200 :
28
+ raise Exception ('The response was not successful. '
29
+ 'Code: {}, Msg: {}' .format (res .status_code ,
30
+ res .text ))
31
+ l = len (responses )
32
+ logging .info ('[Client Handler] Got {} responses' .format (l ))
61
33
62
34
@staticmethod
63
35
def parse_clients (clients ):
@@ -68,76 +40,147 @@ def parse_clients(clients):
68
40
p_clients .append ((host , port ))
69
41
return p_clients
70
42
71
- def perform_parallel_requests (self , endpoint ):
72
- self . reset_last_operation ()
43
+ def get_client_urls (self , endpoint ):
44
+ urls = []
73
45
for host , port in self .clients :
74
- p = Process (target = self .perform_request ,
75
- args = (host , port , endpoint ))
76
- p .start ()
77
- self .processes .append (p )
78
-
79
- def wait_until (self , until_cond , wait_all = False ):
80
- # TODO: What to do in send model?
81
- ended_clients = set ()
82
- completed = False
83
- while not completed :
84
- # Periodically check if the requests are ending
85
- for key in self .clients :
86
- last_operation = self .last_operation [key ]
87
- if not last_operation or key in ended_clients :
88
- # Last operation still not computed or already finished
89
- continue
90
- elif last_operation ['ended' ]:
91
- # TODO: Handle exception when status code != 200
92
- if last_operation ['response' ].status_code != 200 :
93
- raise Exception (
94
- 'Error in response. Error code: {}' .format (
95
- last_operation ['response' ].text ))
96
- logging .info (
97
- '[Client Handler] client {} '
98
- 'finished performing operation {}' .format (
99
- key , last_operation ['op' ]
100
- )
101
- )
102
- ended_clients .add (key )
103
- if until_cond == 'n_responses' :
104
- if ((not wait_all and (len (ended_clients ) >= self .N_FIRSTS ))
105
- or (wait_all and len (ended_clients ) == self .N_FIRSTS )):
106
- completed = True
107
- elif until_cond == 'timeout' :
108
- elapsed = time () - self .started
109
- if ((len (ended_clients ) >= self .WAIT_FROM_N_FIRSTS ) and
110
- elapsed > self .TIMEOUT ):
111
- completed = True
112
- else :
113
- raise Exception ('Not implemented' )
114
- sleep (0.2 )
115
- self .terminate_processes ()
116
- return list (ended_clients )
117
-
118
- def terminate_processes (self ):
119
- for p in self .processes :
120
- p .terminate ()
121
- self .processes = []
122
-
123
- @staticmethod
124
- def get_client_key (host , port ):
125
- return (host , port )
126
-
127
- def perform_request (self , host , port , endpoint ):
128
- client_key = self .get_client_key (host , port )
129
- last_operation = {
130
- 'started' : time (),
131
- 'op' : endpoint ,
132
- 'status' : 'started' ,
133
- 'ended' : None
134
- }
135
- url = 'http://{}:{}/{}' .format (host , port , endpoint )
136
- res = requests .get (url )
137
- last_operation .update ({'status' : 'ended' ,
138
- 'ended' : time (),
139
- 'response' : res })
140
- self .lock .acquire ()
141
- self .last_operation [client_key ] = last_operation
142
- self .lock .release ()
46
+ urls .append ('http://{}:{}/{}' .format (host , port , endpoint ))
47
+ return urls
143
48
49
+ # This was about to work but parellility is difficult and in practics is not working
50
+ #class ClientHandler:
51
+ # """Performs concurrent requests with timeout
52
+ #
53
+ # :OPERATION_MODE n_firsts, timeout or wait_all.
54
+ # :clients list of clients' (host, port) tuples
55
+ # """
56
+ #
57
+ # def __init__(self, clients, OPERATION_MODE='wait_all', **kwargs):
58
+ # self.clients = self.parse_clients(clients)
59
+ # self.n_clients = len(clients)
60
+ # self.OPERATION_MODE = OPERATION_MODE
61
+ # logging.info(
62
+ # '[Client Handler] Operation mode: {}'.format(self.OPERATION_MODE))
63
+ # default_n_firsts = max(1, self.n_clients - 2)
64
+ # if self.OPERATION_MODE == 'n_firsts':
65
+ # self.N_FIRSTS = kwargs.get('n_firsts', default_n_firsts)
66
+ # assert self.N_FIRSTS <= self.n_clients, \
67
+ # 'n_firsts must be <= than num clients'
68
+ # logging.info(
69
+ # '[Client Handler] n_firsts: {}'.format(self.N_FIRSTS))
70
+ # elif self.OPERATION_MODE == 'timeout':
71
+ # self.WAIT_FROM_N_FIRSTS = kwargs.get('wait_from_n_firsts',
72
+ # default_n_firsts)
73
+ # self.TIMEOUT = kwargs.get('timoeut', 60) # Seconds
74
+ # elif self.OPERATION_MODE == 'wait_all':
75
+ # self.N_FIRSTS = self.n_clients
76
+ # logging.info('[Client Handler] Will wait '
77
+ # 'until {} clients'.format(self.N_FIRSTS))
78
+ # else:
79
+ # raise Exception('Operation mode not accepted')
80
+ # self.manager = Manager()
81
+ # self.lock = Lock()
82
+ # self.last_operation = self.manager.dict()
83
+ # self.reset_last_operation()
84
+ # self.processes = []
85
+ #
86
+ # def perform_requests_and_wait(self, endpoint):
87
+ # self.perform_parallel_requests(endpoint)
88
+ # if self.OPERATION_MODE == 'n_firsts':
89
+ # if endpoint == 'send_model':
90
+ # # TODO: Do this part with redundancy
91
+ # return self.wait_until('n_responses', wait_all=True)
92
+ # return self.wait_until('n_responses')
93
+ # elif self.OPERATION_MODE == 'timeout':
94
+ # self.started = time()
95
+ # return self.wait_until('timeout')
96
+ # elif self.OPERATION_MODE == 'wait_all':
97
+ # return self.wait_until('n_responses', wait_all=True)
98
+ #
99
+ # def reset_last_operation(self):
100
+ # self.lock.acquire()
101
+ # for key in self.clients:
102
+ # self.last_operation[key] = None
103
+ # self.lock.release()
104
+ #
105
+ # @staticmethod
106
+ # def parse_clients(clients):
107
+ # p_clients = []
108
+ # for cl in clients:
109
+ # host = cl[list(cl.keys())[0]]['host']
110
+ # port = cl[list(cl.keys())[0]]['port']
111
+ # p_clients.append((host, port))
112
+ # return p_clients
113
+ #
114
+ # def perform_parallel_requests(self, endpoint):
115
+ # self.reset_last_operation()
116
+ # for host, port in self.clients:
117
+ # p = Process(target=self.perform_request,
118
+ # args=(host, port, endpoint))
119
+ # p.start()
120
+ # self.processes.append(p)
121
+ #
122
+ # def wait_until(self, until_cond, wait_all=False):
123
+ # # TODO: What to do in send model?
124
+ # ended_clients = set()
125
+ # completed = False
126
+ # while not completed:
127
+ # # Periodically check if the requests are ending
128
+ # for key in self.clients:
129
+ # last_operation = self.last_operation[key]
130
+ # if not last_operation or key in ended_clients:
131
+ # # Last operation still not computed or already finished
132
+ # continue
133
+ # elif last_operation['ended']:
134
+ # # TODO: Handle exception when status code != 200
135
+ # if last_operation['response'].status_code != 200:
136
+ # raise Exception(
137
+ # 'Error in response. Error code: {}'.format(
138
+ # last_operation['response'].text))
139
+ # logging.info(
140
+ # '[Client Handler] client {} '
141
+ # 'finished performing operation {}'.format(
142
+ # key, last_operation['op']
143
+ # )
144
+ # )
145
+ # ended_clients.add(key)
146
+ # if until_cond == 'n_responses':
147
+ # if ((not wait_all and (len(ended_clients) >= self.N_FIRSTS))
148
+ # or (wait_all and len(ended_clients) == self.N_FIRSTS)):
149
+ # completed = True
150
+ # elif until_cond == 'timeout':
151
+ # elapsed = time() - self.started
152
+ # if ((len(ended_clients) >= self.WAIT_FROM_N_FIRSTS) and
153
+ # elapsed > self.TIMEOUT):
154
+ # completed = True
155
+ # else:
156
+ # raise Exception('Not implemented')
157
+ # sleep(0.2)
158
+ # self.terminate_processes()
159
+ # return list(ended_clients)
160
+ #
161
+ # def terminate_processes(self):
162
+ # for p in self.processes:
163
+ # p.terminate()
164
+ # self.processes = []
165
+ #
166
+ # @staticmethod
167
+ # def get_client_key(host, port):
168
+ # return (host, port)
169
+ #
170
+ # def perform_request(self, host, port, endpoint):
171
+ # client_key = self.get_client_key(host, port)
172
+ # last_operation = {
173
+ # 'started': time(),
174
+ # 'op': endpoint,
175
+ # 'status': 'started',
176
+ # 'ended': None
177
+ # }
178
+ # url = 'http://{}:{}/{}'.format(host, port, endpoint)
179
+ # res = requests.get(url)
180
+ # last_operation.update({'status': 'ended',
181
+ # 'ended': time(),
182
+ # 'response': res})
183
+ # self.lock.acquire()
184
+ # self.last_operation[client_key] = last_operation
185
+ # self.lock.release()
186
+ #
0 commit comments