def stop(self) -> None:

        self.thumbnailer_controller.send_multipart(create_inproc_msg(b'STOP'))
        self.load_balancer_controller.send_multipart(
            create_inproc_msg(b'STOP'))
        self.thumbnail_manager_thread.quit()
        if not self.thumbnail_manager_thread.wait(1000):
            self.thumbnailer_controller.send_multipart(
                create_inproc_msg(b'TERMINATE'))
        self.load_balancer_thread.quit()
        if not self.load_balancer_thread.wait(1000):
            self.load_balancer_controller.send_multipart(
                create_inproc_msg(b'TERMINATE'))
    def generateThumbnails(
            self,
            scan_id: int,
            rpd_files: list,
            name: str,
            proximity_seconds: int,
            cache_dirs: CacheDirs,
            need_photo_cache_dir: bool,
            need_video_cache_dir: bool,
            camera_model: Optional[str] == None,
            camera_port: Optional[str] = None,
            entire_video_required: Optional[bool] = None,
            entire_photo_required: Optional[bool] = None) -> None:
        """
        Initiates thumbnail generation.

        :param scan_id: worker id of the scan
        :param rpd_files: list of rpd_files, all of which should be
         from the same source
        :param name: name of the device
        :param proximity_seconds: the time elapsed between consecutive
         shots that is used to prioritize the order of thumbnail
         generation
        :param cache_dirs: the location where the cache directories
         should be created
        :param need_photo_cache_dir: if True, must use cache dir
         to extract photo thumbnail
        :param need_video_cache_dir: if True, must use cache dir
         to extract video thumbnail
        :param camera_model: If the thumbnails are being downloaded
         from a camera, this is the name of the camera, else None
        :param camera_port: If the thumbnails are being downloaded
         from a camera, this is the port of the camera, else None,
        :param entire_video_required: if the entire video is required
         to extract the thumbnail
        :param entire_photo_required: if the entire photo is required
         to extract the thumbnail
         """
        self.thumbnailer_controller.send_multipart(
            create_inproc_msg(
                b'START_WORKER',
                worker_id=scan_id,
                data=GenerateThumbnailsArguments(
                    scan_id=scan_id,
                    rpd_files=rpd_files,
                    name=name,
                    proximity_seconds=proximity_seconds,
                    cache_dirs=cache_dirs,
                    need_photo_cache_dir=need_photo_cache_dir,
                    need_video_cache_dir=need_video_cache_dir,
                    frontend_port=self._frontend_port,
                    log_gphoto2=self.log_gphoto2,
                    camera=camera_model,
                    port=camera_port,
                    entire_video_required=entire_video_required,
                    entire_photo_required=entire_photo_required)))
 def stop_worker(self, scan_id: int) -> None:
     self.thumbnailer_controller.send_multipart(
         create_inproc_msg(b'STOP_WORKER', worker_id=scan_id))