Scheduled Operations Monitor
Model recurring operational work with reusable schedules, an API-backed service, and a generated monitoring UI.
Exampleschedulingoperationsuidashboardapiexpressionstimezone
🌅 Horizon
Example at a Glance
Overview
Operational tasks often recur at different cadences: collecting pending work, producing daily reports, reconciling state during the week, and closing a reporting period. This example models those triggers as reusable logical schedules, separate from the work that they invoke.
Architecture
The UI observes the modeled operations while the schedules independently trigger their flows.
What It Demonstrates
@service— named and inline schedules applied to operations, connections, and aggregate fan-out.@expression— zero-input scheduled sources and their downstream processing flows.aggregate— scheduled API fan-out across data and reporting services.@api— read endpoints that expose operational schedule information to the UI.@dashboardand@ui— a generated interface defined entirely in Ocean DSL.@configand@deploy— configuration and deployment for both the service and UI.
Expected Result
The generated service registers independent jobs for interval, daily, weekly, and monthly work. The generated UI provides an operations view whose buttons call the generated API endpoints.
🧭 Voyage
1. Problem and Constraints
A schedule must state when work runs without coupling the model to a particular scheduling product. Each scheduled binding needs its own overlap behavior: skip a duplicate trigger, queue one follow-up run, or permit parallel executions.
2. Example Structure
0013-scheduled-operations-monitor/
├── 00-som-info.ocn
├── 10-som-datatype.ocn
├── 20-som-api.ocn
├── 30-som-config.ocn
├── 40-som-expression.ocn
├── 50-som-service.ocn
├── 51-som-data-service.ocn
├── 52-som-reporting-service.ocn
├── 55-som-dashboard.ocn
├── 56-som-ui.ocn
├── 60-som-deploy.ocn
└── example-info/example-info.html
3. Model Reusable Schedules
50-som-service.ocn names four logical schedules. The daily
schedule includes seconds and an IANA timezone; the interval intentionally
has no timezone. Named schedules can be reused, while the Friday and Sunday
examples show one-off inline schedules.
schedule DailyReporting daily at 02:00:35 timezone Europe/Amsterdam overlap queue
schedule MonthlyClose monthly on day 1 at 00:05 timezone UTC overlap skip
operation dailyReport schedule DailyReporting
aggregate api.getMonthlyState -> data.getPendingOperations | data.getReconciliationState | reporting.getMonthlyStatus schedule MonthlyClose
4. Generate the Operations UI
The dashboard and UI use ordinary API connections. They do not duplicate scheduling behavior in the browser; scheduled work stays in the service boundary, while the UI remains an observable, independently generated view.
5. Validate, Generate, and Run
- Open this directory in Ocean UI and validate the complete model.
- Generate the configured target and inspect the service scheduler runtime and scheduler registration files.
- Run the generated deployment and open the Operations UI.
6. Verify the Result
- Inspect the generated service scheduler: each scheduled operation, connection, and aggregate is a distinct job.
- Confirm the daily registration loads
Europe/Amsterdamand the calendar schedules use their declared timezones. - Use the UI buttons to call the overview, daily-report, and monthly-state API endpoints.
7. Experiments
- Change
FastCollectionfromskiptoqueueand observe the generated overlap policy. - Add Thursday to
WeeklyReconciliationand regenerate. - Replace the inline Friday schedule with a named definition when another binding needs the same cadence.
Executable model
<\> Implementation
Explore the runnable model by responsibility, then select a file to inspect its complete source.
# @ocean-meta-start
# tags:
# - scheduling
# - operations-monitor
# perspective:
# feature: scheduled-operations-monitor
# @ocean-meta-end
@info
name: Scheduled Operations Monitor
version: 1.0.0
title: Scheduled Operations Monitor
subtitle: Observe recurring operational work
shortDescription: A complete Ocean DSL example for reusable schedules and scheduled flows.
description: Demonstrates interval, daily, weekly, and monthly schedules through a generated service, API, dashboard, and UI.
# @ocean-meta-start
# tags:
# - datatype
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor
# @ocean-meta-end
@datatype
OperationsOverview
title : String
description : String
timezone : String
DailyOperationsReport
title : String
generatedAt : String
status : String
MonthlyOperationsSummary
pendingOperations : String
reconciliationState : String
monthlyStatus : String
# @ocean-meta-start
# tags:
# - api
# - rest-api
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor
# @ocean-meta-end
@api
OperationsMonitorApi style:rest
engine = gin
configType = ApiConfig
version = 1.0.0
basePath = /operations
generateSwagger = true
get /overview getOverview() : OperationsOverview
get /daily-report getDailyReport() : DailyOperationsReport
get /monthly-state getMonthlyState() : MonthlyOperationsSummary
OperationsDataApi style:rest
engine = gin
configType = ApiConfig
version = 1.0.0
basePath = /operations-data
generateSwagger = true
get /pending getPendingOperations() : String
get /reconciliation-state getReconciliationState() : String
OperationsReportingApi style:rest
engine = gin
configType = ApiConfig
version = 1.0.0
basePath = /operations-reporting
generateSwagger = true
get /monthly-status getMonthlyStatus() : String
# @ocean-meta-start
# tags:
# - configuration
# perspective:
# feature: scheduled-operations-monitor
# service: all
# @ocean-meta-end
@config
@import config O.log.config@1.0.0 as LogConfig
OperationsMonitorConfig
apiConfig : ApiConfig
logConfig : LogConfig
ApiConfig
port : Int (default=8080)
UiConfig
port : Int (default=8080)
logConfig : LogConfig
# @ocean-meta-start
# tags:
# - expression
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor
# @ocean-meta-end
@expression
CollectPendingOperations
input: _
output: pending:String
logic
pending = "pending operational work"
ProcessPendingOperations
input: pending:String
output: _
logic
return
CreateDailyReport
input: _
output: _
logic
# message = "daily operational report created"
return
ReconcileOperations
input: pending:String
output: _
logic
return
GetOperationsOverview
input: _
output: overview:OperationsOverview
logic
var result OperationsOverview
result.title = "Scheduled Operations Monitor"
result.description = "Interval, daily, weekly, and monthly jobs are configured in Ocean DSL."
result.timezone = "UTC and Europe/Amsterdam"
overview = result
GetDailyOperationsReport
input: _
output: report:DailyOperationsReport
logic
var result DailyOperationsReport
result.title = "Daily operations report"
result.generatedAt = "02:00:35 Europe/Amsterdam"
result.status = "Scheduled"
report = result
GetMonthlyOperationsSummary
input: _
output: summary:MonthlyOperationsSummary
logic
var result MonthlyOperationsSummary
result.pendingOperations = "pending operational work"
result.reconciliationState = "reconciliation scheduled"
result.monthlyStatus = "monthly close scheduled"
summary = result
GetReconciliationState
input: _
output: result:String
logic
result = "reconciliation scheduled"
GetMonthlyStatus
input: _
output: result:String
logic
result = "monthly close scheduled"
# @ocean-meta-start
# tags:
# - service
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor
# @ocean-meta-end
@service
OperationsMonitorService
@perspectives: version:1.0.0, lifestyle:stable
use config OperationsMonitorConfig as svcCfg
impl api OperationsMonitorApi as api on svcCfg.apiConfig.port
use api OperationsDataApi as data
use api OperationsReportingApi as reporting
use expression CollectPendingOperations as collect
use expression ProcessPendingOperations as process
use expression CreateDailyReport as dailyReport
use expression ReconcileOperations as reconcile
use expression GetOperationsOverview
use expression GetDailyOperationsReport
use expression GetMonthlyOperationsSummary
# Reusable, technology-independent schedule definitions.
schedule FastCollection every 5m overlap skip
schedule DailyReporting daily at 02:00:35 timezone Europe/Amsterdam overlap queue
schedule WeeklyReconciliation weekly on Monday, Wednesday at 09:00 timezone UTC overlap parallel
schedule MonthlyClose monthly on day 1 at 00:05 timezone UTC overlap skip
# A direct scheduled operation.
operation dailyReport schedule DailyReporting
# Named and inline scheduled connections.
connect collect -> process schedule FastCollection
connect collect -> reconcile schedule WeeklyReconciliation
connect collect -> reconcile schedule every Friday at 18:30 timezone Europe/Amsterdam overlap parallel
# Scheduled aggregate fan-out calls dependent APIs, as aggregates do elsewhere in Ocean DSL.
aggregate api.getMonthlyState -> data.getPendingOperations | data.getReconciliationState | reporting.getMonthlyStatus schedule MonthlyClose
aggregate api.getMonthlyState -> data.getPendingOperations | data.getReconciliationState | reporting.getMonthlyStatus schedule weekly on Sunday at 23:30 timezone UTC overlap queue
# UI-facing read endpoints are ordinary API connections.
connect api.getOverview -> GetOperationsOverview
connect api.getDailyReport -> GetDailyOperationsReport
connect api.getMonthlyState -> GetMonthlyOperationsSummary
# @ocean-meta-start
# tags:
# - service
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-data
# @ocean-meta-end
@service
OperationsDataService
@perspectives: version:1.0.0, lifestyle:stable
use config OperationsMonitorConfig as svcCfg
impl api OperationsDataApi as api on svcCfg.apiConfig.port
use expression CollectPendingOperations
use expression GetReconciliationState
connect api.getPendingOperations -> CollectPendingOperations
connect api.getReconciliationState -> GetReconciliationState
# @ocean-meta-start
# tags:
# - service
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-reporting
# @ocean-meta-end
@service
OperationsReportingService
@perspectives: version:1.0.0, lifestyle:stable
use config OperationsMonitorConfig as svcCfg
impl api OperationsReportingApi as api on svcCfg.apiConfig.port
use expression GetMonthlyStatus
connect api.getMonthlyStatus -> GetMonthlyStatus
# @ocean-meta-start
# tags:
# - dashboard
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor-ui
# @ocean-meta-end
@dashboard
OperationsDashboard
title: Scheduled Operations
layout: SingleColumnLayout
Widget OverviewButton of type Button
label = Refresh schedule overview
Widget DailyReportButton of type Button
label = View daily report schedule
color = secondary
Widget MonthlyStateButton of type Button
label = View monthly close schedule
color = secondary
Widget ScheduleGuide of type Text
title = Reusable schedules
subtitle = Jobs run independently with their own overlap policy.
content = <p>The service demonstrates a five-minute interval, a daily report at 02:00:35 in Europe/Amsterdam, a weekly reconciliation, and a monthly close. The dashboard calls generated API endpoints while scheduled flows run independently in the generated service.</p>
AboutDashboard
title: About scheduling
layout: SingleColumnLayout
Widget AboutText of type Text
title = Ocean DSL scheduling
subtitle = Logical schedules, target-specific generation
content = <p>Schedule definitions describe recurrence, timezone, and overlap behavior without exposing a scheduler implementation. A definition may be reused by operations, connections, and aggregates; inline schedules remain available for one-off jobs.</p>
# @ocean-meta-start
# tags:
# - ui
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: operations-monitor-ui
# @ocean-meta-end
@ui
OperationsMonitorUi
@perspectives: version:1.0.0, lifestyle:stable
framework: htmx
styling: bootstrap
template: go-html-template
backend: go-gin
static: static
configType: UiConfig
nav Operations dashboard = OperationsDashboard
nav About dashboard = AboutDashboard
header title = ⏱️ Scheduled Operations Monitor
header subtitle = Observe the recurring work configured in Ocean DSL
header align = center
footer title = ⚡ Built with Ocean-lab
footer subtitle = Reusable scheduling example
footer align = center
use dashboard OperationsDashboard as operations
use dashboard AboutDashboard as about
use api OperationsMonitorApi
connect operations.OverviewButton.click -> OperationsMonitorApi.getOverview
connect operations.DailyReportButton.click -> OperationsMonitorApi.getDailyReport
connect operations.MonthlyStateButton.click -> OperationsMonitorApi.getMonthlyState
# @ocean-meta-start
# tags:
# - deployment
# - scheduling
# perspective:
# feature: scheduled-operations-monitor
# service: all
# @ocean-meta-end
@deploy
Name: Scheduled-Operations-Monitor-deploy
OperationsMonitorDeploy
service OperationsMonitorService
replica 1
export 9095:OperationsMonitorService.api
dependsOn OperationsDataDeploy, OperationsReportingDeploy
OperationsDataDeploy
service OperationsDataService
replica 1
export 9096:OperationsDataService.api
OperationsReportingDeploy
service OperationsReportingService
replica 1
export 9097:OperationsReportingService.api
OperationsMonitorUiDeploy
service OperationsMonitorUi
replica 1
export 8085:OperationsMonitorUi.config
dependsOn OperationsMonitorDeploy