async def test_handle_outdated(
    task_queue: WorkerTaskQueue,
    worker: Tuple[WorkerTaskDescription, WorkerTaskDescription, WorkerTaskDescription],
    performed_by: Dict[str, List[str]],
) -> None:
    _, _, outdated_task = worker

    all_tasks = [create_task(str(n), outdated_task.name) for n in range(0, 20)]
    for t in all_tasks:
        await task_queue.add_task(t)

    await asyncio.sleep(0)

    count_outstanding = 0
    while task_queue.outstanding_tasks:
        await task_queue.check_outdated_unassigned_tasks()
        count_outstanding += 1

    # every message is retried 3 times ==> 4 times to get rid of all messages
    assert count_outstanding == 4

    results = await asyncio.gather(*[a.callback for a in all_tasks], return_exceptions=True)
    # make sure all results are failures
    for r in results:
        assert isinstance(r, Exception)

    # 20 work items by 4 workers: 5 work items each + retried 3 times (15) => 20
    by_worker = group_by(lambda x: x, (item for sublist in performed_by.values() for item in sublist))
    assert len(by_worker) == 4
    for work_done in by_worker.values():
        assert len(work_done) == 20
Example #2
0
 def __init__(
     self,
     dependencies: CLIDependencies,
     parts: List[CLICommand],
     alias_names: Dict[str, str],
     alias_templates: List[AliasTemplate],
 ):
     super().__init__(dependencies, True)
     self.all_parts = {p.name: p for p in parts + [self]}
     self.parts = {
         p.name: p
         for p in parts + [self] if not isinstance(p, InternalPart)
     }
     self.alias_names = {
         a: n
         for a, n in alias_names.items()
         if n in self.parts and a not in self.parts
     }
     self.reverse_alias_names: Dict[str, List[str]] = {
         k: [e[0] for e in v]
         for k, v in group_by(lambda a: a[1],
                              self.alias_names.items()).items()
     }
     self.alias_templates = {
         a.name: a
         for a in sorted(alias_templates, key=attrgetter("name"))
     }
async def test_handle_work_successfully(
    task_queue: WorkerTaskQueue,
    worker: Tuple[WorkerTaskDescription, WorkerTaskDescription, WorkerTaskDescription],
    performed_by: Dict[str, List[str]],
) -> None:
    success_task, _, _ = worker

    all_tasks = [create_task(str(n), success_task.name) for n in range(0, 20)]
    for t in all_tasks:
        await task_queue.add_task(t)

    results = await asyncio.gather(*[a.callback for a in all_tasks])
    assert results == [{"result": "done!"} for _ in range(0, 20)]

    # make sure the work is split equally between all workers: 20 work items by 4 workers: 5 work items each
    by_worker = group_by(lambda x: x, (item for sublist in performed_by.values() for item in sublist))
    assert len(by_worker) == 4
    for work_done in by_worker.values():
        assert len(work_done) == 5
Example #4
0
 async def update_trigger(self, desc: TaskDescription, register: bool = True) -> None:
     # safeguard: unregister all event trigger of this task
     for existing in (tup for tup in self.registered_event_trigger if desc.id == tup[1].id):
         self.registered_event_trigger.remove(existing)
     # safeguard: unregister all schedule trigger of this task
     for job in self.scheduler.list_jobs():
         if str(job.id).startswith(desc.id):
             job.remove()
     # add all triggers
     if register:
         for trigger in desc.triggers:
             if isinstance(trigger, EventTrigger):
                 self.registered_event_trigger.append((trigger, desc))
             if isinstance(trigger, TimeTrigger):
                 uid = f"{desc.id}_{trigger.cron_expression}"
                 name = f"Trigger for task {desc.id} on cron expression {trigger.cron_expression}"
                 self.scheduler.cron(uid, name, trigger.cron_expression, self.time_triggered, desc, trigger)
     # recompute the lookup table
     self.registered_event_trigger_by_message_type = group_by(
         lambda t: t[0].message_type, self.registered_event_trigger
     )