Skip to content

SyncQueue reference

Experimental feature

This feature is experimental and should be considered unstable and unsupported. API may change at any time and without backwards compatibility.

sheppy.experimental.SyncQueue

SyncQueue(
    backend: str | None = None,
    name: str | None = None,
    *,
    backend_kwargs: dict[str, Any] | None = None,
)

Synchronous wrapper around Queue for codebases without asyncio.

A dedicated asyncio event loop runs in a background daemon thread. Every method submits the corresponding Queue coroutine to that loop via asyncio.run_coroutine_threadsafe and blocks the calling thread until the result is ready. The wrapped Queue and its backend always run on the same loop, so the instance can be shared between threads; long waits (e.g. wait_for with no timeout) block the calling thread, not the loop.

Call close() when done to stop the loop and join its thread. The thread is a daemon, so it does not block interpreter exit.

Unlike Queue, the backend can only be given as a URL string (or via the SHEPPY_BACKEND_URL environment variable); the constructor does not accept a Backend instance.

PARAMETER DESCRIPTION
backend

Backend URL string, e.g. "redis://localhost:6379" or "memory://". If None, uses SHEPPY_BACKEND_URL env var.

TYPE: str | None DEFAULT: None

name

Name of the queue. Defaults to SHEPPY_QUEUE env var or "default".

TYPE: str | None DEFAULT: None

backend_kwargs

Options forwarded to the backend constructor.

TYPE: dict[str, Any] | None DEFAULT: None

Example
q = SyncQueue("redis://localhost:6379")

added = q.add(task)
assert added is task

q.close()
Source code in src/sheppy/experimental/_sync_queue.py
51
52
53
54
55
56
57
58
59
60
61
def __init__(self, backend: str | None = None, name: str | None = None, *, backend_kwargs: dict[str, Any] | None = None):
    self._backend = backend
    self._backend_kwargs = backend_kwargs
    self._name = name

    self._loop = asyncio.new_event_loop()
    self._thread = threading.Thread(target=self._run_loop, daemon=True)
    self._thread.start()
    self._closed = False

    self._queue: Queue = asyncio.run_coroutine_threadsafe(self._create_queue(), self._loop).result()

close

close() -> None

Stop the background event loop and join its thread.

Safe to call more than once.

Source code in src/sheppy/experimental/_sync_queue.py
72
73
74
75
76
77
78
79
80
81
def close(self) -> None:
    """Stop the background event loop and join its thread.

    Safe to call more than once.
    """
    if self._closed:
        return
    self._closed = True
    self._loop.call_soon_threadsafe(self._loop.stop)
    self._thread.join(timeout=5)

add

add(task: Task[R]) -> Task[R] | None
add(task: list[Task[R]]) -> list[Task[R] | None]

Add task into the queue. Accept list of tasks for batch add.

PARAMETER DESCRIPTION
task

Instance of a Task, or list of Task instances for batch mode.

TYPE: Task[R] | list[Task[R]]

RETURNS DESCRIPTION
Task[R] | None | list[Task[R] | None]

The added task, or None if its ID already exists. In batch mode,

Task[R] | None | list[Task[R] | None]

returns a list in input order with None for tasks that already exist.

Source code in src/sheppy/experimental/_sync_queue.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def add(self, task: Task[R] | list[Task[R]]) -> Task[R] | None | list[Task[R] | None]:
    """Add task into the queue. Accept list of tasks for batch add.

    Args:
        task: Instance of a Task, or list of Task instances for batch mode.

    Returns:
        The added task, or None if its ID already exists. In batch mode,
        returns a list in input order with None for tasks that already exist.
    """
    if isinstance(task, list):  # mypy needs this
        return self._run_coro(self._queue.add(task))
    return self._run_coro(self._queue.add(task))

get_task

get_task(task: Task[R] | UUID | str) -> Task[R] | None
get_task(
    task: list[Task[R] | UUID | str],
) -> dict[UUID, Task[R]]

Get task by id.

PARAMETER DESCRIPTION
task

Instance of a Task or its ID, or list of Task instances/IDs for batch mode.

TYPE: Task[R] | UUID | str | list[Task[R] | UUID | str]

RETURNS DESCRIPTION
Task[R] | None | dict[UUID, Task[R]]

Instance of a Task or None if not found.
In batch mode, returns Dictionary of Task IDs to Task instances.

Source code in src/sheppy/experimental/_sync_queue.py
118
119
120
121
122
123
124
125
126
127
def get_task(self, task: Task[R] | UUID | str | list[Task[R] | UUID | str]) -> Task[R] | None | dict[UUID, Task[R]]:
    """Get task by id.

    Args:
        task: Instance of a Task or its ID, or list of Task instances/IDs for batch mode.

    Returns:
        Instance of a Task or None if not found.<br>In *batch mode*, returns Dictionary of Task IDs to Task instances.
    """
    return self._run_coro(self._queue.get_task(task))

get_all_tasks

get_all_tasks() -> list[Task]

Get all tasks, including completed/failed ones.

RETURNS DESCRIPTION
list[Task]

List of all tasks

Source code in src/sheppy/experimental/_sync_queue.py
129
130
131
132
133
134
135
def get_all_tasks(self) -> list[Task]:
    """Get all tasks, including completed/failed ones.

    Returns:
        List of all tasks
    """
    return self._run_coro(self._queue.get_all_tasks())

get_pending

get_pending(count: int = 1) -> list[Task]

List pending tasks.

PARAMETER DESCRIPTION
count

Number of pending tasks to retrieve.

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
list[Task]

List of pending tasks

Source code in src/sheppy/experimental/_sync_queue.py
137
138
139
140
141
142
143
144
145
146
def get_pending(self, count: int = 1) -> list[Task]:
    """List pending tasks.

    Args:
        count: Number of pending tasks to retrieve.

    Returns:
        List of pending tasks
    """
    return self._run_coro(self._queue.get_pending(count))

schedule

schedule(
    task: Task[R], at: datetime | timedelta
) -> Task[R] | None

Schedule task to be processed after certain time.

PARAMETER DESCRIPTION
task

Instance of a Task

TYPE: Task[R]

at

When to process the task.
If timedelta is provided, it will be added to current time.
Note: datetime must be offset-aware (i.e. have timezone info).

TYPE: datetime | timedelta

RETURNS DESCRIPTION
Task[R] | None

The scheduled task, or None if its ID already exists.

Source code in src/sheppy/experimental/_sync_queue.py
148
149
150
151
152
153
154
155
156
157
158
159
160
def schedule(self, task: Task[R], at: datetime | timedelta) -> Task[R] | None:
    """Schedule task to be processed after certain time.

    Args:
        task: Instance of a Task
        at: When to process the task.<br>
            If timedelta is provided, it will be added to current time.<br>
            *Note: datetime must be offset-aware (i.e. have timezone info).*

    Returns:
        The scheduled task, or None if its ID already exists.
    """
    return self._run_coro(self._queue.schedule(task, at))

get_scheduled

get_scheduled() -> list[Task]

List scheduled tasks.

RETURNS DESCRIPTION
list[Task]

List of scheduled tasks

Source code in src/sheppy/experimental/_sync_queue.py
162
163
164
165
166
167
168
def get_scheduled(self) -> list[Task]:
    """List scheduled tasks.

    Returns:
        List of scheduled tasks
    """
    return self._run_coro(self._queue.get_scheduled())

retry

retry(
    task: Task[R] | UUID | str,
    at: datetime | timedelta | None = None,
    force: bool = False,
) -> Task[R] | None

Retry failed task.

PARAMETER DESCRIPTION
task

Instance of a Task or its ID

TYPE: Task[R] | UUID | str

at

When to retry the task.
- If None (default), retries immediately.
- If timedelta is provided, it will be added to current time.
Note: datetime must be offset-aware (i.e. have timezone info).

TYPE: datetime | timedelta | None DEFAULT: None

force

If True, allows retrying even if task has completed successfully. Defaults to False.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
Task[R] | None

The re-queued task, or None if no task with the given ID exists.

RAISES DESCRIPTION
ValueError

If task has already completed successfully and force is not set to True.

TypeError

If provided datetime is not offset-aware.

Source code in src/sheppy/experimental/_sync_queue.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
def retry(self, task: Task[R] | UUID | str, at: datetime | timedelta | None = None, force: bool = False) -> Task[R] | None:
    """Retry failed task.

    Args:
        task: Instance of a Task or its ID
        at: When to retry the task.<br>
            - If None (default), retries immediately.<br>
            - If timedelta is provided, it will be added to current time.<br>
            *Note: datetime must be offset-aware (i.e. have timezone info).*
        force: If True, allows retrying even if task has completed successfully. Defaults to False.

    Returns:
        The re-queued task, or None if no task with the given ID exists.

    Raises:
        ValueError: If task has already completed successfully and force is not set to True.
        TypeError: If provided datetime is not offset-aware.
    """
    return self._run_coro(self._queue.retry(task, at, force))

cancel

cancel(task: Task | UUID | str) -> Task

Cancel a pending or scheduled task.

PARAMETER DESCRIPTION
task

Instance of a Task or its ID.

TYPE: Task | UUID | str

RETURNS DESCRIPTION
Task

The updated Task instance with status 'cancelled'.

RAISES DESCRIPTION
TaskCancellationError

If the task cannot be cancelled - either it was already claimed by a worker, it already finished, or it does not exist.

Source code in src/sheppy/experimental/_sync_queue.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
def cancel(self, task: Task | UUID | str) -> Task:
    """Cancel a pending or scheduled task.

    Args:
        task: Instance of a Task or its ID.

    Returns:
        The updated Task instance with status 'cancelled'.

    Raises:
        TaskCancellationError: If the task cannot be cancelled - either it
            was already claimed by a worker, it already finished, or it
            does not exist.
    """
    return self._run_coro(self._queue.experimental.cancel(task))

delete

delete(task: Task | UUID | str) -> bool

Hard-delete a finished task's stored metadata.

Only tasks in a terminal state (completed, failed, crashed, cancelled) can be deleted.

PARAMETER DESCRIPTION
task

Instance of a Task or its ID.

TYPE: Task | UUID | str

RETURNS DESCRIPTION
bool

True if the task existed and was deleted, False if it was not found.

RAISES DESCRIPTION
ValueError

If the task has not finished yet.

Source code in src/sheppy/experimental/_sync_queue.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def delete(self, task: Task | UUID | str) -> bool:
    """Hard-delete a finished task's stored metadata.

    Only tasks in a terminal state (completed, failed, crashed, cancelled) can be deleted.

    Args:
        task: Instance of a Task or its ID.

    Returns:
        True if the task existed and was deleted, False if it was not found.

    Raises:
        ValueError: If the task has not finished yet.
    """
    return self._run_coro(self._queue.experimental.delete(task))

size

size() -> int

Get number of pending tasks in the queue.

RETURNS DESCRIPTION
int

Number of pending tasks

Source code in src/sheppy/experimental/_sync_queue.py
222
223
224
225
226
227
228
def size(self) -> int:
    """Get number of pending tasks in the queue.

    Returns:
        Number of pending tasks
    """
    return self._run_coro(self._queue.size())

clear

clear() -> int

Clear all tasks, including completed ones.

RETURNS DESCRIPTION
int

Number of stored task entries removed.

Source code in src/sheppy/experimental/_sync_queue.py
230
231
232
233
234
235
236
def clear(self) -> int:
    """Clear all tasks, including completed ones.

    Returns:
        Number of stored task entries removed.
    """
    return self._run_coro(self._queue.clear())

add_cron

add_cron(task: Task, cron: str) -> TaskCron | None

Add a cron job to run a task on a schedule.

PARAMETER DESCRIPTION
task

Instance of a Task

TYPE: Task

cron

Cron expression string (e.g. "*/5 * * * *" to run every 5 minutes)

TYPE: str

RETURNS DESCRIPTION
TaskCron | None

The added cron, or None if an identical cron already exists.

Source code in src/sheppy/experimental/_sync_queue.py
238
239
240
241
242
243
244
245
246
247
248
def add_cron(self, task: Task, cron: str) -> TaskCron | None:
    """Add a cron job to run a task on a schedule.

    Args:
        task: Instance of a Task
        cron: Cron expression string (e.g. "*/5 * * * *" to run every 5 minutes)

    Returns:
        The added cron, or None if an identical cron already exists.
    """
    return self._run_coro(self._queue.add_cron(task, cron))

delete_cron

delete_cron(task: Task, cron: str) -> bool

Delete a cron job.

PARAMETER DESCRIPTION
task

Instance of a Task

TYPE: Task

cron

Cron expression string used when adding the cron job

TYPE: str

RETURNS DESCRIPTION
bool

Success boolean

Source code in src/sheppy/experimental/_sync_queue.py
250
251
252
253
254
255
256
257
258
259
260
def delete_cron(self, task: Task, cron: str) -> bool:
    """Delete a cron job.

    Args:
        task: Instance of a Task
        cron: Cron expression string used when adding the cron job

    Returns:
        Success boolean
    """
    return self._run_coro(self._queue.delete_cron(task, cron))

get_crons

get_crons() -> list[TaskCron]

List all cron jobs.

RETURNS DESCRIPTION
list[TaskCron]

List of TaskCron instances

Source code in src/sheppy/experimental/_sync_queue.py
262
263
264
265
266
267
268
def get_crons(self) -> list[TaskCron]:
    """List all cron jobs.

    Returns:
        List of TaskCron instances
    """
    return self._run_coro(self._queue.get_crons())

wait_for

wait_for(
    task: Task[R] | UUID | str, timeout: float = 0
) -> Task[R] | None
wait_for(
    task: list[Task[R] | UUID | str], timeout: float = 0
) -> dict[UUID, Task[R]]

Wait for task to complete and return updated task instance.

Blocks the calling thread until the task finishes; use timeout to bound the wait.

PARAMETER DESCRIPTION
task

Instance of a Task or its ID, or list of Task instances/IDs for batch mode.

TYPE: Task[R] | UUID | str | list[Task[R] | UUID | str]

timeout

Maximum time to wait in seconds. Default is 0 (wait indefinitely).
If timeout is reached, returns None (or partial results in batch mode).
In batch mode, this is the maximum time to wait for all tasks to complete.
Note: In non-batch mode, if timeout is reached and no task is found, a TimeoutError is raised.

TYPE: float DEFAULT: 0

RETURNS DESCRIPTION
Task[R] | None | dict[UUID, Task[R]]

Instance of a Task or None if not found or timeout reached.
In batch mode, returns dictionary of Task IDs to Task instances (partial results possible on timeout).

RAISES DESCRIPTION
TimeoutError

If timeout is reached and no task is found (only in non-batch mode).

Source code in src/sheppy/experimental/_sync_queue.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
def wait_for(self, task: Task[R] | UUID | str | list[Task[R] | UUID | str], timeout: float = 0) -> Task[R] | None | dict[UUID, Task[R]]:
    """Wait for task to complete and return updated task instance.

    Blocks the calling thread until the task finishes; use `timeout`
    to bound the wait.

    Args:
        task: Instance of a Task or its ID, or list of Task instances/IDs for batch mode.
        timeout: Maximum time to wait in seconds. Default is 0 (wait indefinitely).<br>
                 If timeout is reached, returns None (or partial results in batch mode).<br>
                 In batch mode, this is the maximum time to wait for all tasks to complete.<br>
                 Note: In non-batch mode, if timeout is reached and no task is found, a TimeoutError is raised.

    Returns:
        Instance of a Task or None if not found or timeout reached.<br>In batch mode, returns dictionary of Task IDs to Task instances (partial results possible on timeout).

    Raises:
        TimeoutError: If timeout is reached and no task is found (only in non-batch mode).
    """
    return self._run_coro(self._queue.wait_for(task, timeout))

add_workflow

add_workflow(workflow: Workflow) -> WorkflowResult

Add a workflow into the queue.

Source code in src/sheppy/experimental/_sync_queue.py
297
298
299
def add_workflow(self, workflow: Workflow) -> WorkflowResult:
    """Add a workflow into the queue."""
    return self._run_coro(self._queue.experimental.add_workflow(workflow))

wait_for_workflow

wait_for_workflow(
    workflow: Workflow | UUID | str, timeout: float = 0
) -> Workflow | None
wait_for_workflow(
    workflow: list[Workflow | UUID | str],
    timeout: float = 0,
) -> dict[UUID, Workflow]

Wait for workflow to finish (complete or fail) and return the updated workflow.

PARAMETER DESCRIPTION
workflow

Instance of a Workflow or its ID, or list of Workflow instances/IDs for batch mode.

TYPE: Workflow | UUID | str | list[Workflow | UUID | str]

timeout

Maximum time to wait in seconds. Default is 0 (wait indefinitely).

TYPE: float DEFAULT: 0

RETURNS DESCRIPTION
Workflow | None | dict[UUID, Workflow]

The finished Workflow, or None if not found.
In batch mode, returns a dictionary of Workflow IDs to finished Workflow instances.

RAISES DESCRIPTION
TimeoutError

If a positive timeout expires before all given workflows have finished.

Source code in src/sheppy/experimental/_sync_queue.py
307
308
309
310
311
312
313
314
315
316
317
318
319
320
def wait_for_workflow(self, workflow: Workflow | UUID | str | list[Workflow | UUID | str], timeout: float = 0) -> Workflow | None | dict[UUID, Workflow]:
    """Wait for workflow to finish (complete or fail) and return the updated workflow.

    Args:
        workflow: Instance of a Workflow or its ID, or list of Workflow instances/IDs for batch mode.
        timeout: Maximum time to wait in seconds. Default is 0 (wait indefinitely).

    Returns:
        The finished Workflow, or None if not found.<br>In *batch mode*, returns a dictionary of Workflow IDs to finished Workflow instances.

    Raises:
        TimeoutError: If a positive timeout expires before all given workflows have finished.
    """
    return self._run_coro(self._queue.experimental.wait_for_workflow(workflow, timeout))

get_workflow

get_workflow(
    workflow: Workflow | UUID | str,
) -> Workflow | None
get_workflow(
    workflow: list[Workflow | UUID | str],
) -> dict[UUID, Workflow]

Get workflow by id.

PARAMETER DESCRIPTION
workflow

Instance of a Workflow or its ID, or list of Workflow instances/IDs for batch mode.

TYPE: Workflow | UUID | str | list[Workflow | UUID | str]

RETURNS DESCRIPTION
Workflow | None | dict[UUID, Workflow]

Instance of a Workflow or None if not found.
In batch mode, returns Dictionary of Workflow IDs to Workflow instances.

Source code in src/sheppy/experimental/_sync_queue.py
328
329
330
331
332
333
334
335
336
337
def get_workflow(self, workflow: Workflow | UUID | str | list[Workflow | UUID | str]) -> Workflow | None | dict[UUID, Workflow]:
    """Get workflow by id.

    Args:
        workflow: Instance of a Workflow or its ID, or list of Workflow instances/IDs for batch mode.

    Returns:
        Instance of a Workflow or None if not found.<br>In *batch mode*, returns Dictionary of Workflow IDs to Workflow instances.
    """
    return self._run_coro(self._queue.experimental.get_workflow(workflow))

get_all_workflows

get_all_workflows() -> list[Workflow]

Get all stored workflows, including completed/failed ones.

RETURNS DESCRIPTION
list[Workflow]

List of all Workflow instances

Source code in src/sheppy/experimental/_sync_queue.py
339
340
341
342
343
344
345
def get_all_workflows(self) -> list[Workflow]:
    """Get all stored workflows, including completed/failed ones.

    Returns:
        List of all Workflow instances
    """
    return self._run_coro(self._queue.experimental.get_all_workflows())

get_pending_workflows

get_pending_workflows() -> list[Workflow]

Get workflows that are neither completed nor errored.

RETURNS DESCRIPTION
list[Workflow]

List of pending Workflow instances

Source code in src/sheppy/experimental/_sync_queue.py
347
348
349
350
351
352
353
def get_pending_workflows(self) -> list[Workflow]:
    """Get workflows that are neither completed nor errored.

    Returns:
        List of pending Workflow instances
    """
    return self._run_coro(self._queue.experimental.get_pending_workflows())

delete_workflow

delete_workflow(workflow: Workflow | UUID | str) -> bool

Delete a workflow.

PARAMETER DESCRIPTION
workflow

Instance of a Workflow or its ID

TYPE: Workflow | UUID | str

RETURNS DESCRIPTION
bool

True if the workflow existed and was deleted.

Source code in src/sheppy/experimental/_sync_queue.py
355
356
357
358
359
360
361
362
363
364
def delete_workflow(self, workflow: Workflow | UUID | str) -> bool:
    """Delete a workflow.

    Args:
        workflow: Instance of a Workflow or its ID

    Returns:
        True if the workflow existed and was deleted.
    """
    return self._run_coro(self._queue.experimental.delete_workflow(workflow))