class DraftInterface(ABC): pick_type: t.Type[Pick] passing_to: DraftInterface class ConnectionException(Exception): pass def __init__(self, drafter: Drafter, draft: Draft, draft_seat: DraftSeat): super().__init__() self._drafter = drafter self._draft = draft self._draft_seat = draft_seat self._pool = Cube() self._messages: t.List[t.Mapping[str, t.Any]] = [] self._pick_counter = 0 self._booster_queue = Queue() self._pick_queue = Queue() self._out_queue = Queue() self._current_booster: t.Optional[DraftBooster] = None self._terminating = threading.Event() self._booster_pusher = threading.Thread(target=self._draft_loop) self._connect_lock = threading.Lock() self._consumer: t.Optional[WebsocketConsumer] = None @property def messages(self) -> t.List[t.Mapping[str, t.Any]]: return self._messages @property def pool(self) -> Cube: return self._pool def connect(self, consumer: WebsocketConsumer) -> None: with self._connect_lock: if self._consumer is not None: raise self.ConnectionException('already connected') self._consumer = consumer def disconnect(self) -> None: with self._connect_lock: if self._consumer is None: raise self.ConnectionException('no consumer connected') self._consumer = None def send_message(self, message_type: str, **kwargs) -> None: self.out_queue.put({ 'type': message_type, **kwargs, }) def send_error(self, error_type: str, **kwargs): self.send_message('error', error_type=error_type, **kwargs) @property def booster_queue(self) -> Queue[DraftBooster]: return self._booster_queue @property def booster_amount(self) -> int: return self._booster_queue.qsize() + (1 if self._current_booster else 0) def give_booster(self, booster: DraftBooster) -> None: self._booster_queue.put(booster) self._draft.broadcast_message( 'booster_amount_update', drafter=self._drafter.user.pk, queue_size=self.booster_amount, ) @property def pick_queue(self) -> Queue[Cubeable]: return self._pick_queue @property def out_queue(self): return self._out_queue def receive_message(self, message: t.Any) -> None: message_type = message.get('type') if message_type == 'pick': pick = message.get('pick') if pick is None: self.send_error('empty_pick') return try: pick = RawStrategy(db).deserialize(self.pick_type, pick) except SerializationException: self.send_error('misconstrued_pick') return self._pick_queue.put(pick) else: self.send_error('unknown_message_type', message_type=message_type) def start(self) -> None: self.send_message( 'started', **self._draft.serialize(), ) self._booster_pusher.start() def stop(self) -> None: self._terminating.set() @abstractmethod def perform_pick(self, pick: Pick) -> bool: pass def _draft_loop(self) -> None: while not self._terminating.is_set(): try: booster = self._booster_queue.get(timeout=2) except Empty: continue self._current_booster = booster self.send_message('booster', booster=RawStrategy.serialize( self._current_booster)) while not self._terminating.is_set(): try: pick = self._pick_queue.get(timeout=2) except Empty: continue if not self.perform_pick(pick): self.send_error( 'invalid_pick', pick=pick.serialize(), ) continue self._pick_counter += 1 self.send_message( 'pick', pick=pick.serialize(), booster=RawStrategy.serialize(self._current_booster), pick_number=self._pick_counter, ) DraftPick.objects.create( seat=self._draft_seat, pack_number=self._draft.pack_counter, pick_number=self._current_booster.pick_number, global_pick_number=self._pick_counter - 1, pack=self._current_booster, pick=pick, ) self._current_booster.pick_number += 1 if self._current_booster.cubeables: self.passing_to.give_booster(self._current_booster) else: self._draft.booster_empty(self._current_booster) self._current_booster = None self._draft.broadcast_message( 'booster_amount_update', drafter=self._drafter.user.pk, queue_size=self.booster_amount, ) break
def _run_uploader(input_queue, saver_list, saver_config): uploader = ImageUploader(input_queue, saver_list, saver_config) uploader.run() def start_uploader(input_queue): assert isinstance(input_queue, Queue), "Start Saver error: queue is invalid" saver_list = SAVER_LIST saver_config = SAVER_CONFIG process_num = SAVER_CONFIG["process"] for _ in range(process_num): p = Process(target=_run_uploader, args=(input_queue, saver_list, saver_config)) p.start() if __name__ == "__main__": task_queue = Queue(size=1000) picture_queue = Queue(size=1000) upload_queue = Queue(size=1000) tasks = [TaskInfo("phrasepicture"), TaskInfo("wordpicture"), TaskInfo("iconpicture"), TaskInfo("ninepicture")] for task in tasks: task.set_num(100000) task_queue.put(task) start_builder(task_queue, picture_queue) start_transformer(picture_queue, upload_queue) start_uploader(upload_queue)