Here is the refactored package structure. The code is split into logical modules, ensuring single responsibility, proper encapsulation, and a clean public API.

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

### `queue/__init__.py`
This file defines the public API. It imports from submodules to hide internal implementation details (like `PriorityQueue` if you decide not to expose it, though I have exposed it for completeness based on the original monolith).

```python
"""
Queue Package.
Exports the main Job class, JobQueue, PriorityQueue, and retry logic.
"""
from .core import Job, JobQueue
from .priority import PriorityQueue
from .retry import process_with_retry

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

### `queue/core.py`
Contains the fundamental data model (`Job`) and the standard FIFO queue implementation (`JobQueue`).

```python
"""
Core module containing Job data model and basic queue operations.
"""
from dataclasses import dataclass, field
from typing import Any, Optional
from collections import deque
from datetime import datetime


@dataclass
class Job:
    """Represents a unit of work to be processed."""
    id: str
    payload: Any
    priority: int = 0
    retry_count: int = 0
    created_at: datetime = field(default_factory=datetime.now)
    status: str = "pending"

    def __repr__(self):
        return f"Job(id={self.id}, status={self.status}, retries={self.retry_count})"


class JobQueue:
    """
    A standard FIFO queue for Job objects.
    """
    def __init__(self):
        self._queue: deque = deque()

    def enqueue(self, job: Job) -> None:
        """Add a job to the end of the queue."""
        self._queue.append(job)

    def dequeue(self) -> Optional[Job]:
        """Remove and return the job at the front of the queue."""
        if self._queue:
            return self._queue.popleft()
        return None

    def peek(self) -> Optional[Job]:
        """Return the job at the front without removing it."""
        if self._queue:
            return self._queue[0]
        return None

    def size(self) -> int:
        """Return the number of jobs in the queue."""
        return len(self._queue)

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

### `queue/priority.py`
Contains the priority queue implementation using a binary heap. It relies on `Job` from `core.py`.

```python
"""
Priority Queue implementation using a min-heap.
"""
import heapq
from typing import Optional

from .core import Job


class PriorityQueue:
    """
    A queue that dequeues jobs based on priority (lower number = higher priority).
    """
    def __init__(self):
        self._heap: list = []
        self._counter = 0  # Used to break ties for fairness

    def enqueue(self, job: Job) -> None:
        """
        Add a job to the queue. 
        Items are pushed as (priority, counter, job) to ensure stable sorting.
        """
        self._counter += 1
        entry = (job.priority, self._counter, job)
        heapq.heappush(self._heap, entry)

    def dequeue(self) -> Optional[Job]:
        """
        Remove and return the job with the highest priority (lowest number).
        """
        if self._heap:
            return heapq.heappop(self._heap)[2]
        return None

    def peek(self) -> Optional[Job]:
        """Return the highest priority job without removing it."""
        if self._heap:
            return self._heap[0][2]
        return None

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

### `queue/retry.py`
Contains the logic for handling failed jobs with exponential backoff. It relies on `Job` from `core.py` to update state.

```python
"""
Retry logic module.
Handles job execution with exponential backoff and error handling.
"""
import time
import random
from typing import Callable, Any

from .core import Job


def process_with_retry(
    job: Job, 
    func: Callable[[Any], None], 
    max_retries: int = 3,
    base_delay: float = 1.0
) -> bool:
    """
    Executes a job function with retry logic and exponential backoff.
    
    Args:
        job: The Job object to process (status and retry_count will be updated).
        func: The callable that accepts the job payload.
        max_retries: Maximum number of retry attempts.
        base_delay: Initial delay in seconds for backoff.
        
    Returns:
        True if successful, False if all retries exhausted.
    """
    for attempt in range(max_retries + 1):
        try:
            func(job.payload)
            job.status = "completed"
            job.retry_count = 0
            return True
        except Exception as e:
            job.retry_count += 1
            job.status = "failed"
            
            if attempt < max_retries:
                # Exponential backoff: base_delay * 2^attempt + jitter
                delay = (base_delay * (2 ** attempt)) + random.uniform(0, 1)
                time.sleep(delay)
            else:
                job.status = "failed_max_retries"
                return False

    return False
```