Here is the refactored package structure. I have implemented the logic to ensure all dependencies are resolved correctly without circular imports, while maintaining the functionality of the original monolithic file.

### File Structure
```text
queue/
├── __init__.py
├── core.py
├── priority.py
└── retry.py
```

### 1. `queue/__init__.py`
This file exposes the clean public API. It imports the main classes and the utility function defined in other modules.

```python
"""
Queue Package.
Exports the main Job class, JobQueue, and retry utilities.
"""

from .core import Job, JobQueue
from .retry import process_with_retry

__all__ = ['Job', 'JobQueue', 'process_with_retry']
```

### 2. `queue/core.py`
This module contains the business logic for the Job and the main Queue orchestrator. It imports `PriorityQueue` from `priority.py`.

```python
"""
Core module containing Job dataclass and JobQueue logic.
"""
from dataclasses import dataclass, field
from typing import Any, Optional, List
from .priority import PriorityQueue

@dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str
    payload: Any
    priority: int = 0
    status: str = "pending"
    created_at: float = field(default_factory=lambda: __import__('time').time())

class JobQueue:
    """
    High-level job queue that manages Job instances.
    Delegates priority sorting to the internal PriorityQueue.
    """
    def __init__(self):
        # Use a generic priority queue for internal sorting
        self._queue = PriorityQueue()
        self._jobs: dict[str, Job] = {} # Track jobs by ID for lookup

    def enqueue(self, job: Job) -> None:
        """Add a job to the queue."""
        self._jobs[job.id] = job
        # PriorityQueue expects (item, priority)
        self._queue.push(job, job.priority)

    def dequeue(self) -> Optional[Job]:
        """
        Remove and return the highest priority job.
        Returns None if queue is empty.
        """
        job = self._queue.pop()
        if job is not None:
            job.status = "processing"
            return job
        return None

    def peek(self) -> Optional[Job]:
        """Look at the next job without removing it."""
        job = self._queue.peek()
        return job

    def get_job(self, job_id: str) -> Optional[Job]:
        """Retrieve a job by ID."""
        return self._jobs.get(job_id)

    def is_empty(self) -> bool:
        """Check if the queue has no jobs."""
        return len(self._jobs) == 0
    
    def size(self) -> int:
        """Return the number of jobs in the queue."""
        return len(self._jobs)
```

### 3. `queue/priority.py`
This module handles the low-level heap operations. It is kept generic to avoid circular imports with `core.py`.

```python
"""
Priority Queue implementation using a binary heap.
"""
import heapq
import time
from typing import Any, Optional, Tuple

class PriorityQueue:
    """
    A min-heap based priority queue.
    Lower numbers have higher priority.
    """
    def __init__(self):
        self._queue: list[Tuple[int, int, Any]] = []
        self._counter = 0  # Tie-breaker for FIFO behavior within same priority

    def push(self, item: Any, priority: int) -> None:
        """
        Insert an item with a specific priority.
        Items with lower integer priority are popped first.
        """
        # We negate priority to simulate max-heap behavior if needed, 
        # but standard heapq is min-heap. 
        # Assuming lower number = higher priority (standard for job queues).
        entry = (priority, self._counter, item)
        heapq.heappush(self._queue, entry)
        self._counter += 1

    def pop(self) -> Optional[Any]:
        """
        Remove and return the item with the highest priority (lowest number).
        Returns None if the queue is empty.
        """
        if not self._queue:
            return None
        _, _, item = heapq.heappop(self._queue)
        return item

    def peek(self) -> Optional[Any]:
        """Return the highest priority item without removing it."""
        if not self._queue:
            return None
        return self._queue[0][2]
    
    def __len__(self):
        return len(self._queue)
```

### 4. `queue/retry.py`
This module contains the retry logic with exponential backoff. It is decoupled from the queue classes to allow reuse.

```python
"""
Retry logic module with exponential backoff support.
"""
import time
import math
from typing import Callable, TypeVar, Any

T = TypeVar('T')

def process_with_retry(
    func: Callable[..., T], 
    max_retries: int = 3, 
    initial_delay: float = 1.0,
    max_delay: float = 60.0,
    backoff_multiplier: float = 2.0
) -> T:
    """
    Executes a function with exponential backoff on failure.
    
    Args:
        func: The callable to execute.
        max_retries: Maximum number of retry attempts.
        initial_delay: Initial delay in seconds.
        max_delay: Cap the delay at this value.
        backoff_multiplier: Factor to multiply delay by each retry.
    
    Returns:
        The result of the function.
    
    Raises:
        The last exception encountered if all retries are exhausted.
    """
    delay = initial_delay
    last_exception = None

    for attempt in range(max_retries + 1):
        try:
            return func()
        except Exception as e:
            last_exception = e
            if attempt >= max_retries:
                break
            
            # Calculate next delay with exponential backoff
            delay = min(delay * backoff_multiplier, max_delay)
            time.sleep(delay)

    raise last_exception
```

### Key Refactoring Decisions

1.  **Circular Import Prevention**: `core.py` imports `PriorityQueue` from `priority.py`, but `priority.py` does *not* import `core.py`. `PriorityQueue` is generic (`Any`), allowing `JobQueue` (in `core.py`) to enforce type safety when interacting with `Job` objects.
2.  **Separation of Concerns**:
    *   `core.py`: Business logic (Job definition, Queue orchestration).
    *   `priority.py`: Data structure (Heap implementation).
    *   `retry.py`: Side-effect handling (Network/IO failures).
    *   `__init__.py`: Public API surface.
3.  **Type Safety**: Used `dataclass` for `Job` and Type Hints (`Callable`, `Optional`, etc.) to maintain code quality.
4.  **Backward Compatibility**: The `JobQueue` class mimics the behavior of the original monolithic `JobQueue`, and `process_with_retry` retains its signature and logic.