# Path: django_lightweight_queue/types.py
# class Logger(Protocol):
#     def log(
#         self,
#         level: int,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def debug(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def info(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def warning(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def error(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def exception(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
# 
# Path: django_lightweight_queue/utils.py
# @lru_cache()
# def get_path(path: str) -> Any:
#     module_name, attr = path.rsplit('.', 1)
# 
#     module = importlib.import_module(module_name)
# 
#     return getattr(module, attr)
# 
# @lru_cache()
# def get_middleware() -> List[Any]:
#     middleware = []
# 
#     for path in app_settings.MIDDLEWARE:
#         try:
#             middleware.append(get_path(path)())
#         except MiddlewareNotUsed:
#             pass
# 
#     return middleware


import sys
import json
import time
import datetime
import warnings
from typing import Any, Dict, Tuple, Callable, Optional, TYPE_CHECKING
from django.db import transaction
from .types import QueueName, WorkerNumber
from .utils import get_path, get_middleware
    from .task import TaskWrapper
        return "<Job: {}(*{!r}, **{!r}) @ {}>".format(
            self.path,
            self.args,
            self.kwargs,
            self.created_time_str,
        )

    @classmethod
    def from_json(cls, val: str) -> 'Job':
        as_dict = json.loads(val)

        # Historic jobs won't have a created_time, so have a default
        created_time = as_dict.pop('created_time', None)

        job = cls(**as_dict)
        if created_time is not None:
            job.created_time = datetime.datetime.strptime(
                created_time,
                TIME_FORMAT,
            )

        # Ensures that Job.from_json(x).to_json() == x
        job._json = val

        return job

    @property
    def created_time_str(self) -> str:
        return self.created_time.strftime(TIME_FORMAT)


# Path: django_lightweight_queue/types.py
# class Logger(Protocol):
#     def log(
#         self,
#         level: int,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def debug(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def info(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def warning(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def error(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
#     def exception(
#         self,
#         msg: str,
#         *args: Any,
#         exc_info: _ExcInfoType = ...,
#         stack_info: bool = ...,
#         extra: Optional[Dict[str, Any]] = ...,
#         **kwargs: Any
#     ) -> None:
# 
# Path: django_lightweight_queue/utils.py
# @lru_cache()
# def get_path(path: str) -> Any:
#     module_name, attr = path.rsplit('.', 1)
# 
#     module = importlib.import_module(module_name)
# 
#     return getattr(module, attr)
# 
# @lru_cache()
# def get_middleware() -> List[Any]:
#     middleware = []
# 
#     for path in app_settings.MIDDLEWARE:
#         try:
#             middleware.append(get_path(path)())
#         except MiddlewareNotUsed:
#             pass
# 
#     return middleware


# Path: django_lightweight_queue/job.py
import sys
import json
import time
import datetime
import warnings
from typing import Any, Dict, Tuple, Callable, Optional, TYPE_CHECKING
from django.db import transaction
from .types import QueueName, WorkerNumber
from .utils import get_path, get_middleware
    from .task import TaskWrapper

        return "<Job: {}(*{!r}, **{!r}) @ {}>".format(
            self.path,
            self.args,
            self.kwargs,
            self.created_time_str,
        )

    @classmethod
    def from_json(cls, val: str) -> 'Job':
        as_dict = json.loads(val)

        # Historic jobs won't have a created_time, so have a default
        created_time = as_dict.pop('created_time', None)

        job = cls(**as_dict)
        if created_time is not None:
            job.created_time = datetime.datetime.strptime(
                created_time,
                TIME_FORMAT,
            )

        # Ensures that Job.from_json(x).to_json() == x
        job._json = val

        return job

    @property
    def created_time_str(self) -> str:
        return self.created_time.strftime(TIME_FORMAT)


    def run(self, *, queue: QueueName, worker_num: WorkerNumber) -> bool: