import importlib import json import os import requests import sys import time import threading class StoppableThread(threading.Thread): def __init__(self, target, args=()): super(StoppableThread, self).__init__(target=target, args=args) self._status = 'running' def stop(self): if self._status == 'running': self._status = 'stopping' def stopped(self): self._status = 'stopped' def is_running(self): return (self._status == 'running') def is_stopping(self): return (self._status == 'stopping') def is_stopped(self): return (self._status == 'stopped') class Solver(object): def __init__(self, config): self.type = 'solver' self.host = config['host'] self.address = config['address'] self.name = config['name'] self.solver = importlib.import_module(f"solvers.{config['solver']}") self.thread = None def __repr__(self): return "Solver" def solve(self, params): start_time = time.time() solution = self.solver.solve(params) end_time = time.time() self.thread.stopped() elapsed_time = end_time - start_time if not 'elapsed_time' in solution: solution['elapsed_time'] = elapsed_time self.submit_solution(params, solution) self.thread = None return True def post(self, path, data): response = requests.post( f'http://{self.host}/api/{path}', json.dumps(data), headers={'Content-Type': 'application/json'}) print(f"I: Post to {self.host}, API Cmd: {path}") return response def submit_solution(self, params, solution): data = { 'request_id': params['request_id'], 'problem': params['name'], 'worker': self.address } data.update(solution) self.post('problem/solution', data) def start_solver(self, params): if self.thread is None: print("I: Solver started") self.thread = StoppableThread(target=self.solve, args=(params, )) self.thread.start() return {'status': 'started'} else: return {'status': 'busy'} def stop_solver(): if self.thread is not None: if self.thread.is_running(): self.thread.stop() self.thread.join() self.thread = None def call_api(self, method, cmd, params): if cmd == 'role': return {'role': self.type} elif cmd == 'solve': return self.start_solver(params) else: return None