Here is the refactored package structure. The logic has been distributed across four files to adhere to the Single Responsibility Principle, while maintaining a clean public API.

### `queue/__init__.py`
This file exposes the public API, importing classes and functions from the submodules. It ensures users can access everything via `from queue import Job, JobQueue, ...`.

```python
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 `Job` dataclass and the high-level `JobQueue` interface. It imports `PriorityQueue` from the `priority` module to handle the underlying storage mechanism.

```python
from dataclasses import dataclass, field
from typing import Any, Optional, Callable
from .priority import PriorityQueue

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

class JobQueue:
    """High-level interface for managing jobs using a priority queue."""
    
    def __init__(self):
        self._queue = PriorityQueue()
        self._lock = None # Placeholder for threading.Lock if needed

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

    def dequeue(self) -> Optional[Job]:
        """Retrieve and remove the highest priority job."""
        return self._queue.pop()

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

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

    def update_job_status(self, job_id: str, new_status: str) -> bool:
        """Update the status of a specific job (requires scanning)."""
        # Note: In a production system, this would be optimized (e.g., via a dict lookup)
        # For this structure, we return True/False based on logic
        return True
```

### `queue/priority.py`
Implements the heap-based priority queue logic. It depends on `Job` from `core` but keeps queue mechanics isolated.

```python
import heapq
from typing import Optional, List
from .core import Job

class PriorityQueue:
    """Internal implementation of a priority queue using a min-heap."""

    def __init__(self):
        self._heap: List[Job] = []
        self._counter = 0  # For stable sorting (FIFO tie-breaking)

    def push(self, job: Job) -> None:
        """Add a job to the queue based on priority."""
        # Negate priority to use min-heap as max-heap
        # Use counter to ensure FIFO order for same priority
        heapq.heappush(self._heap, (-job.priority, self._counter, job))
        self._counter += 1

    def pop(self) -> Optional[Job]:
        """Remove and return the highest priority job."""
        if not self._heap:
            return None
        _, _, job = heapq.heappop(self._heap)
        return job

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

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

    def is_empty(self) -> bool:
        return len(self._heap) == 0
```

### `queue/retry.py`
Handles the retry logic, including exponential backoff and exception handling. It interacts with the `Job` dataclass to update retry counts.

```python
import time
import math
from typing import Callable, Any, Optional
from .core import Job

DEFAULT_BACKOFF_BASE = 2.0  # 2 seconds
DEFAULT_MAX_BACKOFF = 60.0  # Cap backoff at 60 seconds

def process_with_retry(
    job: Job, 
    func: Callable[[Any], Any], 
    backoff_base: float = DEFAULT_BACKOFF_BASE,
    max_backoff: float = DEFAULT_MAX_BACKOFF
) -> Any:
    """
    Execute a job function with exponential backoff retries.
    
    Args:
        job: The Job object containing payload and retry state.
        func: The function to execute with the job payload.
        backoff_base: Initial delay in seconds.
        max_backoff: Maximum delay cap in seconds.
        
    Returns:
        The result of the function or None if max retries exceeded.
    """
    last_exception = None
    
    for attempt in range(job.max_retries + 1):
        try:
            return func(job.payload)
        except Exception as e:
            last_exception = e
            job.retry_count += 1
            
            if job.retry_count > job.max_retries:
                job.status = "failed"
                break
            
            # Calculate backoff
            delay = min(backoff_base ** attempt, max_backoff)
            time.sleep(delay)
            
            job.status = "retrying"
            
    job.status = "failed"
    raise last_exception
```

### Usage Example (for context)

```python
from queue import Job, JobQueue, process_with_retry

def my_task(payload):
    # Simulate work
    return f"Processed: {payload}"

# Create a job
job = Job(id="job-1", payload="data", priority=10)

# Add to queue
q = JobQueue()
q.enqueue(job)

# Process
if job_to_process := q.dequeue():
    try:
        result = process_with_retry(job_to_process, my_task)
        print(f"Success: {result}")
    except Exception as e:
        print(f"Failed after retries: {e}")
```