Querying
Scheduled queries
Orbital supports running saved queries automatically on a schedule. This is useful for scenarios such as:
- Polling an external API every few minutes
- Refreshing a dataset at a regular interval
- Running nightly sync or cleanup jobs
Scheduled queries complement existing HTTP Endpoints and Background Streams, giving you multiple ways to publish and reuse queries.
Defining a Scheduled Query
You declare a scheduled query using the @Scheduled
annotation:
import com.orbitalhq.scheduler.Scheduled
@Scheduled(cron = "0 0/5 * * * ?")
query RefreshProducts {
find { Product[] }
}
Be sure to include the import statement: import com.orbitalhq.scheduler.Scheduled
This runs the query RefreshProducts
every 5 minutes.
Under the hood, Orbital uses Quartz Scheduler with a JDBC-backed job store, so schedules are persistent and cluster-safe.
Annotation Reference
namespace com.orbitalhq.scheduler
annotation Scheduled {
/**
* Cron expression (Quartz format)
*/
cron: String?
/**
* Run with fixed rate (ISO-8601 duration or shorthand like "10m")
*/
fixedRate: String?
/**
* Max number of executions (-1 = forever)
*/
repeatCount: Int = -1
/**
* What to do if a fire is missed
*/
misfirePolicy: MisfirePolicy = MisfirePolicy.Default
/**
* Trigger priority (higher runs first)
*/
priority: Int = 5
}
enum MisfirePolicy {
Default,
FireImmediately,
Skip
}
Property | Description | Example / Values | Default |
---|---|---|---|
cron | A Quartz cron expression with 6 fields: seconds, minutes, hours, day-of-month, month, day-of-week. | 0 0 2 * * ? → 2:00 AM daily | None (required if fixedRate not set) |
fixedRate | Run at a fixed interval. Supports ISO-8601 durations or shorthand. | PT10M or 10m | None (required if cron not set) |
repeatCount | Number of times to run. | -1 = forever | -1 |
misfirePolicy | How to handle missed runs. | Default (Quartz’s smart policy, usually fire once now)FireImmediately (catch up immediately)Skip (ignore missed runs, wait for next) | Default |
priority | Trigger priority if multiple jobs fire simultaneously. | 5 (default), higher numbers run first | 5 |
Provide either cron or fixedRate
cron
or Supported Query Types
Scheduled queries must be finite queries (find
or call
).
Streaming queries (stream { }
) cannot be scheduled.
Admin & Monitoring
Scheduled queries are shown in the Orbital UI under the Saved Queries tab.
Query results from each scheduled run are stored in Orbital’s query history, if enabled.
Cluster Behavior
When running in a cluster, job scheduling is co-ordinated across the cluster, using Quartz and the Postgres job store to coordinate execution.
At any given time, exactly one node will execute a scheduled query, ensuring there are no duplicates. If a node crashes or becomes unavailable, another node in the cluster automatically takes over future runs.
Examples
Hourly polling job:
import com.orbitalhq.scheduler.Scheduled
@Scheduled(fixedRate = "1h")
query PollApi {
call { ExternalApi[] }
}
Nightly batch job:
@Scheduled(cron = "0 0 2 * * ?", misfirePolicy = FireImmediately)
query NightlySync {
find { Orders }
}
Limitations
- No support yet for multiple schedules per query (one
@Scheduled
per query). - Missed runs are not replayed unless
misfirePolicy
is set.