예제 #1
0
파일: draft.py 프로젝트: guldfisk/cubeapp
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
예제 #2
0
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)