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
}
PropertyDescriptionExample / ValuesDefault
cronA Quartz cron expression with 6 fields: seconds, minutes, hours, day-of-month, month, day-of-week.0 0 2 * * ? → 2:00 AM dailyNone (required if fixedRate not set)
fixedRateRun at a fixed interval. Supports ISO-8601 durations or shorthand.PT10M or 10mNone (required if cron not set)
repeatCountNumber of times to run.-1 = forever-1
misfirePolicyHow 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
priorityTrigger priority if multiple jobs fire simultaneously.5 (default), higher numbers run first5

Provide either cron or fixedRate

Exactly one of cron or fixedRate must be provided.

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.
Previous
Publishing queries (http / websockets)
Next
Caching in queries