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

Add support for cancellation of a problem or request in each solver

parent ffd55d63
Loading
Loading
Loading
Loading
+6 −0
Changes for roles/host.py: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -147,6 +147,9 @@ class Host(object):
        elif cmd == 'stop':
            self.worker_manager.request_stop()
            return {}
        elif cmd == 'cancel':
            self.worker_manager.request_cancel(params)
            return {'status': 'canceled'}
        elif cmd == 'worker/status':
            self.worker_manager.update_status(params['address'], params['status'])
            return {'status': 'updated'}
@@ -233,6 +236,9 @@ class WorkerManager(object):
    def request_stop(self):
        self.broadcast('stop', {})
    
    def request_cancel(self, params):
        self.broadcast('cancel', params)

    def broadcast(self, cmd, params, solvers=None):

        threads = []
+31 −8
Changes for roles/solver.py: 31 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -19,9 +19,10 @@ class Solver(object):
        self.solver = importlib.import_module(f"solvers.{config['solver']}")
        self.queue = OrderedDict()

        self.solving = None

        self.status = None

        # self.thread = None
        self.thread = threading.Thread(name='solver', target=self.solver_thread, daemon=True)
        self.thread.start()

@@ -43,14 +44,15 @@ class Solver(object):
            if len(self.queue) > 0:
                print("I: Solver started")
                _, params = self.queue.popitem(last=False)
                # self.status = f'Running ({len(self.queue)} in queue)'
                self.solving = params
                self.set_status(f'Running ({len(self.queue)} in queue)')
                try:
                    self.solve(params)
                # self.status = 'Ready'
                except Exception as e:
                    print("E: An error has occurred in the solver thread")
                self.solving = None
                self.set_status('Ready')
            else:
                # self.status = 'Ready'
                self.set_status('Ready')
                time.sleep(0.5)
    
    def solve(self, params):
@@ -65,7 +67,7 @@ class Solver(object):
            solution['elapsed_time'] = elapsed_time

        self.submit_solution(params, solution)
        # self.thread = None

        return True
    
    def post(self, path, data):
@@ -94,17 +96,36 @@ class Solver(object):
        print("I: Problem queued")
        _id = params['request_id']
        self.queue[_id] = params
        # self.status = f'Running ({len(self.queue)} in queue)'
        self.set_status(f'Running ({len(self.queue)} in queue)')
        return {'status': self.status}
        
    def stop_solver(self):

        if self.thread is not None:
        # if self.thread is not None:
        #     self.solver.stop()
        self.solver.stop()
        
        return {'status': self.status}
    
    def cancel_queue(self, params):

        if 'request_id' in params:
            request_id = params['request']
            for k, v in self.queue.items():
                if k == request_id:
                    self.queue.pop(k, None)
            if self.solving['request_id'] == request_id:
                self.solver.stop()()
        elif 'problem' in params:
            problem_name = params['problem']
            for k, v in self.queue.items():
                if v['name'] == problem_name:
                    self.queue.pop(k, None)
            if self.solving['name'] == problem_name:
                self.solver.stop()()

        return {'status': 'canceled'}

    def call_api(self, method, cmd, params):
        if cmd == 'role':
            return {'role': self.type}
@@ -112,6 +133,8 @@ class Solver(object):
            return self.start_solver(params)
        elif cmd == 'stop':
            return self.stop_solver()
        elif cmd == 'cancel':
            return self.cancel_queue(params)
        elif cmd == 'status':
            return {'status': self.status}
        else:
+26 −0
Changes for static/js/adc2019.js: 26 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@ class StatusView {
                _this.start_solver();
            });
            
            _this.container.find('.cancel-button').click(()=>{
                _this.cancel_problem();
            });
            
            _this.container.find('.save-button').click(()=>{
                _this.save_solution();
                _this.fire('refresh');
@@ -112,6 +116,28 @@ class StatusView {
        });
    }
    
    cancel_problem(){
        var _this = this;

        var _button = _this.container.find('.cancel-button')
        _button.html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span><span class="sr-only">Loading...</span>');
        _button.prop('disabled', 'disabled');

        $.ajax({
            type: "POST",
            dataType: "json",
            url: "/api/cancel",
            data: JSON.stringify({
                "problem": _this.problem_key,
            }),
            contentType: 'application/json'
        }).done((d) => {
            _button.prop('disabled', false);
            _button.text('Cancel');
            console.log(d);
        });
    }
    
    // 強制停止
    stop_solver(){
        var _this = this;
+2 −2
Changes for templates/part_problem_status.html: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
<div>
    <h4 class='inline-heading' id='problem-status-title'>{{problem.name}}</h4>
    <a href="/viewer#{{problem.name}}" target="_blank">Viewer</a>
    {#% # if localmode %#}
    <button class="btn btn-primary btn-lg start-button" type="button" data-qname="{{problem.name}}">Start</button>
    <!-- <button class="btn btn-danger btn-lg stop-button" type="button" data-qname="all">Stop</button> -->
    <button class="btn btn-danger btn-lg cancel-button" type="button" data-qname="{{problem.name}}">Cancel</button>
    <button class="btn btn-info btn-lg save-button" type="button" data-qname="{{problem.name}}">Save</button>
    <button class="btn btn-success btn-lg submit-button" type="button" data-qname="{{problem.name}}">Up</button>
    {#% else %#}
    <!-- [View Only] -->
    <a class="btn btn-outline-success btn-lg" href="/viewer#{{problem.name}}" role="button" target='_blank'>Viewer</a>
    {#% endif %#}
</div>