ProvenPin Install

APScheduler BackgroundScheduler with an in-memory jobstore: working versions (tested 2026-10-16)

Register interval and one-off jobs on a BackgroundScheduler backed by MemoryJobStore, then test scheduling, replacement and execution offline without a persistent store.

passed6 passed · 0 failed2026-10-16 00:01 UTC
Status
passed
Last passed
2026-10-16 00:01 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions2
apscheduler@3.11.3pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38826982604

The code

Exactly the files that passed. Your agent can pull them with get_recipe("apscheduler-memory-jobstore") (install), or see them on GitHub.

requirements.txt
apscheduler==3.11.3
pytest==9.1.1
scheduler.py
from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.schedulers.background import BackgroundScheduler


def build_scheduler(paused: bool = False) -> BackgroundScheduler:
    # MemoryJobStore holds jobs in this process only; nothing survives a restart.
    scheduler = BackgroundScheduler(
        jobstores={"default": MemoryJobStore()},
        executors={"default": ThreadPoolExecutor(2)},
        job_defaults={"coalesce": True, "max_instances": 1, "misfire_grace_time": 5},
    )
    scheduler.start(paused=paused)
    return scheduler


def schedule_interval(scheduler, func, seconds, job_id):
    return scheduler.add_job(func, "interval", seconds=seconds, id=job_id)


def schedule_once(scheduler, func, run_at, job_id):
    return scheduler.add_job(func, "date", run_date=run_at, id=job_id)
tests/test_scheduler.py
import threading
import time
from datetime import datetime, timedelta, timezone

import pytest
from apscheduler.jobstores.base import ConflictingIdError
from apscheduler.jobstores.memory import MemoryJobStore

from scheduler import build_scheduler, schedule_interval, schedule_once


def test_default_jobstore_is_memory():
    s = build_scheduler()
    assert isinstance(s._jobstores["default"], MemoryJobStore)
    s.shutdown(wait=False)


def test_jobs_live_only_in_memory():
    s = build_scheduler()
    schedule_interval(s, lambda: None, 60, "tick")
    assert s.get_job("tick") is not None
    s.shutdown(wait=False)
    fresh = build_scheduler()
    assert fresh.get_job("tick") is None
    fresh.shutdown(wait=False)


def test_duplicate_id_conflicts_unless_replaced():
    s = build_scheduler()
    schedule_interval(s, lambda: None, 60, "tick")
    with pytest.raises(ConflictingIdError):
        schedule_interval(s, lambda: None, 30, "tick")
    job = s.add_job(lambda: None, "interval", seconds=30, id="tick", replace_existing=True)
    assert job.trigger.interval.total_seconds() == 30
    s.shutdown(wait=False)


def test_interval_next_run_time_is_future():
    s = build_scheduler()
    before = datetime.now(timezone.utc)
    job = schedule_interval(s, lambda: None, 5, "tick")
    assert job.next_run_time > before
    s.shutdown(wait=False)


def test_paused_scheduler_defers_until_resumed():
    ran = threading.Event()
    s = build_scheduler(paused=True)
    schedule_interval(s, ran.set, 0.05, "tick")
    assert not ran.wait(0.2)
    s.resume()
    assert ran.wait(2)
    s.shutdown(wait=False)


def test_date_job_runs_once_then_disappears():
    ran = threading.Event()
    s = build_scheduler()
    schedule_once(s, ran.set, datetime.now(timezone.utc) - timedelta(seconds=1), "once")
    assert ran.wait(2)
    for _ in range(50):
        if s.get_job("once") is None:
            break
        time.sleep(0.02)
    assert s.get_job("once") is None
    s.shutdown(wait=False)
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.