import queue
import time
from dataclasses import dataclass, field, replace
from typing import Any, Dict, Tuple
@dataclass(frozen=True)
class Job:
task_name: str
args: Tuple[Any, ...] = ()
kwargs: Dict[str, Any] = field(default_factory=dict)
attempts: int = 0
enqueued_at: float = field(default_factory=time.time)
def retried(self) -> "Job":
return replace(self, attempts=self.attempts + 1)
class JobQueue:
def __init__(self, maxsize: int = 1000):
self._q: "queue.Queue[Job]" = queue.Queue(maxsize=maxsize)
def enqueue(self, task_name, *args, **kwargs) -> None:
job = Job(task_name=task_name, args=args, kwargs=kwargs)
self._q.put(job)
def put(self, job: Job) -> None:
self._q.put(job)
def get(self, timeout=None) -> Job:
return self._q.get(timeout=timeout)
def task_done(self) -> None:
self._q.task_done()
def join(self) -> None:
self._q.join()
import logging
import queue
import threading
from email_tasks import TASK_REGISTRY
from job_queue import JobQueue
log = logging.getLogger("worker")
class Worker:
def __init__(self, job_queue: JobQueue, concurrency: int = 2, max_retries: int = 3):
self._q = job_queue
self._concurrency = concurrency
self._max_retries = max_retries
self._stopping = threading.Event()
self._threads = []
def start(self) -> None:
for i in range(self._concurrency):
t = threading.Thread(target=self._run, name=f"worker-{i}", daemon=True)
t.start()
self._threads.append(t)
log.info("started %d worker threads", self._concurrency)
def _run(self) -> None:
while not self._stopping.is_set():
try:
job = self._q.get(timeout=0.5)
except queue.Empty:
continue
try:
fn = TASK_REGISTRY[job.task_name]
fn(*job.args, **job.kwargs)
except Exception:
self._handle_failure(job)
finally:
self._q.task_done()
def _handle_failure(self, job) -> None:
if job.attempts + 1 >= self._max_retries:
log.exception("dropping job %s after %d attempts", job.task_name, job.attempts + 1)
return
log.warning("retrying job %s (attempt %d)", job.task_name, job.attempts + 1)
self._q.put(job.retried())
def drain(self) -> None:
self._q.join()
def stop(self, drain: bool = True) -> None:
if drain:
self.drain()
self._stopping.set()
for t in self._threads:
t.join(timeout=5)
log.info("worker stopped")
import logging
import smtplib
from email.message import EmailMessage
log = logging.getLogger("email")
def send_welcome_email(to_addr: str, name: str) -> None:
msg = EmailMessage()
msg["To"] = to_addr
msg["From"] = "hello@example.com"
msg["Subject"] = "Welcome aboard!"
msg.set_content(f"Hi {name}, thanks for signing up.")
with smtplib.SMTP("localhost", 25, timeout=10) as smtp:
smtp.send_message(msg)
log.info("sent welcome email to %s", to_addr)
def send_password_reset(to_addr: str, token: str) -> None:
msg = EmailMessage()
msg["To"] = to_addr
msg["From"] = "security@example.com"
msg["Subject"] = "Reset your password"
msg.set_content(f"Use this link: https://example.com/reset?t={token}")
with smtplib.SMTP("localhost", 25, timeout=10) as smtp:
smtp.send_message(msg)
log.info("sent reset email to %s", to_addr)
TASK_REGISTRY = {
"send_welcome_email": send_welcome_email,
"send_password_reset": send_password_reset,
}
import atexit
import logging
import signal
from job_queue import JobQueue
from worker import Worker
logging.basicConfig(level=logging.INFO)
jobs = JobQueue(maxsize=500)
worker = Worker(jobs, concurrency=3, max_retries=3)
worker.start()
def enqueue_email(task_name: str, *args, **kwargs) -> None:
jobs.enqueue(task_name, *args, **kwargs)
def _shutdown(*_args) -> None:
logging.getLogger("app").info("draining jobs before exit")
worker.stop(drain=True)
atexit.register(_shutdown)
signal.signal(signal.SIGTERM, lambda *_: _shutdown())
if __name__ == "__main__":
enqueue_email("send_welcome_email", "ada@example.com", name="Ada")
enqueue_email("send_password_reset", "grace@example.com", token="abc123")
worker.drain()
This snippet shows a minimal, dependency-free background job system built on Python's standard library, useful when a project needs deferred work like sending emails but does not want to run Redis, RabbitMQ, or Celery. It trades durability for simplicity: jobs live in an in-memory queue.Queue, so anything unprocessed at shutdown is lost. That trade-off is acceptable for low-stakes side effects (welcome emails, cache warming) on a single process, but not for money-critical work.
The job_queue tab defines the primitives. A Job is a frozen dataclass carrying a callable name, its args/kwargs, and an attempts counter that supports retries. JobQueue wraps a bounded queue.Queue; enqueue builds a Job and calls put, while get and task_done mirror the standard queue API so the worker can cooperate with join(). Bounding the queue provides natural backpressure — if producers outrun consumers, enqueue blocks instead of exhausting memory.
The worker tab is where concurrency lives. Worker spawns a pool of daemon threading.Threads, each running _run, which loops on queue.get(timeout=...). Using a timeout rather than a blocking get lets the loop periodically check _stopping, an threading.Event, so shutdown is responsive. When a task raises, _handle_failure re-enqueues it with an incremented attempts until max_retries is hit, then logs and drops it. stop sets the event and joins the threads, and drain calls the queue's join() so callers can wait for in-flight work — the key to a graceful shutdown that does not strand half-sent batches.
The email_tasks tab registers the actual work. send_welcome_email is an ordinary function looked up by name from a TASK_REGISTRY; keeping tasks name-addressable (rather than pickling closures) keeps the queue serialization-friendly if it is later swapped for a real broker. The app tab wires everything together: it constructs the Worker, exposes enqueue_email, and registers an atexit hook plus a SIGTERM handler so a container stop drains pending jobs before exit. GIL contention makes this best for I/O-bound work like SMTP calls, exactly the email case shown here.
Related snips
import os
import stat
for root, _dirs, files in os.walk('/etc'):
for name in files:
path = os.path.join(root, name)
Python security audit script for exposed risky filesystem state
class Product(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
cost = models.DecimalField(max_digits=10, decimal_places=2)
margin = models.DecimalField(max_digits=5, decimal_places=2, blank=True)
Django model signals vs overriding save
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
use crossbeam::channel::unbounded;
use std::thread;
fn main() {
let (tx, rx) = unbounded();
Crossbeam for advanced concurrent data structures
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
Promises and async/await patterns for asynchronous JavaScript
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
Channels (mpsc) for message passing between threads
Share this code
Here's the card — post it anywhere.