mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Collapse SSE feature flags into single enable_sse_updates
Replace enable_sse_history_updates and enable_sse_entry_point_updates with a single enable_sse_updates. The two flags shared the same SSE connection plumbing (events/stream + dispatcher), and only the HistoryAuditMonitor lifecycle has real per-process cost — entry-point dispatch is event-driven and effectively free. One knob admins can flip. Updates schema, sample config, server (app, configuration manager, history_audit_monitor, sse_monitor), client stores and their tests, integration tests, and the regenerated admin docs.
This commit is contained in:
@@ -66,7 +66,7 @@ export const useEntryPointStore = defineStore("entryPointStore", () => {
|
||||
const configStore = useConfigStore();
|
||||
|
||||
const decide = () => {
|
||||
if (configStore.config?.enable_sse_entry_point_updates) {
|
||||
if (configStore.config?.enable_sse_updates) {
|
||||
// Baseline fetch + SSE. Reconnect-refetch closes the "user
|
||||
// navigated away and missed events" window.
|
||||
fetchEntryPoints().catch((err) => console.warn("Initial entry-point load failed", err));
|
||||
|
||||
@@ -41,7 +41,7 @@ function registerDefaultHandlers({ enableSse }: { enableSse: boolean }) {
|
||||
server.use(
|
||||
http.get("/api/configuration", ({ response }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return response(200).json({ enable_sse_history_updates: enableSse } as any);
|
||||
return response(200).json({ enable_sse_updates: enableSse } as any);
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ describe("historyStore — config-driven SSE vs polling", () => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe("when enable_sse_history_updates is true (SSE scenario)", () => {
|
||||
describe("when enable_sse_updates is true (SSE scenario)", () => {
|
||||
beforeEach(() => {
|
||||
registerDefaultHandlers({ enableSse: true });
|
||||
});
|
||||
@@ -148,7 +148,7 @@ describe("historyStore — config-driven SSE vs polling", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("when enable_sse_history_updates is false (polling scenario)", () => {
|
||||
describe("when enable_sse_updates is false (polling scenario)", () => {
|
||||
beforeEach(() => {
|
||||
registerDefaultHandlers({ enableSse: false });
|
||||
});
|
||||
|
||||
@@ -423,7 +423,7 @@ export const useHistoryStore = defineStore("historyStore", () => {
|
||||
}
|
||||
|
||||
// Choose between SSE and polling based on the server config flag
|
||||
// `enable_sse_history_updates`. SSE success at the socket level is not a
|
||||
// `enable_sse_updates`. SSE success at the socket level is not a
|
||||
// reliable proxy: the `/api/events/stream` endpoint accepts connections
|
||||
// even when the HistoryAuditMonitor is disabled, so relying on the
|
||||
// EventSource `connected` state would silently stop polling without any
|
||||
@@ -443,7 +443,7 @@ export const useHistoryStore = defineStore("historyStore", () => {
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const decide = () => {
|
||||
if (configStore.config?.enable_sse_history_updates) {
|
||||
if (configStore.config?.enable_sse_updates) {
|
||||
// SSE delivers incremental updates only; the store still needs
|
||||
// a baseline fetch so the history panel isn't empty until the
|
||||
// first change arrives.
|
||||
|
||||
@@ -281,6 +281,23 @@
|
||||
:Type: int
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``kombu_sqla_transport_cleanup_interval``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description:
|
||||
Time (in seconds) between attempts to delete fully-consumed rows
|
||||
from the Kombu SQLAlchemy transport tables (``kombu_message``).
|
||||
Only relevant when ``amqp_internal_connection`` uses a
|
||||
``sqlalchemy+*`` scheme (the default with an on-disk
|
||||
control.sqlite); the SQLAlchemy transport has no built-in TTL, so
|
||||
without this task the tables grow unbounded. The task no-ops on
|
||||
non-SQLAlchemy brokers (RabbitMQ/Redis honor per-message
|
||||
expiration natively). Set to 0 to disable the cleanup task.
|
||||
:Default: ``900``
|
||||
:Type: int
|
||||
|
||||
|
||||
~~~~~~~~~~~~~
|
||||
``file_path``
|
||||
~~~~~~~~~~~~~
|
||||
@@ -5816,30 +5833,23 @@
|
||||
:Type: str
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``enable_sse_history_updates``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
``enable_sse_updates``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description:
|
||||
Enables real-time history update notifications via Server-Sent
|
||||
Events (SSE). When enabled, a background monitor watches for
|
||||
history changes (via PostgreSQL LISTEN/NOTIFY or audit table
|
||||
polling as a fallback for SQLite) and pushes update signals to
|
||||
connected browsers, replacing aggressive 3-second polling.
|
||||
:Default: ``false``
|
||||
:Type: bool
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
``enable_sse_entry_point_updates``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description:
|
||||
Enables real-time interactive-tool entry-point update
|
||||
notifications via Server-Sent Events. When enabled, the client
|
||||
subscribes to entry_point_update SSE events and refetches the
|
||||
entry-point list on each event, replacing the 10-second polling
|
||||
loop. When disabled, polling remains the source of updates.
|
||||
Enables real-time updates via Server-Sent Events (SSE), replacing
|
||||
the history (3 s), entry-point (10 s) and notification (30 s)
|
||||
polling loops with push events delivered over a single
|
||||
``/api/events/stream`` connection per browser tab. A background
|
||||
monitor watches for history changes (via PostgreSQL LISTEN/NOTIFY,
|
||||
or audit-table polling as a fallback for SQLite); entry-point
|
||||
changes are dispatched directly from the code paths that mutate
|
||||
them; in-app notifications and broadcasts are pushed when
|
||||
``enable_notification_system`` is also true. When disabled,
|
||||
polling remains the source of updates for all three. See the admin
|
||||
guide "Server-Sent Events for real-time updates" for the full
|
||||
architecture, monitoring guidance and proxy configuration.
|
||||
:Default: ``false``
|
||||
:Type: bool
|
||||
|
||||
@@ -5851,9 +5861,9 @@
|
||||
:Description:
|
||||
The interval in seconds between history audit table polls when
|
||||
using the polling fallback (SQLite or when PostgreSQL
|
||||
LISTEN/NOTIFY is unavailable). Only used when
|
||||
enable_sse_history_updates is true. Lower values mean faster
|
||||
updates but more database queries. Recommended range: 1-5 seconds.
|
||||
LISTEN/NOTIFY is unavailable). Only used when enable_sse_updates
|
||||
is true. Lower values mean faster updates but more database
|
||||
queries. Recommended range: 1-5 seconds.
|
||||
:Default: ``2``
|
||||
:Type: int
|
||||
|
||||
@@ -5869,6 +5879,9 @@
|
||||
finished, etc.
|
||||
The system allows notification scheduling and expiration, and
|
||||
users can opt-out of specific notification categories or channels.
|
||||
Delivery is push-based via Server-Sent Events when
|
||||
``enable_sse_updates`` is also true, and falls back to 30-second
|
||||
polling against ``/api/notifications/status`` otherwise.
|
||||
Admins can schedule and broadcast notifications that will be
|
||||
visible to all users, including special server-wide announcements
|
||||
such as scheduled maintenance, high load warnings, and event
|
||||
|
||||
@@ -1018,7 +1018,7 @@ class UniverseApplication(StructuredApp, GalaxyManagerApplication, InstallationT
|
||||
# daemon wins that election when present, otherwise one webapp picks it
|
||||
# up. start/stop are driven by heartbeat role transitions rather than
|
||||
# postfork, so the monitor cleanly migrates when the leader dies.
|
||||
if self.config.enable_sse_history_updates:
|
||||
if self.config.enable_sse_updates:
|
||||
monitor = self._register_singleton(HistoryAuditMonitor)
|
||||
self.database_heartbeat.add_audit_monitor_change_callback(monitor.on_role_change)
|
||||
|
||||
@@ -1057,7 +1057,7 @@ class UniverseApplication(StructuredApp, GalaxyManagerApplication, InstallationT
|
||||
self.database_heartbeat.shutdown()
|
||||
|
||||
def _shutdown_history_audit_monitor(self):
|
||||
if not self.config.enable_sse_history_updates:
|
||||
if not self.config.enable_sse_updates:
|
||||
return
|
||||
self[HistoryAuditMonitor].shutdown()
|
||||
|
||||
|
||||
@@ -512,8 +512,8 @@ galaxy:
|
||||
# history_audit database table. Set to 0 to disable pruning.
|
||||
#history_audit_table_prune_interval: 3600
|
||||
|
||||
# Time (in seconds) between attempts to delete fully-consumed rows from
|
||||
# the Kombu SQLAlchemy transport tables (``kombu_message``). Only
|
||||
# Time (in seconds) between attempts to delete fully-consumed rows
|
||||
# from the Kombu SQLAlchemy transport tables (``kombu_message``). Only
|
||||
# relevant when ``amqp_internal_connection`` uses a ``sqlalchemy+*``
|
||||
# scheme (the default with an on-disk control.sqlite); the SQLAlchemy
|
||||
# transport has no built-in TTL, so without this task the tables grow
|
||||
@@ -3144,25 +3144,25 @@ galaxy:
|
||||
# Message to display on the export citations tool page
|
||||
#citations_export_message_html: When writing up your analysis, remember to include all references that should be cited in order to completely describe your work. Also, please remember to <a href="https://galaxyproject.org/citing-galaxy">cite Galaxy</a>.
|
||||
|
||||
# Enables real-time history update notifications via Server-Sent
|
||||
# Events (SSE). When enabled, a background monitor watches for history
|
||||
# changes (via PostgreSQL LISTEN/NOTIFY or audit table polling as a
|
||||
# fallback for SQLite) and pushes update signals to connected
|
||||
# browsers, replacing aggressive 3-second polling.
|
||||
#enable_sse_history_updates: false
|
||||
|
||||
# Enables real-time interactive-tool entry-point update notifications
|
||||
# via Server-Sent Events. When enabled, the client subscribes to
|
||||
# entry_point_update SSE events and refetches the entry-point list on
|
||||
# each event, replacing the 10-second polling loop. When disabled,
|
||||
# polling remains the source of updates.
|
||||
#enable_sse_entry_point_updates: false
|
||||
# Enables real-time updates via Server-Sent Events (SSE), replacing
|
||||
# the history (3 s), entry-point (10 s) and notification (30 s)
|
||||
# polling loops with push events delivered over a single
|
||||
# ``/api/events/stream`` connection per browser tab. A background
|
||||
# monitor watches for history changes (via PostgreSQL LISTEN/NOTIFY,
|
||||
# or audit-table polling as a fallback for SQLite); entry-point
|
||||
# changes are dispatched directly from the code paths that mutate
|
||||
# them; in-app notifications and broadcasts are pushed when
|
||||
# ``enable_notification_system`` is also true. When disabled, polling
|
||||
# remains the source of updates for all three. See the admin guide
|
||||
# "Server-Sent Events for real-time updates" for the full
|
||||
# architecture, monitoring guidance and proxy configuration.
|
||||
#enable_sse_updates: false
|
||||
|
||||
# The interval in seconds between history audit table polls when using
|
||||
# the polling fallback (SQLite or when PostgreSQL LISTEN/NOTIFY is
|
||||
# unavailable). Only used when enable_sse_history_updates is true.
|
||||
# Lower values mean faster updates but more database queries.
|
||||
# Recommended range: 1-5 seconds.
|
||||
# unavailable). Only used when enable_sse_updates is true. Lower
|
||||
# values mean faster updates but more database queries. Recommended
|
||||
# range: 1-5 seconds.
|
||||
#history_audit_monitor_poll_interval: 2
|
||||
|
||||
# Enables the Notification System integrated in Galaxy.
|
||||
@@ -3171,6 +3171,9 @@ galaxy:
|
||||
# etc.
|
||||
# The system allows notification scheduling and expiration, and users
|
||||
# can opt-out of specific notification categories or channels.
|
||||
# Delivery is push-based via Server-Sent Events when
|
||||
# ``enable_sse_updates`` is also true, and falls back to 30-second
|
||||
# polling against ``/api/notifications/status`` otherwise.
|
||||
# Admins can schedule and broadcast notifications that will be visible
|
||||
# to all users, including special server-wide announcements such as
|
||||
# scheduled maintenance, high load warnings, and event announcements,
|
||||
|
||||
@@ -4313,25 +4313,22 @@ mapping:
|
||||
desc: |
|
||||
Message to display on the export citations tool page
|
||||
|
||||
enable_sse_history_updates:
|
||||
enable_sse_updates:
|
||||
type: bool
|
||||
default: false
|
||||
required: false
|
||||
desc: |
|
||||
Enables real-time history update notifications via Server-Sent Events (SSE).
|
||||
When enabled, a background monitor watches for history changes (via PostgreSQL
|
||||
LISTEN/NOTIFY or audit table polling as a fallback for SQLite) and pushes update
|
||||
signals to connected browsers, replacing aggressive 3-second polling.
|
||||
|
||||
enable_sse_entry_point_updates:
|
||||
type: bool
|
||||
default: false
|
||||
required: false
|
||||
desc: |
|
||||
Enables real-time interactive-tool entry-point update notifications via
|
||||
Server-Sent Events. When enabled, the client subscribes to entry_point_update
|
||||
SSE events and refetches the entry-point list on each event, replacing the
|
||||
10-second polling loop. When disabled, polling remains the source of updates.
|
||||
Enables real-time updates via Server-Sent Events (SSE), replacing the
|
||||
history (3 s), entry-point (10 s) and notification (30 s) polling loops
|
||||
with push events delivered over a single ``/api/events/stream``
|
||||
connection per browser tab. A background monitor watches for history
|
||||
changes (via PostgreSQL LISTEN/NOTIFY, or audit-table polling as a
|
||||
fallback for SQLite); entry-point changes are dispatched directly from
|
||||
the code paths that mutate them; in-app notifications and broadcasts
|
||||
are pushed when ``enable_notification_system`` is also true.
|
||||
When disabled, polling remains the source of updates for all three.
|
||||
See the admin guide "Server-Sent Events for real-time updates" for the
|
||||
full architecture, monitoring guidance and proxy configuration.
|
||||
|
||||
history_audit_monitor_poll_interval:
|
||||
type: int
|
||||
@@ -4340,7 +4337,7 @@ mapping:
|
||||
desc: |
|
||||
The interval in seconds between history audit table polls when using the polling
|
||||
fallback (SQLite or when PostgreSQL LISTEN/NOTIFY is unavailable). Only used when
|
||||
enable_sse_history_updates is true. Lower values mean faster updates but more
|
||||
enable_sse_updates is true. Lower values mean faster updates but more
|
||||
database queries. Recommended range: 1-5 seconds.
|
||||
|
||||
enable_notification_system:
|
||||
@@ -4354,6 +4351,10 @@ mapping:
|
||||
|
||||
The system allows notification scheduling and expiration, and users can opt-out of specific notification categories or channels.
|
||||
|
||||
Delivery is push-based via Server-Sent Events when ``enable_sse_updates``
|
||||
is also true, and falls back to 30-second polling against
|
||||
``/api/notifications/status`` otherwise.
|
||||
|
||||
Admins can schedule and broadcast notifications that will be visible to all users, including special server-wide announcements such as scheduled maintenance, high load warnings, and event announcements, to name a few examples.
|
||||
|
||||
enable_mcp_server:
|
||||
|
||||
@@ -229,8 +229,7 @@ class ConfigSerializer(base.ModelSerializer):
|
||||
"tool_training_recommendations_link": _use_config,
|
||||
"tool_training_recommendations_api_url": _use_config,
|
||||
"enable_notification_system": _use_config,
|
||||
"enable_sse_history_updates": _use_config,
|
||||
"enable_sse_entry_point_updates": _use_config,
|
||||
"enable_sse_updates": _use_config,
|
||||
"instance_resource_url": _use_config,
|
||||
"instance_access_url": _use_config,
|
||||
"organization_name": _use_config,
|
||||
|
||||
@@ -4,7 +4,7 @@ Detects history changes via PostgreSQL LISTEN/NOTIFY (instant) or by polling
|
||||
the history_audit table (SQLite fallback). Dispatches SSE events to connected
|
||||
users via Kombu control tasks.
|
||||
|
||||
Only active when ``enable_sse_history_updates`` is True in the Galaxy config.
|
||||
Only active when ``enable_sse_updates`` is True in the Galaxy config.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
@@ -56,13 +56,13 @@ def main() -> int:
|
||||
heartbeat = DatabaseHeartbeat(application_stack=app.application_stack)
|
||||
|
||||
monitor = None
|
||||
if app.config.enable_sse_history_updates:
|
||||
if app.config.enable_sse_updates:
|
||||
from galaxy.managers.history_audit_monitor import HistoryAuditMonitor
|
||||
|
||||
monitor = app[HistoryAuditMonitor]
|
||||
heartbeat.add_audit_monitor_change_callback(monitor.on_role_change)
|
||||
else:
|
||||
log.warning("enable_sse_history_updates is False — galaxy-sse-monitor will idle with no producers")
|
||||
log.warning("enable_sse_updates is False — galaxy-sse-monitor will idle with no producers")
|
||||
|
||||
heartbeat.start()
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class TestHistorySSEIntegration(IntegrationTestCase):
|
||||
def handle_galaxy_config_kwds(cls, config):
|
||||
super().handle_galaxy_config_kwds(config)
|
||||
config["enable_celery_tasks"] = False
|
||||
config["enable_sse_history_updates"] = True
|
||||
config["enable_sse_updates"] = True
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -36,10 +36,10 @@ class TestEntryPointSSESeleniumIntegration(SeleniumIntegrationTestCase):
|
||||
config["enable_celery_tasks"] = False
|
||||
# App.vue only calls entryPointStore.startWatchingEntryPoints() when
|
||||
# interactivetools_enable is True, and the store only opens an SSE
|
||||
# connection when enable_sse_entry_point_updates is True. Without both,
|
||||
# connection when enable_sse_updates is True. Without both,
|
||||
# __galaxy_sse_connected never becomes true and the gate below times out.
|
||||
config["interactivetools_enable"] = True
|
||||
config["enable_sse_entry_point_updates"] = True
|
||||
config["enable_sse_updates"] = True
|
||||
|
||||
def _wait_for_sse_connected(self) -> None:
|
||||
"""Block until the frontend confirms the SSE pipeline is live."""
|
||||
|
||||
Reference in New Issue
Block a user