ores.scheduler.job_definition
Table of Contents
A job the scheduler fires on a cron expression. The row carries the schedule
(schedule_expression), what to run when it fires, and whether it is active.
action_type selects the behaviour: execute_sql runs the SQL in command,
and nats_publish publishes the subject and body carried in action_payload.
The table is bi-temporal and audited (see
projects/ores.sql/create/scheduler/scheduler_job_definitions_create.sql): it
carries version, the four audit columns and the valid_from=/=valid_to pair
with the GIST exclusion and the delete rule, so the model takes the ordinary
audited shape and needs no shape flag.
tenant_id is nullable. A job may belong to no tenant, because the scheduler
fires system jobs from a NULL-tenant row: the MQ statistics scrape and the
compute stale-result reaper are both such rows. The model binds
uuid-identified-lookup for its UUID surrogate key, its tenant scope and its
standard presentation tier, and states nullable_tenant_id itself, which that
profile leaves to the model.
job_name is the natural key and is unique within its tenant; id is the
surrogate. Uniqueness is what the component's upsert path relies on: a job that
arrives under an existing name updates that row in place instead of adding a
second one.
The component's operational views — the global job-instance list and the live
scheduler status — are operations rather than entity verbs, and are modelled
in ores.scheduler.scheduling_operations.
1. Flags
2. Natural keys
3. Columns
3.1. job_name
Unique name for the job within its tenant. The scheduler seed writes
ores.mq.metrics_scrape and the compute seed writes
compute.v1.reap.stale_results; both are system jobs, so both carry a NULL
tenant and neither collides with a tenant's own job of the same name.
3.2. id
UUID primary key for the job definition.
3.3. party_id
Optional party scope for this job. NULL for a tenant-scoped job and for a system job.
3.4. description
Human-readable description of the job.
3.5. command
SQL command to execute when action_type is execute_sql.
3.6. schedule_expression
Cron expression defining the schedule. It is the component's own validated
cron_expression type, so an invalid expression cannot enter the domain.
3.7. action_type
Execution mode: execute_sql or nats_publish.
3.8. action_payload
Payload for the nats_publish action type. The scheduler seed writes an empty
object; the compute seed writes {"subject":"compute.v1.work.reap"}.
3.9. is_active
Whether the job fires. A paused job keeps its row and its history.
4. SQL
4.1. Flags
5. Physical space
The shell commands for this entity are switched off. The ores.shell composite
does not carry a scheduler part yet, and the shell command registry is
hand-written, so enabling the facet here would generate command units and a
recipe for a module no build reaches. Adding the part to the shell component,
registering its commands, and then enabling this facet is the next unit of the
scheduler clean-up; the profile enables the facet, so this table states the
reason it is overridden.
| Address | Enabled |
|---|---|
| ores.cpp.shell-command | false |
6. C++
6.1. Flags
6.2. Repository
6.3. Domain includes
#include <chrono> #include <optional> #include <string> #include <boost/uuid/uuid.hpp>
6.4. Conventions
6.5. Table display
| column | header |
|---|---|
| id | ID |
| job_name | Job Name |
| description | Description |
| schedule_expression | Schedule |
| is_active | Active |
| modified_by | Modified By |
| version | Version |
6.6. Custom repository methods
The generated CRUD set reads by primary key and by the natural key. The scheduler loop needs a third read: every active job, across every tenant, because it fires system jobs as well as tenant ones. That read is the one method beyond the generated set, and it cannot be expressed by the generated by-column finder because it deliberately drops the tenant filter.
6.6.1. Repository declarations
/** * @brief Reads every active job definition, across all tenants. * * The scheduler loop fires system jobs as well as tenant ones, so it * cannot read through the tenant-scoped CRUD set. */ std::vector<domain::job_definition> read_all_active(context ctx);
6.6.2. Repository implementations
std::vector<domain::job_definition> job_definition_repository::read_all_active(context ctx) { BOOST_LOG_SEV(lg(), debug) << "Reading all active job definitions."; static const auto max(make_timestamp(MAX_TIMESTAMP, lg())); const auto query = sqlgen::read<std::vector<job_definition_entity>> | where("is_active"_c == true && "valid_to"_c == max.value()); return execute_read_query<job_definition_entity, domain::job_definition>( ctx, query, [](const auto& entities) { return job_definition_mapper::map(entities); }, lg(), "Reading all active job definitions."); }
7. See also
- ores.scheduler — component group overview.