Example #1
0
    def test_run_on_error(self):
        """Test whether an exception is thrown if a task fails"""

        small_delay = 0
        manager = TasksManager(self.backend_tasks,
                               "fake-section",
                               self.stopper,
                               self.config,
                               timer=small_delay)

        with self.assertRaises(Exception):
            manager.run()
Example #2
0
    def test_initialization(self):
        """Test whether attributes are initializated"""

        small_delay = 0
        first_backend = self.backends[list(self.backends.keys())[0]]
        manager = TasksManager(self.backend_tasks,
                               first_backend,
                               self.stopper,
                               self.config,
                               timer=small_delay)

        self.assertEqual(manager.config, self.config)
        self.assertEqual(manager.stopper, self.stopper)
        self.assertEqual(manager.tasks_cls, self.backend_tasks)
        self.assertEqual(manager.backend_section, first_backend)
        self.assertEqual(manager.timer, small_delay)
        self.assertEqual(manager.tasks, [])
Example #3
0
    def test_add_task(self):
        """Test whether tasks are properly added"""

        small_delay = 0
        first_backend = list(self.backends.keys())[0]
        manager = TasksManager(self.backend_tasks,
                               first_backend,
                               self.stopper,
                               self.config,
                               timer=small_delay)

        self.assertEqual(manager.tasks, [])

        for tc in manager.tasks_cls:
            task = tc(manager.config)
            task.set_backend_section(manager.backend_section)
            manager.tasks.append(task)

        self.assertEqual(len(manager.tasks), len(manager.tasks_cls))
Example #4
0
    def execute_batch_tasks(self,
                            tasks_cls,
                            big_delay=0,
                            small_delay=0,
                            wait_for_threads=True):
        """
        Start a task manager per backend to complete the tasks.

        :param task_cls: list of tasks classes to be executed
        :param big_delay: seconds before global tasks are executed, should be days usually
        :param small_delay: seconds before backend tasks are executed, should be minutes
        :param wait_for_threads: boolean to set when threads are infinite or
                                should be synchronized in a meeting point
        """
        def _split_tasks(tasks_cls):
            """
            we internally distinguish between tasks executed by backend
            and tasks executed with no specific backend. """
            backend_t = []
            global_t = []
            for t in tasks_cls:
                if t.is_backend_task(t):
                    backend_t.append(t)
                else:
                    global_t.append(t)
            return backend_t, global_t

        logger.debug('Tasks Manager starting .. ')

        backend_tasks, global_tasks = _split_tasks(tasks_cls)
        logger.debug('backend_tasks = %s' % (backend_tasks))
        logger.debug('global_tasks = %s' % (global_tasks))

        threads = []

        # stopper won't be set unless wait_for_threads is True
        stopper = threading.Event()

        # launching threads for tasks by backend
        if len(backend_tasks) > 0:
            repos_backend = self._get_repos_by_backend()
            for backend in repos_backend:
                # Start new Threads and add them to the threads list to complete
                t = TasksManager(backend_tasks, backend, stopper, self.config,
                                 small_delay)
                threads.append(t)
                t.start()

        # launch thread for global tasks
        if len(global_tasks) > 0:
            # FIXME timer is applied to all global_tasks, does it make sense?
            # All tasks are executed in the same thread sequentially
            gt = TasksManager(global_tasks, "Global tasks", stopper,
                              self.config, big_delay)
            threads.append(gt)
            gt.start()
            if big_delay > 0:
                when = datetime.now() + timedelta(seconds=big_delay)
                when_str = when.strftime('%a, %d %b %Y %H:%M:%S %Z')
                logger.info("%s will be executed on %s" %
                            (global_tasks, when_str))

        if wait_for_threads:
            time.sleep(1)  # Give enough time create and run all threads
            stopper.set()  # All threads must stop in the next iteration
            logger.debug(
                " Waiting for all threads to complete. This could take a while .."
            )

        # Wait for all threads to complete
        for t in threads:
            t.join()

        # Checking for exceptions in threads to log them
        self.__check_queue_for_errors()

        logger.debug(" Task manager and all its tasks (threads) finished!")
Example #5
0
    def execute_batch_tasks(self,
                            tasks_cls,
                            big_delay=0,
                            small_delay=0,
                            wait_for_threads=True):
        """
        Start a task manager per backend to complete the tasks.

        :param task_cls: list of tasks classes to be executed
        :param big_delay: seconds before global tasks are executed, should be days usually
        :param small_delay: seconds before backend tasks are executed, should be minutes
        :param wait_for_threads: boolean to set when threads are infinite or
                                should be synchronized in a meeting point
        """

        # 把task分为两种
        # backend_tasks 包括从backend获取数据,并作ecrich工作
        # backend_tasks = [<class 'sirmordred.task_collection.TaskRawDataCollection'>, <class 'sirmordred.task_enrich.TaskEnrich'>]
        # global_tasks = [<class 'sirmordred.task_projects.TaskProjects'>] 做project加载工作
        def _split_tasks(tasks_cls):
            """
            we internally distinguish between tasks executed by backend
            and tasks executed with no specific backend. """
            backend_t = []
            global_t = []
            for t in tasks_cls:
                if t.is_backend_task(t):
                    backend_t.append(t)
                else:
                    global_t.append(t)
            return backend_t, global_t

        backend_tasks, global_tasks = _split_tasks(tasks_cls)
        logger.debug('backend_tasks = %s' % (backend_tasks))
        logger.debug('global_tasks = %s' % (global_tasks))

        # 多线程
        threads = []
        # update 为 false 时, wait_for_threads 为 true ,会去设置一个相当于贯穿多个线程之间的条件变量
        # stopper won't be set unless wait_for_threads is True
        stopper = threading.Event()

        # launching threads for tasks by backend
        if len(backend_tasks) > 0:
            repos_backend = self._get_repos_by_backend()
            for backend in repos_backend:
                # 启动线程
                # Start new Threads and add them to the threads list to complete
                t = TasksManager(backend_tasks, backend, stopper, self.config,
                                 small_delay)
                threads.append(t)
                t.start()

        # launch thread for global tasks
        if len(global_tasks) > 0:
            # FIXME timer is applied to all global_tasks, does it make sense?
            # All tasks are executed in the same thread sequentially
            gt = TasksManager(global_tasks, "Global tasks", stopper,
                              self.config, big_delay)
            threads.append(gt)
            gt.start()
            if big_delay > 0:
                when = datetime.now() + timedelta(seconds=big_delay)
                when_str = when.strftime('%a, %d %b %Y %H:%M:%S %Z')
                logger.info("%s will be executed on %s" %
                            (' '.join([g.__name__
                                       for g in global_tasks]), when_str))
        # update 为 false 时, wait_for_threads 为 true ,stopper 变量申请完默认为 false
        # stopper 为false时,其他线程t.start(),但是会阻塞等待,等到调用 set之后为 true,才会开始执行
        # 可以去看 task_manager.py
        if wait_for_threads:
            time.sleep(1)  # Give enough time create and run all threads
            stopper.set()  # All threads must stop in the next iteration

        # Wait for all threads to complete
        for t in threads:
            t.join()

        # Checking for exceptions in threads to log them
        self.__check_queue_for_errors()

        logger.debug(
            "[thread:main] All threads (and their tasks) are finished")