Broker plugins#
SkyPortal integrates with external alert brokers (e.g. BOOM, Kowalski, Fink,
Lasair) through a pluggable provider interface, modeled on the follow-up
facility APIs (skyportal/facility_apis/). A broker provider is a registered
class; a configured connection to a broker is a Broker database record that
supplies the per-instance endpoints/credentials the provider operates on.
This lets a new broker be added as a provider class (and shared helpers) instead of forking SkyPortal or re-deriving the same integration in every deployment.
Concepts#
BrokerAPI(skyportal/broker_apis/interface.py), the base class. Every operation is a stub that raisesNotImplementedError; a provider overrides only what it supports.Registry, providers are listed in the
BROKERStuple inskyportal/broker_apis/__init__.py. Thebroker_classnamesPostgres enum (skyportal/enum_types.py) is derived from it, so provider names are validated at the database level (mirrorsapi_classnames). Append new providers to the end of the tuple to keep the enum stable.Capabilities,
BrokerAPI.implements()reports which operations a provider overrode. Handlers gate on it, and the frontend can show/hide features accordingly.Brokermodel (skyportal/models/broker.py), one configured broker:name,broker_classname(which provider),active, and encryptedaltdata(endpoints/credentials, mirroringAllocation.altdata). Only system admins may create/update/delete brokers, andaltdatais redacted from non-admins.Site defaults,
default_alert_searchanddefault_crossmatchname the broker the source page’s “Search alerts” button opens and the one its cross-matches (cone searches) run against. At most one broker holds each; pick them on the brokers page. The seeded data makes ALeRCE both.
Operations#
Interactive (SkyPortal → broker): query_alerts, get_alert, get_cutouts,
cone_search, save_as_source, and filter management (get_filters,
create_filter, update_filter, delete_filter, test_filter,
filter_modules).
Ingestion (broker → SkyPortal): run_ingestion, a long-lived consumer/poller
(see “Ingestion and filters” below).
Ingestion and filters (end to end)#
Once a broker is configured (a Broker record with valid altdata), ingestion,
running its filters and pulling in matching alerts, is driven by a background
service and gated by config.
1. Enable the ingestion service#
The broker_ingest service (services/broker_ingest/) runs one task per active
broker whose provider implements run_ingestion. It is off by default; enable
it in your config and restart the app:
brokers:
ingest_enabled: true
With it disabled the service idles (it does not exit), so nothing is ever polled.
Confirm it via make monitor (the broker_ingest entry should be RUNNING) and
log/broker_ingest.log, which prints either broker ingestion disabled ... or
starting ingestion for broker <id> (<name>).
brokers.ingest_enabled is a config value, not in the database, not in a
broker’s altdata, and not exposed via the API. A broker’s run_ingestion: true
capability only means the provider supports ingestion, not that it is running.
2. Attach filters#
A filter_kind: "query" broker (e.g. Lasair) runs one query per SkyPortal Filter
linked to it. Create a Filter (on a Stream + your Group), then attach the
query, for Lasair the SELECT / FROM / WHERE parts, from the broker page (or
POST /api/brokers/<id>/filters/<filter_id>). Filters are re-read every poll
cycle, so adding/editing one does not require a restart.
3. When and how often#
run_ingestion polls immediately on start, then sleeps altdata.poll_interval
seconds (provider default; e.g. Lasair 86400 = daily, ALeRCE/ANTARES 3600), so the
first batch appears within seconds of the service starting, not after a full
interval. Changing poll_interval (or other broker altdata) is read once when a
broker’s task starts, so restart the ingestion service to apply it.
4. Where results land#
Matching objects are registered as Candidates under the passing filter and appear on the Candidates / Scanning page filtered by it, not as Sources. From there you review and save the ones worth keeping.
5. Auto-save#
To save passing objects as Sources automatically (into the filter’s group)
instead of only registering candidates, set the filter’s autosave flag, the
“Auto-save passing objects as sources” checkbox in the Lasair filter builder, or
POST /api/brokers/<id>/filters/<filter_id> with {"autosave": true}. Objects
already saved to that group are skipped. Use it only when the filter is selective
enough to trust everything it passes; otherwise keep it off and tighten the
filter’s conditions so scanning stays manageable.
Endpoints#
GET/POST/PATCH/DELETE /api/brokers[/{id}], manageBrokerrecords.GET /api/brokers/{id}/alerts[/{alert_id}], query alerts (dispatched to the broker’s provider).GET /api/internal/broker_apis, capabilities + config schema of every registered provider (for the frontend).
Writing a provider#
Add
skyportal/broker_apis/mybroker.pywith aMYBROKER(BrokerAPI)class overriding the operations you support. Read per-instance config frombroker.altdata. Provideform_json_schema_config(and optionallyui_json_schema,surveys,validate_config).Append it to
BROKERSinskyportal/broker_apis/__init__.py.A database migration for the extended
broker_apisenum is generated automatically.
See skyportal/broker_apis/generic.py (GENERICBROKER) for a working reference
that talks to any REST broker via a configured base_url/token.