Commit a4d7fc10 authored by Kento HASEGAWA's avatar Kento HASEGAWA
Browse files

Update the request view and its backend process

parent 4b5c132c
Loading
Loading
Loading
Loading
+84 −50
Changes for roles/host.py: 84 added lines, 50 removed lines.
Original line number Diff line number Diff line
@@ -54,16 +54,24 @@ class Host(object):
        if problem is None:
            return {'status': 'key error'}
        else:
            request = Request(self.worker_manager, problem.get_dict(), solvers=solvers)
            # request = Request(self.worker_manager, problem.get_dict(), solvers=solvers)
            if solvers is None:
                _solvers = self.worker_manager.get_workers()
            else:
                _solvers = dict()
                for k, v in self.worker_manager.get_workers().items():
                    if k in solvers:
                        _solvers[k] = v
            for _, v in _solvers.items():
                request = Request(self.worker_manager, problem.get_dict(), v)
                request.broadcast()

                request_id = request.get_id()
                self.request[request_id] = request
                self.problem_to_request[problem_key].append(request_id)

            request.broadcast()
            return {
                'status': 'processed',
                'request_id': request_id,
                'timeout': request.timeout
                }

    def get_problems(self):
@@ -82,6 +90,10 @@ class Host(object):
                return {'status': 'ignored'}
            problem_key = solution['problem']
            
            request_id = solution['request_id']
            if request_id in self.request:
                self.request[request_id].store_response(solution)

            if problem_key in self.problems:
                res = self.problems[problem_key].put_partial_solution(solution)
            else:
@@ -308,6 +320,11 @@ class Worker(object):
        self.name = params['name']
        self.host = params['host']
        self.role = params['role']
        
        if not 'partial_mode' in params:
            self.partial_mode = False
        else:
            self.partial_mode = params['partial_mode']
        self.params = params
        self.status = 'Ready'

@@ -339,23 +356,33 @@ class Worker(object):

class Request(object):

    def __init__(self, worker_manager, data, timeout=10000, solvers=None):
        self.worker_manager = worker_manager
    def __init__(self, worker_manager, data, worker, timeout=10000):
        # self.worker_manager = worker_manager

        self.data = data
        self.timeout = timeout
    
        self.request_id = time.time()
        self.broadcast_time = None
        self.request_time = None
        self.done_time = None

        if solvers is None:
            self.solvers = list(self.worker_manager.get_workers().keys())
        else:
            self.solvers = solvers
        # if solvers is None:
        #     self.solvers = list(self.worker_manager.get_workers().keys())
        # else:
        #     self.solvers = solvers
        self.solver = worker

        self.response = dict()
        for w in self.solvers:
            self.response[w] = list()
        # for w in self.solvers:
            # self.response[w] = list()
        self.response = list()

        if self.solver.partial_mode:
            self.part_nums = len(data['group_problems'])
            self.solved = [0 for v in range(self.part_nums + 1)]
        else:
            self.part_nums = 1
            self.solved = [0]

    @property
    def request_data(self):
@@ -371,55 +398,62 @@ class Request(object):
        return self.request_data
    
    def store_response(self, data):
        worker = data['worker']
        self.response[worker].append(data)
        # worker = data['worker']
        # self.response[worker].append(data)
        # self.response[worker] = data
        self.response.append(data)
        print(data)
        if 'part_id' in data:
            idx = data['part_id']
            print(idx)
            if data['status'] == 'done':
                self.solved[idx] += 1
        else:
            self.solved[-1] = 1
            self.done_time = time.time()

    def get_status(self):
        worker_count = 0
        response_count = 0
        for v in self.solvers:
            worker_count += 1
            if v in self.response:
                response_count += 1

        status = ''
        if worker_count == response_count:
            status = 'done'
        # elif time.time() - self.broadcast_time > self.timeout:
        #     status = 'timeout'
        else:
            elapsed_time = time.time() - self.broadcast_time

        if self.solved[-1] == 1:
            elapsed_time = self.done_time - self.request_time
            et_minutes = int(elapsed_time // 60)
            et_seconds = int(elapsed_time % 60)
            # status = 'processing'
            status = f'{et_minutes}:{et_seconds:02}'
        
        if self.broadcast_time is None:
            progress = 0,
        else:
            progress_problem =  response_count / worker_count * 100
            progress_time = (time.time() - self.broadcast_time) / self.timeout * 100
            progress = min(100, max(progress_problem, progress_time))
        
        worker_status = dict()
        for v in self.solvers:
            if v in self.response and len(self.response[v]) > 0:
                worker_status[v] = self.response[v][0]['status']
            status = f'done ({self.solved[-1]}) [{et_minutes}:{et_seconds:02}]'
        elif self.solved[-1] == -1:
            status = 'failed'
        else:
                if self.worker_manager.workers[v].status == 'Not connected':
                    worker_status[v] = 'Not connected'
            if self.solver.status == 'Not connected':
                status = 'Not connected'
            else:
                    worker_status[v] = 'Waiting for response'
                if len(self.solved) == 1:
                    status_mes = 'Waiting for response'
                elif len(self.solved) > 1:
                    counter = sum([v>0 for v in self.solved])
                    status_mes = f'{counter}/{len(self.solved)}'

                elapsed_time = time.time() - self.request_time
                et_minutes = int(elapsed_time // 60)
                et_seconds = int(elapsed_time % 60)
                elapsed_time_str = f'{et_minutes}:{et_seconds:02}'

                status = f'{status_mes} [{elapsed_time_str}]'

        return {
            'status': status,
            'workers': worker_count,
            'solutions': response_count,
            'progress': progress,
            'worker_status': worker_status
            'worker': self.solver.address,
            # 'solutions': response_count,
            # 'progress': progress,
            # 'worker_status': worker_status
            }

    def broadcast(self):
        self.worker_manager.broadcast('solve', self.request_data, solvers=self.solvers)
        self.broadcast_time = time.time()
        
        def _sender():
            self.solver.post('solve', self.request_data)

        _th = threading.Thread(name=f'request_sender_{self.solver.address}', target=_sender, daemon=True)
        _th.start()

        self.request_time = time.time()
+3 −0
Changes for roles/solver.py: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -82,6 +82,9 @@ class Solver(object):
                solution['block_map'] = gblock_map

                self.submit_solution(data, solution)

                if self.solver.stop_flag:
                    break
        else:
            start_time = time.time()
            solution = self.solver.solve(params)
+2 −1
Changes for static/js/adc2019.js: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ class StatusView {
            }),
            contentType: 'application/json'
        }).done((d) => {
            var request_id = d['request_id'];
            console.log(d);
            // var request_id = d['request_id'];
            // var timeout = d['timeout'];

            // _this.container.find('#solver-processing-modal').modal({
+3 −10
Changes for templates/part_request_status.html: 3 added lines, 10 removed lines.
Original line number Diff line number Diff line
<div>
    {% for r in status %}
    <p>処理結果:<span id='request-status-value'>{{r.status}}</span></p>
    <table class="table table-bordered table-sm">
        <!-- <tr>
            <th>Worker (Solver)</th>
            <th>Status</th>
        </tr> -->
        <tbody>
            {% for k, v in r['worker_status'].items() %}
            {% for r in status %}
            <tr>
                <td>{{k}}</td>
                <td>{{v}}</td>
                <td>{{r['worker']}}</td>
                <td>{{r['status']}}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% endfor %}
</div>