Getting Started¶
Installation¶
From PyPI¶
From source¶
Starting PostgreSQL¶
docker run -d --name lapinq-db \
-e POSTGRES_USER=lapinq \
-e POSTGRES_PASSWORD=lapinq \
-e POSTGRES_DB=lapinq \
-p 5432:5432 \
postgres:16-alpine
Start Server + Inline Worker (simplest)¶
Run both the HTTP server and task worker in a single process:
This is the easiest way to get started. The inline worker executes tasks in-process using the Rust executor (PyO3) for sync functions.
Start Server with Separate Worker¶
Terminal 1 — Server:¶
Terminal 2 — Python worker:¶
Terminal 2 — Rust worker (production):¶
Dashboard¶
Open http://localhost:8001 in your browser. The dashboard shows queue statistics and recent tasks with real-time updates via WebSocket.
The dashboard is protected by session-based authentication. On first run the server creates a default admin user automatically:
- Username:
lapinq - Password:
lapinq
After logging in, admins can create additional users, change passwords, and manage permissions from the dashboard's "Manage Users" page.
Your First Task¶
from lapinq import TaskQueue
tasks = TaskQueue(server_url="http://localhost:8001")
@tasks.task(name="hello")
def hello(name: str):
return f"Hello, {name}!"
# Enqueue — returns a TaskRef
ref = hello.queue(name="World")
print(ref.task_id) # "uuid-..."
print(ref.wait(timeout=30)) # poll for result
Task TTL (Time To Live)¶
Tasks expire automatically after a configurable time. Set ttl_seconds when enqueuing.
Keep for 1 day (86400s)¶
Keep for 1 minute (60s)¶
Don't persist (0 = no TTL, task remains until completed or archived)¶
ttl_seconds=0disables expiry for that task. The task remains indefinitely unless you delete it manually from the dashboard.
Enable periodic cleanup¶
The server must run with --cleanup-interval to expire tasks automatically:
This checks for expired tasks every 60 seconds. Without this flag, TTL is stored but never enforced.
Async Client¶
from lapinq import AsyncTaskQueue
async def main():
tasks = AsyncTaskQueue(server_url="http://localhost:8001")
@tasks.task(name="hello")
async def hello(name: str):
return f"Hello, {name}!"
ref = await hello.aqueue(name="World")
result = await ref.awaitait(timeout=30)
print(result["status"])
await tasks.close()