Queues (Horizon) #
Horizon dashboard at /horizon. Key jobs in apps/web/app/Jobs/:
| Job | Queue | Purpose |
|---|---|---|
DataImportJob | importers | Scheduled data importers per corp/site; re-checks ImporterRequirement::unmet() at execution time |
SiteLinkTenantsSyncJob | default | SiteLink tenant/ledger sync |
RunWidgetAgentTurn | default | Async widget AI turn + Reverb broadcast |
RunAgentEvalsJob | default | Agent evaluation suite |
RevMgmt/OnboardCorporationJob | default | Rev-mgmt onboarding cascade |
Scheduler #
Defined in apps/web/routes/console.php. Local dev runs php artisan schedule:work via dedicated Lando scheduler service (mirrors Horizon pattern). Manual data syncs via Admin now mark the per-importer SyncSchedule as executed so the Data Sync UI reflects last-run time.
| Schedule | Command |
|---|---|
| Every minute | app:run-scheduled-syncs — includes site_units importer when enabled per corp |
| Every 5 min | horizon:snapshot |
| Daily 03:00 | app:run-rev-mgmt-engine — only engine_connected facilities |
| Monthly 1st 00:10 | ai:grant-monthly-credits |
| Hourly :15 | ai:sync-cloudflare-costs |
Importer requirements #
Enum: App\Enum\ImporterRequirement. Each data importer declares which corporation-level config it needs before running. ImporterRequirement::unmet($requirements, $corp) returns unsatisfied cases with human-readable missingMessage() text for the Admin Data Sync UI.
| Requirement | Checks |
|---|---|
SITELINK_API | Corp api_username + api_password |
RAPIDSTOR_TOKEN | Corp rs_api_token |
GOOGLE_INTEGRATION | Connected Google integration record |
MTAS_API | services.mtas.api_token configured |
BIGQUERY_CONFIG | Per-corp BigQuery config in services.bigquery.storapp.{code} |
Artisan commands #
| Command | Purpose |
|---|---|
journey:import-translations | Bulk import translation keys/overrides from RapidStor corp configs (ImportJourneyTranslations) |
translations:sync | Daily pull of RapidStor v2 frontend bundled translations from rapidstor.frontend_translations_url; upserts base + corp layers via TranslationImporter; hash-gated skip |
Notable scheduled/other: app:data-sync, app:fetch-site-reviews, app:review-sentiment, app:onboard-revenue-facility, app:import-sites-for-corporation, app:seed-sync-schedules.
Dev script: apps/web/scripts/import-frontend-translations.mjs — one-shot import from local RapidStor mono translation trees via translations:import. Targets: --target=lando (default), docker, or docker --swarm for production deploys.
Rev-mgmt engine (Go) #
Service: apps/rev-mgmt-engine/. Triggered daily via app:run-rev-mgmt-engine and on-demand from the Revenue Management UI (engine-connected facilities only).
| Layer | Behaviour |
|---|---|
| Layer 1 | Base-rate recommendations from occupancy, competitor data, rules; active explorations wired end-to-end |
| Layer 2 | Promotion recommendations from ClickHouse evaluation-window streaks |
| ECRI | Tenant-scoped rate increases — gated off by default (REV_MGMT_ECRI_ENABLED); not production-ready |
Anchor precedence for Layer 1: anchor_rate → standard_rate → skip (standard_rate_unset). Legacy competitor_median fallback removed at go-live. Competitor staleness detection flags facilities with outdated competitor data.
Operator approval (approve.Service.ApproveAs) orchestrates: Mongo write → Redis cache DEL → MySQL audit → fire-and-forget SiteLink wrapper push. Audit trail uses structured JWT actor claims (not string-parsed decidedBy). Recommendations and overrides are keyed on RapidStor unit-type _id; see Architecture → Rev-mgmt identity.
Operator activity feed: engine GET /api/activity (SQL-filtered to operator event types) proxied by Suite at GET /api/v1/revenue-management/activity.
Agent runtime (TypeScript) #
Service: apps/agent-runtime/. Ported turn loop, replay, MCP client, and agent profiles from Laravel. REST + WS surface in src/http/api.ts: public widget routes at /widget/*, authenticated admin routes at /v1/*, health at /health. Widget turns call RapidStor MCP via WidgetToolProvider; conversation state in MySQL (conversations, messages tables). Docker image built from repo root (npm workspace). Laravel AgentRuntimeClient still handles in-app assistant with HMAC-signed requests.