std.scheduler
runner, program, spawn, and scheduled task lifecycle
std.scheduler is a higher-level standard library family in foundation-base. This page explains when to use it, how it fits internally, and where to find the API surface.
1 Motivation
Use this layer when application or tooling code needs the behavior described by the page title without reaching directly into implementation namespaces. The top-level namespace is the starting point; subnamespaces expose more focused building blocks.
2 How to use it
Require the top-level namespace for common workflows, then move to subnamespaces when you need a lower-level primitive. Existing tests under test/std/scheduler and test/std/scheduler_test.clj are the best executable examples for edge cases.
create and inspect a runner
(component/with [runner (runner:create)]
(runner:info runner))
=> {:executors {:core {:threads 0 :active 0 :queued 0 :terminated false}
:scheduler {:threads 0 :active 0 :queued 0 :terminated false}}
:programs {}}
install and trigger a program
(component/with [runner (runner:create)]
(let [q (java.util.concurrent.LinkedBlockingQueue.)]
(install runner {:id :hello
:type :basic
:interval 100
:main-fn (fn [_ t] (.put q t))})
(trigger runner :hello)
(boolean (.poll q 1000 java.util.concurrent.TimeUnit/MILLISECONDS))))
=> true
3 Internal usage
This library family is used across source, tests, generated examples, and docs tooling. During detailed documentation passes, collect concrete usage with code.manage/find-usages and code.manage/locate-code, then keep only high-signal examples in the page narrative.
4 API
5 std.scheduler Guide
std.scheduler is a system for managing concurrent, scheduled tasks (programs) using a runner abstraction. It handles lifecycle, spawning, and scaling of these tasks.
5.1 Core Concepts
- Runner: The container for all scheduling logic. It has its own thread pools.n- Program: A definition of a task, including its logic (
main-fn), state (create-fn), and frequency (interval).n- Spawn: An executing instance of a program. A single program (like "send-email") might have multiple spawns (workers).
5.2 Usage
5.2.1 Scenarios
5.2.1.1 1. Periodic "Cron" Job
Scenario: Run a cleanup task every minute.
(require '[std.scheduler :as scheduler]\n '[std.lib :as h])\n\n(def runner (scheduler/runner {:id \"system-runner\"}))\n\n(def cleanup-job\n {:id :cleanup\n :interval 60000 ;; 60s\n :create-fn (constantly {:deleted 0}) ;; Initial state\n :main-fn (fn [args timestamp]\n ;; Perform cleanup logic\n (println \"Cleaning up at\" timestamp)\n {:count 1}) ;; Return value updates state if merge-fn is defined\n })\n\n(scheduler/install runner cleanup-job)\n(scheduler/spawn runner :cleanup) ;; Start one instance
5.2.1.2 2. Worker Pool Pattern
Scenario: A job queue that needs multiple workers processing in parallel.
You can define a program and then spawn it multiple times.
(def worker-job\n {:id :worker\n :interval 100 ;; Check queue every 100ms\n :main-fn (fn [_ _]\n (when-let [job (pop-queue!)]\n (process job)))\n ;; Optional: Define limits\n :min 1\n :max 5})\n\n(scheduler/install runner worker-job)\n\n;; Scale up\n(dotimes [_ 3]\n (scheduler/spawn runner :worker))
5.2.1.3 3. Dynamic Scaling
Scenario: Increase workers during high load.
You can programmatically spawn or unspawn instances based on metrics.
(defn check-load [runner]\n (let [q-size (get-queue-size)]\n (cond\n (> q-size 100) (scheduler/spawn runner :worker)\n (< q-size 10) (scheduler/unspawn runner :worker))))
unspawn removes one instance, respecting the policy (e.g., kill the :last created one).
5.2.1.4 4. Manual Triggering
Scenario: Force execution immediately (e.g., via Admin UI).
You don't need to wait for the interval.
(scheduler/trigger runner :cleanup)
5.2.1.5 5. Managing State
Scenario: Accumulating results.
The merge-fn allows a program to update its :state atom based on the return value of main-fn.
(def stats-job\n {:id :stats\n :interval 1000\n :create-fn (constantly 0)\n :main-fn (fn [_ _] (rand-int 10))\n :merge-fn (fn [old-state new-val]\n (+ old-state new-val))})\n\n;; Access state\n(scheduler/get-state runner :stats)
6 std.scheduler: A Comprehensive Summary (including submodules)
The std.scheduler module provides a robust and flexible framework for scheduling and managing asynchronous tasks in Clojure applications. It builds upon std.concurrent to leverage thread pools and queues, offering features like program installation, dynamic spawning of tasks, and comprehensive monitoring of task execution. The module is designed to handle various scheduling policies and provides detailed information about running and completed tasks.
6.1 std.scheduler (Main Namespace)
This namespace serves as the primary entry point for the scheduling system, aggregating and re-exporting key functionalities from its submodules. It defines the core Runner component and provides high-level functions for managing scheduled programs.
Core Concepts:
RunnerComponent: The central component that manages scheduled programs and their execution. It encapsulates the underlying executors and program states.n Programs: Definitions of tasks to be scheduled, including their type, execution policy, and associated functions.n Spawns: Individual instances of a running program.
Key Functions:
get-spawn,stop-spawn,kill-spawn: Functions for managing individual spawns.nget-all-spawn,count-spawn,list-spawn,latest-spawn,earliest-spawn,list-stopped,latest-stopped,latest,stop-all-spawn,kill-all-spawn,clear,get-state,get-program: Functions for managing all spawns of a program.nrunner:start,runner:stop,runner:kill: Lifecycle functions for theRunner.nrunner:started?,runner:stopped?,runner:health,runner:info: Status and introspection functions for theRunner.nrunner?,runner:create,runner: Predicate and constructors forRunnerrecords.ninstalled?,create-program,uninstall,install: Functions for managing program definitions.nspawn,unspawn: Functions for dynamically starting and stopping program instances.ntrigger: Manually triggers a program's execution.nset-interval: Dynamically adjusts the interval of a running program.n*get-props: Retrieves properties of running spawns.
6.2 std.scheduler.common (Common Scheduler Utilities)
This sub-namespace provides shared helper functions for managing the scheduler's runtime environment, including executor creation and lifecycle management.
Key Functions:
new-runtime: Constructs a new runtime environment for the scheduler, includingcoreandschedulerexecutors.nstop-runtime: Stops all executors within a runtime.nkill-runtime: Forcefully stops all executors within a runtime.nall-ids: Returns all running program IDs.nspawn-form,gen-spawn(macro): Generates spawn-related forms.n*spawn-all-form,gen-spawn-all(macro): Generates forms for all spawns.
6.3 std.scheduler.spawn (Task Spawning and Management)
This sub-namespace provides the core logic for spawning and managing individual task instances (spawns), including their lifecycle, job management, and result handling.
Core Concepts:
SpawnRecord: Represents a single instance of a running program, tracking its ID, properties, output, state, and exit status.n Jobs: Individual tasks submitted to a spawn.n Program Definitions: Configurable properties for a scheduled program (e.g.,type,policy,interval,main-fn,args-fn).
Key Functions:
spawn-status: Returns the status of a spawn.nspawn-info: Returns detailed information about a spawn.nspawn?,create-spawn: Predicate and constructor forSpawnrecords.nset-props,get-props: Sets or retrieves properties of a spawn.nget-job,update-job,remove-job,add-job,list-jobs,list-job-ids,count-jobs: Functions for managing jobs within a spawn.nsend-result: Sends a result to a spawn's output.nhandler-run: Executes a job's main function and handles results.ncreate-handler-basic,create-handler-constant,create-handler: Creates different types of job handlers.nschedule-timing: Calculates the timing for the next schedule.nwrap-schedule: Wraps a schedule function.nspawn-save-past: Moves a spawn from running to past.nspawn-loop: Creates the main loop for a spawn.nrun: Constructs and starts a spawn loop.nget-all-spawn,get-spawn,count-spawn,list-spawn,latest-spawn,earliest-spawn: Functions for retrieving running spawns.nlist-stopped,latest-stopped,latest: Functions for retrieving stopped spawns.nstop-spawn,kill-spawn: Stops or kills a spawn.nstop-all,kill-all: Stops or kills all spawns of a program.nclear: Clears program and past spawn information.nget-state,get-program: Retrieves program state or definition.
6.4 std.scheduler.types (Scheduler Contracts)
This sub-namespace defines Malli schemas (contracts) for scheduler configurations, ensuring type safety and valid input for program definitions.
Key Functions:
+runtime+: Schema for runtime options.n+spawn+: Schema for spawn options.n+program+: Schema for program definitions.n*<program>: The main schema for a scheduled program.
6.5 Usage Pattern:
The std.scheduler module is essential for building applications that require automated or periodic task execution. It provides:
- Flexible Scheduling: Support for various program types (e.g.,
:basic,:constant) and scheduling policies.n Concurrency Management: Leveragesstd.concurrentfor efficient task execution.n Program Lifecycle: Functions for installing, uninstalling, spawning, and stopping programs.n Monitoring and Introspection: Detailed information about running and completed tasks.n Extensibility: A protocol-driven design allows for custom program types and handlers.
By offering a comprehensive and extensible task scheduling framework, std.scheduler empowers developers to build robust and reliable automated systems.