# Buggy code
def _get_many_from_db_backend(self, async_tasks) -> Mapping[str, EventBufferValueType]:
    task_ids = _tasks_list_to_task_ids(async_tasks)
    session = app.backend.ResultSession()
    task_cls = app.backend.task_cls
    with session_cleanup(session):
        tasks = session.query(task_cls).filter(task_cls.task_id.in_(task_ids)).all()

    task_results = [app.backend.meta_from_decoded(task.to_dict()) for task in tasks]
    task_results_by_task_id = {
        task_result["task_id"]: task_result for task_result in task_results
    }
    return self._prepare_state_and_info_by_task_dict(task_ids, task_results_by_task_id)


# Traceback (AttributeError)
[2021-03-03 17:31:19,393] {scheduler_job.py:1298} ERROR - Exception when executing SchedulerJob._run_scheduler_loop
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/airflow/jobs/scheduler_job.py", line 1280, in _execute
self._run_scheduler_loop()
File "/usr/local/lib/python3.6/dist-packages/airflow/jobs/scheduler_job.py", line 1384, in _run_scheduler_loop
self.executor.heartbeat()
File "/usr/local/lib/python3.6/dist-packages/airflow/executors/base_executor.py", line 162, in heartbeat
self.sync()
File "/usr/local/lib/python3.6/dist-packages/airflow/executors/celery_executor.py", line 340, in sync
self.update_all_task_states()
File "/usr/local/lib/python3.6/dist-packages/airflow/executors/celery_executor.py", line 399, in update_all_task_states
state_and_info_by_celery_task_id = self.bulk_state_fetcher.get_many(self.tasks.values())
File "/usr/local/lib/python3.6/dist-packages/airflow/executors/celery_executor.py", line 552, in get_many
result = self._get_many_from_db_backend(async_results)
File "/usr/local/lib/python3.6/dist-packages/airflow/executors/celery_executor.py", line 570, in _get_many_from_db_backend
task_cls = app.backend.task_cls
AttributeError: 'DatabaseBackend' object has no attribute 'task_cls'
[2021-03-03 17:31:20,396] {process_utils.py:100} INFO - Sending Signals.SIGTERM to GPID 3852
[2021-03-03 17:31:20,529] {process_utils.py:66} INFO - Process psutil.Process(pid=3996, status='terminated', started='17:31:19') (3996) terminated with exit code None
[2021-03-03 17:31:20,533] {process_utils.py:66} INFO - Process psutil.Process(pid=3997, status='terminated', started='17:31:19') (3997) terminated with exit code None
[2021-03-03 17:31:20,533] {process_utils.py:206} INFO - Waiting up to 5 seconds for processes to exit...
[2021-03-03 17:31:20,540] {process_utils.py:66} INFO - Process psutil.Process(pid=3852, status='terminated', exitcode=0, started='17:31:13') (3852) terminated with exit code 0
[2021-03-03 17:31:20,540] {scheduler_job.py:1301} INFO - Exited execute loop

# Fixed code
def _get_many_from_db_backend(self, async_tasks) -> Mapping[str, EventBufferValueType]:
    task_ids = _tasks_list_to_task_ids(async_tasks)
    session = app.backend.ResultSession()
    task_cls = getattr(app.backend, "task_cls", TaskDb)
    with session_cleanup(session):
        tasks = session.query(task_cls).filter(task_cls.task_id.in_(task_ids)).all()

    task_results = [app.backend.meta_from_decoded(task.to_dict()) for task in tasks]
    task_results_by_task_id = {
        task_result["task_id"]: task_result for task_result in task_results
    }
    return self._prepare_state_and_info_by_task_dict(task_ids, task_results_by_task_id)