示例#1
0
    def __init__(self,
                 loop: AbstractEventLoop = None,
                 session: ClientSession = None) -> None:
        """Start the discovery protocol using the supplied loop.

        raises:
            RuntimeError: If attempted to start the protocol when it is
                          already running.
        """
        self._controllers = {}  # type: Dict[str, Controller]
        self._disconnected = set()  # type: Set[str]
        self._listeners = []  # type: List[Listener]
        self._close_task = None  # type: Optional[Task]

        _LOG.info("Starting discovery protocol")
        if not loop:
            if session:
                self.loop = session.loop
            else:
                self.loop = asyncio.get_event_loop()
        else:
            self.loop = loop

        self.session = session
        self._own_session = session is None

        self._transport = None  # type: Optional[DatagramTransport]

        self._scan_condition = Condition(loop=self.loop)  # type: Condition

        self._tasks = []  # type: List[Future]
示例#2
0
文件: pool.py 项目: dbrojas/asynch
    def __init__(self,
                 minsize: int = 1,
                 maxsize: int = 10,
                 loop=None,
                 **kwargs):
        self._maxsize = maxsize
        self._minsize = minsize
        self._connection_kwargs = kwargs
        self._terminated: Set[Connection] = set()
        self._used: Set[Connection] = set()
        self._cond = Condition()
        self._closing = False
        self._closed = False
        self._free: Deque[Connection] = collections.deque(maxlen=maxsize)
        self._loop = loop

        if maxsize <= 0:
            raise ValueError("maxsize is expected to be greater than zero")

        if minsize < 0:
            raise ValueError(
                "minsize is expected to be greater or equal to zero")

        if minsize > maxsize:
            raise ValueError("minsize is greater than max_size")
示例#3
0
    def __init__(self, discovery, device_uid: str, device_ip: str) -> None:
        """Create a controller interface. Usually this is called from the discovery service.

        If neither device UID or address are specified, will search network
        for exactly one controller. If UID is specified then the addr is ignored.

        Args:
            device_uid: Controller UId as a string (eg: mine is '000013170')
                If specified, will search the network for a matching device
            device_addr: Device network address. Usually specified as IP address

        Raises:
            ConnectionAbortedError: If id is not set and more than one iZone instance is
                discovered on the network.
            ConnectionRefusedError: If no iZone discovered, or no iZone device discovered at
                the given IP address or UId
        """
        self._ip = device_ip
        self._discovery = discovery
        self._device_uid = device_uid

        self.zones: List[Zone] = []
        self.fan_modes: List[Controller.Fan] = []
        self._system_settings: Controller.ControllerData = {}

        self._fail_exception = None
        self._reconnect_condition = Condition()

        self._sending_lock = Lock()
        """Create a session for sending commands
        iZone controller doesnt like sessions being kept alive, so disabled"""
        self._session = requests.session()
        self._session.keep_alive = False
示例#4
0
async def fire_event(condition: Condition):
    while True:
        await asyncio.sleep(5)
        print('About to notify, acquiring condition lock...')
        async with condition:
            print('Lock acquired, notifying all workers.')
            condition.notify_all()
        print('Notification finished, releasing lock.')
示例#5
0
 def __init__(self, client, stdscr):
     self.stdscr = stdscr
     self.client = client
     self.inputevent = Condition()
     self.inputs = ""
     self.w, self.h = curses.COLS, curses.LINES
     self.fin = False
     self.showinput = True
示例#6
0
    def __init__(self, client, stdscr):
        self.stdscr = stdscr
        self.client = client
        self.inputevent = Condition()
        self.client.add_event_handler(self.on_message, events.NewMessage)
        self.client.add_event_handler(self.on_user_update, events.UserUpdate)
        # TODO
        # self.client.add_event_handler(self.on_read, events.MessageRead)
        self.text_emojis = True

        self.macros = {}
        self.macro_recording = None
        self.macro_sequence = []

        self.popup_input = None
        self.last_saved_location = "/tmp/tttc/"

        # the offset which messages are being displayed.
        # the number corresponds to the lowest message shown on screen as the messages are drawing upwards
        self.message_offset = 0

        self.tab_selection = 0

        self.inputs = ""
        self.inputs_cursor = 0

        self.edit_message = None

        self.popup = None

        self.drawtool = drawtool.Drawtool(self)
        self.fin = False
        from config import colors as colorconfig
        self.colors = colorconfig.get_colors()
        self.ready = False

        self.search_result = None
        self.search_index = None
        self.search_box = ""
        self.vimline_box = ""
        self.command_box = ""

        self._dialogs = []
        self._dialogs_updated = False
        self.num_pinned = 0

        # index corresponds to the index in self.dialogs
        self.selected_chat = 0
        # index offset
        self.selected_chat_offset = 0
            
        self.modestack = ["normal"]

        self.key_handler = KeyHandler(self)

        self.forward_messages = []
示例#7
0
 def __init__(self,
              amqp_target,
              route_key,
              username=None,
              password=None,
              **task_kwargs):
     super().__init__(amqp_target, route_key, username, password,
                      **task_kwargs)
     self._task._citizen_condition_new_block = Condition(loop=self.loop)
     self._task._citizen_condition_unregister = Condition(loop=self.loop)
 def __init__(
         self,
         token,  # type: str
         token_refresher=None):
     # type: (str) -> None
     if not isinstance(token, six.string_types):
         raise TypeError("token must be a string.")
     self._token = create_access_token(token)
     self._token_refresher = token_refresher
     self._lock = Condition(Lock())
     self._some_thread_refreshing = False
 def __init__(self,
              token,  # type: str
              **kwargs
              ):
     token_refresher = kwargs.pop('token_refresher', None)
     communication_token_refresh_options = CommunicationTokenRefreshOptions(token=token,
                                                                            token_refresher=token_refresher)
     self._token = communication_token_refresh_options.get_token()
     self._token_refresher = communication_token_refresh_options.get_token_refresher()
     self._lock = Condition(Lock())
     self._some_thread_refreshing = False
示例#10
0
async def wait_condition_or_timeout(condition: asyncio.Condition,
                                    timeout: float) -> None:
    """Wait for a condition or timeout."""
    loop = asyncio.get_event_loop()
    future = loop.create_future()

    def _handle_timeout() -> None:
        if not future.done():
            future.set_result(None)

    timer_handle = loop.call_later(timeout, _handle_timeout)
    condition_wait = loop.create_task(condition.wait())

    def _handle_wait_complete(_: asyncio.Task) -> None:
        if not future.done():
            future.set_result(None)

    condition_wait.add_done_callback(_handle_wait_complete)

    try:
        await future
    finally:
        timer_handle.cancel()
        if not condition_wait.done():
            condition_wait.cancel()
        with contextlib.suppress(asyncio.CancelledError):
            await condition_wait
示例#11
0
def main_condition():
    """有三个协程,但一时间之允许有一个协程http请求,且保证最先发起http请求的是flag为2的协程"""
    """
        acquire() 获取原始锁
        release() 释放原始锁
        notify(n=1) 唤醒正在wait的n个协程,并释放原始锁
        locked() 原始锁是否已经被获取,如果已经别获取 return True
        notify_all() 唤醒所有正在wait的协程,不释放原始锁
        COROUTINE wait() 释放原始锁,并挂起当前协程
    """
    loop = asyncio.get_event_loop()
    print('loop start time:{}'.format(loop.time()))
    condition = Condition()  # 获取一个Condition对象

    async def test(loop, condition, flag):
        await condition.acquire()  # 获取原始锁
        if flag != 2:  # 让flag为2的协程,先进行http请求
            await condition.wait()  # 释放原始锁,等待被唤醒

        async with aiohttp.ClientSession() as session:
            html = await fetch(session, 'http://github.com/kagxin')
            print("html len:{}, flag:{}, loop time:{}".format(
                len(html), flag, loop.time()))

        condition.notify(n=1)  # 通知激活另外一个协程
        condition.release()  # 释放原始锁

    pt = functools.partial(test, loop, condition)
    gs = asyncio.gather(*map(pt, range(3)))
    try:
        loop.run_until_complete(gs)
    finally:
        loop.close()
    """
示例#12
0
 async def asend(self, value: OpT) -> OpT:
     if self._stopped: raise StopAsyncIteration
     if self._ac is None: self._ac = ACondition()
     if value is None:
         async with self._ac:
             if len(self._rl) == 0:
                 try:
                     if self._basegen:
                         yv = await self._base.asend(None)
                     else:
                         yv = await self._base.__anext__()
                     self._yl.append(yv)
                     return yv
                 except (Exception, GeneratorExit) as exc:
                     self._stopped = True
                     self._ac.notify_all()
                     raise StopAsyncIteration from exc
             else:
                 yv = self._rl.popleft()
                 self._yl.append(yv)
                 return yv
     else:
         async with self._ac:
             if value in self._yl:
                 self._yl.remove(value)
                 self._rl.append(value)
示例#13
0
文件: discovery.py 项目: gavc1/pizone
    def __init__(self,
                 loop: AbstractEventLoop = None,
                 session: ClientSession = None) -> None:
        """Start the discovery protocol using the supplied loop.
        raises:
            RuntimeError: If attempted to start the protocol when it is already running.
        """
        self._controllers: Dict[str, Controller] = {}
        self._listeners: List[Listener] = []
        self._closing = False

        _LOG.info("Starting discovery protocol")
        if not loop:
            if session:
                self.loop = session.loop
            else:
                self.loop = asyncio.get_event_loop()
        else:
            self.loop = loop

        if not session:
            self.session = ClientSession(loop=self.loop)
            self._own_session = True
        else:
            assert session.loop is loop, "Passed client session does not share the same loop"
            self.session = session
            self._own_session = False

        self._transport: Optional[DatagramTransport] = None

        self._scan_condition: Condition = Condition(loop=self.loop)

        self._tasks: List[Future] = []
示例#14
0
async def async_request(nvim: Nvim,
                        lines_around: int) -> Optional[_Payload[Payload]]:
    global _COND, _SESSION
    _COND = _COND or Condition()

    with timeit("TS"):
        uid = next(_UIDS)
        _SESSION = _Session(uid=uid, done=False, payload=_NIL_P)

        async with _COND:
            _COND.notify_all()

        def cont() -> None:
            nvim.api.exec_lua(f"{NAMESPACE}.ts_req(...)", (uid, lines_around))

        await async_call(nvim, cont)

        while True:
            if _SESSION.uid == uid and _SESSION.done:
                return _vaildate(_SESSION.payload)

            elif _SESSION.uid > uid:
                return None

            else:
                async with _COND:
                    await _COND.wait()
示例#15
0
文件: __init__.py 项目: linuseing/hub
    def __init__(self, core: "Core", config: Dict):
        self.core = core
        self.config = config

        self.in_queue = asyncio.queues.Queue(loop=core.event_loop)
        self.out_queue = asyncio.queues.Queue(maxsize=10, loop=core.event_loop)

        self._reader: Optional[StreamReader] = None
        self._writer: Optional[StreamWriter] = None

        self._route = []

        self.volume = 0

        self._command_lock = Condition(loop=core.event_loop)

        self._responses: Dict[str, Optional[Callable]] = {
            "51:00:44:01": None,  # cannot execute at the current time (AV)
            "51:7a": self.set_volume,  # get volume response
        }

        self._target = None

        self._manager: Optional[Task] = None

        self._close_event = asyncio.Event(loop=core.event_loop)
        self._closed_event = asyncio.Event(loop=core.event_loop)
示例#16
0
    def __init__(
        self,
        player_configuration: PlayerConfiguration,
        *,
        avatar: Optional[int] = None,
        battle_format: str,
        log_level: Optional[int] = None,
        max_concurrent_battles: int = 1,
        server_configuration: ServerConfiguration,
        start_listening: bool = True,
        team: Optional[Union[str, Teambuilder]] = None,
    ) -> None:
        """
        :param player_configuration: Player configuration.
        :type player_configuration: PlayerConfiguration
        :param avatar: Player avatar id. Optional.
        :type avatar: int, optional
        :param battle_format: Name of the battle format this player plays.
        :type battle_format: str
        :param log_level: The player's logger level.
        :type log_level: int. Defaults to logging's default level.
        :param max_concurrent_battles: Maximum number of battles this player will play
            concurrently. If 0, no limit will be applied. Defaults to 1.
        :type max_concurrent_battles: int
        :param server_configuration: Server configuration.
        :type server_configuration: ServerConfiguration
        :param start_listening: Wheter to start listening to the server. Defaults to
            True.
        :type start_listening: bool
        :param team: The team to use for formats requiring a team. Can be a showdown
            team string, a showdown packed team string, of a ShowdownTeam object.
            Defaults to None.
        :type team: str or Teambuilder, optional
        """
        super(Player, self).__init__(
            player_configuration=player_configuration,
            avatar=avatar,
            log_level=log_level,
            server_configuration=server_configuration,
            start_listening=start_listening,
        )

        self._format: str = battle_format
        self._max_concurrent_battles: int = max_concurrent_battles

        self._battles: Dict[str, Battle] = {}
        self._battle_semaphore: Semaphore = Semaphore(0)

        self._battle_start_condition: Condition = Condition()
        self._battle_count_queue: Queue = Queue(max_concurrent_battles)
        self._challenge_queue: Queue = Queue()

        if isinstance(team, Teambuilder):
            self._team = team
        elif isinstance(team, str):
            self._team = ConstantTeambuilder(team)
        else:
            self._team = None

        self.logger.debug("Player initialisation finished")
async def manipulate_condition(condition: asyncio.Condition):
    print("starting manipulate_condition")

    # consumer의 시작을 잠깐 지연시킨다
    await asyncio.sleep(0.1)

    for i in range(1, 3):
        async with condition:
            print(f"notifying {i} condumers")
            condition.notify(i)
        await asyncio.sleep(0.1)

    async with condition:
        print("notifying remaining consumers")
        condition.notify_all()
    print("ending manupulate_condition")
示例#18
0
async def _wait_for_depletion(
    *,
    signaller: asyncio.Condition,
    scheduler: aiotasks.Scheduler,
    settings: configuration.OperatorSettings,
    streams: Streams,
) -> None:

    # Notify all the workers to finish now. Wake them up if they are waiting in the queue-getting.
    for stream in streams.values():
        await stream.backlog.put(EOS.token)

    # Wait for the queues to be depleted, but only if there are some workers running.
    # Continue with the tasks termination if the timeout is reached, no matter the queues.
    # NB: the scheduler is checked for a case of mocked workers; otherwise, the streams are enough.
    async with signaller:
        try:
            await asyncio.wait_for(
                signaller.wait_for(lambda: not streams or scheduler.empty()),
                timeout=settings.batching.exit_timeout)
        except asyncio.TimeoutError:
            pass

    # The last check if the termination is going to be graceful or not.
    if streams:
        logger.warning(
            f"Unprocessed streams left for {list(streams.keys())!r}.")
示例#19
0
    async def change_audit_actions(self, ctx: commands.Context) -> None:
        """
        A method to change the audit (logging) actions for the guild.
        This is implemented via a discord.ext.menus interface.
            For a more detailed description of how the menu works, see the ActionBitMenu class.

        Parameters:
            ctx (commands.Context): The invocation context.

        Returns:
            None.
        """

        if logging := (await retrieve_query(
                self.bot.DATABASE_NAME,
                'SELECT CHANNEL_ID, BITS FROM LOGGING WHERE GUILD_ID=?',
            (ctx.guild.id, ))):
            bits = int(logging[0][1])

            # create a asyncio.Condition to allow for concurrency checking
            condition = Condition()

            # start the menu
            menu = ActionBitMenu(LoggingActions.all_actions(bits), bits,
                                 condition)
            await menu.start(ctx)

            # while the menu is active, this method is active
            # the condition notifies on menu termination (either via success, cancellation, or timeout)
            async with condition:
                await condition.wait()
示例#20
0
async def condition_chain(
    source: asyncio.Condition,
    target: asyncio.Condition,
) -> None:
    """
    A condition chain is a "clean" hack to attach one condition to another.

    It is a "clean" (not "dirty") hack to wake up the webhook configuration
    managers when either the resources are revised (as seen in the insights),
    or a new client config is yielded from the webhook server.
    """
    async with source:
        while True:
            await source.wait()
            async with target:
                target.notify_all()
示例#21
0
文件: test.py 项目: gavc1/pizone
    async def test_async(self):
        self.loop = asyncio.get_event_loop()
        self.condition = Condition(loop=self.loop)

        async with discovery(self):
            async with self.condition:
                await self.condition.wait()

            self.dump_data()

            # test setting values
            await self.ctrl.set_mode(Controller.Mode.AUTO)

            Controller.CONNECT_RETRY_TIMEOUT = 2

            self.ctrl._ip = 'bababa'  # pylint: disable=protected-access
            try:
                await self.ctrl.set_sleep_timer(30)
                assert False, "Should be unreachable code"
            except ConnectionError:
                pass

            # Should reconnect here
            async with self.condition:
                await self.condition.wait()

            await self.ctrl.set_mode(Controller.Mode.HEAT)

            self.dump_data()
示例#22
0
async def async_request(
        nvim: Nvim, name: str, clients: AbstractSet[str],
        *args: Any) -> AsyncIterator[Tuple[Optional[str], Any]]:
    with timeit(f"LSP :: {name}"):
        cond = _CONDS.setdefault(name, Condition())

        uid = next(_UIDS)
        _STATE[name] = _Session(uid=uid, done=False, acc=())
        async with cond:
            cond.notify_all()

        def cont() -> None:
            nvim.api.exec_lua(
                f"{NAMESPACE}.{name}(...)",
                (name, uid, tuple(clients), *args),
            )

        await async_call(nvim, cont)

        while True:
            acc = _STATE[name]
            if acc.uid == uid:
                _STATE[name] = _Session(uid=acc.uid, done=acc.done, acc=())
                for client, a in acc.acc:
                    yield client, a
                if acc.done:
                    break
            elif acc.uid > uid:
                break

            async with cond:
                await cond.wait()
示例#23
0
 def __init__(self,
              context: StreamFlowContext,
              default_policy: Policy,
              retry_delay: Optional[int] = None) -> None:
     super().__init__()
     self.context: StreamFlowContext = context
     self.default_policy: Policy = default_policy
     self.retry_interval: Optional[int] = retry_delay
     self.wait_queue: Condition = Condition()
 def __init__(self, token: str, **kwargs: Any):
     if not isinstance(token, six.string_types):
         raise TypeError("Token must be a string.")
     self._token = create_access_token(token)
     self._token_refresher = kwargs.pop('token_refresher', None)
     self._proactive_refresh = kwargs.pop('proactive_refresh', False)
     if (self._proactive_refresh and self._token_refresher is None):
         raise ValueError(
             "When 'proactive_refresh' is True, 'token_refresher' must not be None."
         )
     self._timer = None
     self._async_mutex = Lock()
     if sys.version_info[:3] == (3, 10, 0):
         # Workaround for Python 3.10 bug(https://bugs.python.org/issue45416):
         getattr(self._async_mutex, '_get_loop', lambda: None)()
     self._lock = Condition(self._async_mutex)
     self._some_thread_refreshing = False
     self._is_closed = Event()
示例#25
0
async def main():
    cond = Condition()
    fs = list([workers(cond, i) for i in range(10)])
    workers(cond, 11)
    workers(cond, 12)

    await sleep(0.1)
    async with cond:
        for i in range(4):
            print('notify {} workers'.format(i))
            cond.notify(i)
            await sleep(0.1)

    async with cond:
        await sleep(0.5)
        print('notify all')
        cond.notify_all()

    await wait(fs)
示例#26
0
    def __init__(self, client, stdscr):
        self.stdscr = stdscr
        self.client = client
        self.inputevent = Condition()
        self.client.add_event_handler(self.on_message, events.NewMessage)
        self.client.add_event_handler(self.on_user_update, events.UserUpdate)
        # TODO
        # self.client.add_event_handler(self.on_read, events.MessageRead)
        self.text_emojis = True

        self.macros = {}
        self.macro_recording = None
        self.macro_sequence = []

        self.inputs = ""
        self.inputs_cursor = 0

        self.edit_message = None

        self.popup = None

        self.drawtool = drawtool.Drawtool(self)
        self.fin = False
        from config import colors as colorconfig
        self.colors = colorconfig.get_colors()
        self.ready = False

        self.search_result = None
        self.search_index = None
        self.search_box = ""
        self.vimline_box = ""
        self.command_box = ""

        # index corresponds to the index in self.dialogs
        self.selected_chat = 0
        # index offset
        self.selected_chat_offset = 0
            
        self.selected_message = None

        self.mode = "normal"
        self.modestack = []
示例#27
0
    def __init__(self,
                 player_configuration: PlayerConfiguration,
                 *,
                 avatar: Optional[int] = None,
                 battle_format: str,
                 log_level: Optional[int] = None,
                 max_concurrent_battles: int = 1,
                 server_configuration: ServerConfiguration,
                 start_listening: bool = True,
                 alpha=.9,
                 gamma=.95,
                 q_init=.6) -> None:
        """
        :param player_configuration: Player configuration.
        :type player_configuration: PlayerConfiguration
        :param avatar: Player avatar id. Optional.
        :type avatar: int, optional
        :param battle_format: Name of the battle format this player plays.
        :type battle_format: str
        :param log_level: The player's logger level.
        :type log_level: int. Defaults to logging's default level.
        :param max_concurrent_battles: Maximum number of battles this player will play
            concurrently. If 0, no limit will be applied. Defaults to 1.
        :type max_concurrent_battles: int
        :param server_configuration: Server configuration.
        :type server_configuration: ServerConfiguration
        :param start_listening: Wheter to start listening to the server. Defaults to
            True.
        :type start_listening: bool
        """
        self.q = {}  # type: Dict[str, np.ndarray]
        self.move_history = []  # type: List[(str, int)]
        self.learning_rate = alpha
        self.value_discount = gamma
        self.q_init_val = q_init
        super(Player, self).__init__(
            player_configuration=player_configuration,
            avatar=avatar,
            log_level=log_level,
            server_configuration=server_configuration,
            start_listening=start_listening,
        )

        self._format: str = battle_format
        self._max_concurrent_battles: int = max_concurrent_battles

        self._battles: Dict[str, Battle] = {}
        self._battle_semaphore: Semaphore = Semaphore(0)

        self._battle_start_condition: Condition = Condition()
        self._battle_count_queue: Queue = Queue(max_concurrent_battles)
        self._challenge_queue: Queue = Queue()

        self.logger.debug("Player initialisation finished")
示例#28
0
    def __init__(self, rate: float, bucket_size: int) -> None:
        """Constructor for TokenBucket.

        Args:
            rate (float): The number of tokens added to the bucket per second.
                          A token is added to the bucket every 1/rate seconds.
            bucket_size (int): The maximum number of tokens the bucket can hold.

        Raises:
            ValueError: When rate or bucket_size less than or equal to 0.
        """
        if rate <= 0:
            raise ValueError("rate must be > 0")
        if bucket_size <= 0:
            raise ValueError("bucket size must be > 0")
        self._rate: Final[float] = rate
        self._bucket_size: Final[int] = bucket_size
        self.n_token = bucket_size
        self._cond = Condition(Lock())
        _token_filler_worker.register(self)
示例#29
0
    def __init__(
        self,
        pool: Executor,
        nvim: Nvim,
        vars_dir: Path,
        match: MatchOptions,
        comp: CompleteOptions,
        limits: Limits,
        reviewer: PReviewer,
    ) -> None:
        self.pool = pool
        self.vars_dir = vars_dir
        self.match, self.comp, self.limits = match, comp, limits
        self.nvim, self._reviewer = nvim, reviewer

        self.idling = Condition()
        self._workers: MutableMapping[Worker, BaseClient] = WeakKeyDictionary()

        self._lock = Lock()
        self._task: Optional[Task] = None
        self._tasks: Sequence[Task] = ()
示例#30
0
    async def cont() -> None:
        payload = _DECODER(rpayload)
        cond = _CONDS.setdefault(payload.name, Condition())

        acc = _STATE[payload.name]
        if payload.uid >= acc.uid:
            _STATE[payload.name] = _Session(
                uid=payload.uid,
                done=payload.done,
                acc=(*acc.acc, (payload.client, payload.reply)),
            )
        async with cond:
            cond.notify_all()
示例#31
0
 async def replay_job(self,
                      replay_request: ReplayRequest) -> ReplayResponse:
     sender_job = self.context.scheduler.get_job(replay_request.sender)
     target_job = self.context.scheduler.get_job(replay_request.target)
     if target_job.name not in self.jobs:
         self.jobs[target_job.name] = JobVersion(target_job.name, version=0)
     if target_job.name not in self.wait_queues:
         self.wait_queues[target_job.name] = Condition()
     wait_queue = self.wait_queues[target_job.name]
     async with wait_queue:
         if (target_job.name not in self.replay_cache
                 or self.replay_cache[target_job.name].version <
                 replay_request.version):
             # Reschedule job
             logger.info(
                 "Rescheduling job {job}".format(job=target_job.name))
             command_output = CommandOutput(value=None,
                                            status=Status.FAILED)
             self.replay_cache[target_job.name] = ReplayResponse(
                 job=target_job.name,
                 outputs=None,
                 version=self.jobs[target_job.name].version + 1)
             try:
                 if sender_job.step.target is not None:
                     await self.context.scheduler.notify_status(
                         sender_job.name, Status.WAITING)
                 command_output = await self._replay_job(
                     self.jobs[target_job.name])
             finally:
                 if target_job.step.target is not None:
                     await self.context.scheduler.notify_status(
                         target_job.name, command_output.status)
             # Retrieve output
             output_ports = target_job.step.output_ports.values()
             output_tasks = []
             for output_port in output_ports:
                 output_tasks.append(
                     asyncio.create_task(
                         output_port.token_processor.compute_token(
                             target_job, command_output)))
             self.replay_cache[target_job.name].outputs = {
                 port.name: token
                 for (port,
                      token) in zip(output_ports, await asyncio.gather(
                          *output_tasks))
             }
             wait_queue.notify_all()
         elif self.replay_cache[target_job.name].outputs is None:
             # Wait for job completion
             await wait_queue.wait()
         return self.replay_cache[target_job.name]