Here is the refactored package structure.

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

### 1. `queue/__init__.py`
This file defines the public API, importing the necessary classes and functions from internal modules to keep the namespace clean.

```python
"""
Queue Package.
Provides a priority-based job queue with retry capabilities.
"""

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

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

### 2. `queue/priority.py`
Contains the low-level Priority Queue implementation using Python's `heapq`. It is generic and does not depend on the `Job` class.

```python
"""
Priority Queue Implementation.
A min-heap based queue for ordering items by priority.
"""
import heapq
from typing import Any, Optional

class PriorityQueue:
    def __init__(self):
        self._heap = []
        self._counter = 0

    def push(self, item: Any, priority: int = 0):
        """Push an item with a specific priority."""
        # Tie-breaker using counter to ensure FIFO for same priorities
        heapq.heappush(self._heap, (priority, self._counter, item))
        self._counter += 1

    def pop(self) -> Any:
        """Pop the item with the highest priority."""
        if not self._heap:
            raise IndexError("Pop from empty priority queue")
        _, _, item = heapq.heappop(self._heap)
        return item

    def peek(self) -> Optional[Any]:
        """View the item with the highest priority without removing it."""
        if not self._heap:
            return None
        return self._heap[0][2]

    def is_empty(self) -> bool:
        """Check if the queue is empty."""
        return len(self._heap) == 0

    def __len__(self) -> int:
        return len(self._heap)
```

### 3. `queue/core.py`
Contains the `Job` dataclass and the main `JobQueue` orchestrator. It imports `PriorityQueue` for internal storage.

```python
"""
Core Queue Operations.
Defines the Job data structure and the main JobQueue manager.
"""
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Optional, List
from enum import Enum

from .priority import PriorityQueue

class JobStatus(Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"

@dataclass
class Job:
    id: str
    payload: Any
    priority: int = 0
    status: JobStatus = JobStatus.PENDING
    created_at: datetime = field(default_factory=datetime.now)
    
    # Allow comparison based on priority (lower number = higher priority)
    def __lt__(self, other):
        if self.priority == other.priority:
            return self.created_at < other.created_at
        return self.priority < other.priority

class JobQueue:
    def __init__(self):
        self._queue = PriorityQueue()
        self._jobs: dict[str, Job] = {}

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

    def dequeue(self) -> Optional[Job]:
        """Remove and return the highest priority job."""
        job = self._queue.pop()
        if job:
            job.status = JobStatus.RUNNING
        return job

    def peek(self) -> Optional[Job]:
        """Return the highest priority job without removing it."""
        return self._queue.peek()

    def mark_completed(self, job_id: str) -> bool:
        """Update job status to completed."""
        if job_id in self._jobs:
            self._jobs[job_id].status = JobStatus.COMPLETED
            return True
        return False

    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:
        return self._queue.is_empty()

    def __len__(self) -> int:
        return len(self._queue)
```

### 4. `queue/retry.py`
Contains the retry logic utility. It is independent of the queue internals to allow reuse in other contexts.

```python
"""
Retry Logic Implementation.
Handles exponential backoff and retry attempts.
"""
import time
import random
from typing import Callable, Any

def process_with_retry(
    func: Callable,
    *args,
    max_retries: int = 3,
    backoff_factor: float = 1.0,
    **kwargs
) -> Any:
    """
    Execute a function with exponential backoff retry logic.
    
    Args:
        func: The callable to execute.
        *args: Positional arguments to pass to the function.
        max_retries: Maximum number of retry attempts.
        backoff_factor: Base delay in seconds for backoff.
        **kwargs: Keyword arguments to pass to the function.
        
    Returns:
        The result of the function if successful.
        
    Raises:
        The last exception raised if all retries fail.
    """
    last_exception = None
    
    for attempt in range(max_retries + 1):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            last_exception = e
            if attempt == max_retries:
                break
            
            # Calculate exponential backoff with jitter
            delay = (2 ** attempt) * backoff_factor + random.uniform(0, 1)
            time.sleep(delay)
            
    raise last_exception
```

### Key Refactoring Decisions:

1.  **Separation of Concerns**:
    *   `priority.py` handles only heap mechanics.
    *   `core.py` handles business logic (`Job` definition, Queue management).
    *   `retry.py` handles failure strategies.
2.  **Circular Import Safety**: `core.py` imports `priority.py`, but `priority.py` imports nothing from `core`. This prevents circular dependency errors.
3.  **Public API**: `__init__.py` hides the internal `PriorityQueue` class, exposing only `Job`, `JobQueue`, and `process_with_retry` to the end-user.
4.  **Data Structure**: `Job` implements `__lt__` to allow `PriorityQueue` to compare jobs without needing to know the `Job` class definition in `priority.py`.
5.  **State Management**: `JobQueue` maintains a separate dictionary (`_jobs`) to look up jobs by ID for status updates, while `PriorityQueue` handles the ordering.