Перейти к содержанию

HOWTO: Per-listener instance gate#

Audience: ops / SRE running multi-node Ruxeo clusters who need to disable a specific listener on specific nodes for debugging or gradual rollout, without flipping the listener globally.

Status: code-level mechanism wired since sansay355 (P3.A). UI exposure is intentionally minimal — see "Why no UI" below.

When to use this#

You normally don't. The per-module Admin Settings page (/admin/ruxeo-admin-settings) already exposes "globally / all nodes / specific nodes" toggles for every feature that operators routinely care about (rxbm.notifications.duedate.enabled, rxcm.schedulers.bg.deadline.enabled, …). Use those first.

Reach for the per-listener gate only when:

  • You need to disable a listener on one debug node while the rest of the cluster runs normally, AND no module-level feature flag exists for it. Example: RxbmModuleAccessCacheInvalidator has no feature flag — if a misbehaving user-sync flooding event queues is pinning a node, you can quiet it there alone.
  • You're testing a new listener gradually: enable on canary, leave off on others.

The convention#

Every listener that extends RxbmInstanceAwareListener declares a stable getListenerType() string (e.g. "scheduler.license-hwm", "dueDateNotificationScheduler", "directoryDeduplication"). The base service (RxbmConfigService.isListenerEnabledForInstance) looks up:

rxbm.listener.<listenerType>.enabled

…in two places, in order:

  1. rxbm_dir_admin_settings directory — instance-aware. Lookup first tries (setting_key, instance_id = current node), falls back to (setting_key, instance_id IS NULL) (global). Set via the Rxbm.Config.ToggleSetting Automation operation.

  2. nuxeo.conf / Framework.getProperty — global only, restart required.

If neither carries an explicit value, the call falls through to the role gate (rxbm.listeners.backend.enabled / rxbm.listeners.frontend.enabled based on rxbm.instance.role).

Examples#

Disable RxbmModuleAccessCacheInvalidator on node backend-02 only#

Via REST (recommended — no restart):

curl -u Administrator:Administrator -X POST \
  -H "Content-Type: application/json" \
  -d '{"params":{"settingKey":"rxbm.listener.moduleAccessCacheInvalidator.enabled","value":"false","instanceId":"backend-02","category":"listener","description":"Mute on backend-02 while AD sync is fixed"}}' \
  http://qa.ruxeo.ru/nuxeo/site/automation/Rxbm.Config.ToggleSetting

(Replace moduleAccessCacheInvalidator with the actual getListenerType() value — find it in the listener's Java source or via REST: Rxbm.Config.ListListenerTypes once that op is added.)

Disable the recurrence scheduler everywhere via nuxeo.conf#

rxbm.listener.scheduler.recurrence.enabled=false

Restart required for nuxeo.conf changes.

Re-enable via REST#

Remove the directory override:

curl -u Administrator:Administrator -X POST \
  -H "Content-Type: application/json" \
  -d '{"params":{"settingKey":"rxbm.listener.moduleAccessCacheInvalidator.enabled","value":"true","instanceId":"backend-02","category":"listener","description":"AD sync fixed, re-enable"}}' \
  http://qa.ruxeo.ru/nuxeo/site/automation/Rxbm.Config.ToggleSetting

(Setting value=true overwrites the override to the enabled state; to fully clear the override, a Rxbm.Config.RemoveDirectoryOverride op exists but the current admin pattern is to leave an explicit true for audit visibility.)

Why no UI#

The rxbm-feature-flags-panel already lists 13+ module-level feature flags in the Base Module section, each with an instance-aware dropdown. Adding a parallel listener-type panel duplicates the same "per-node toggle" UX for a less-discoverable set of keys, making the admin page noisier without buying operators much they couldn't already do via the module-level flags. The per-listener-type gate is kept as a power-user escape hatch: callable via REST + nuxeo.conf, code-level honored by isListenerEnabledForInstance, documented here.

If a specific listener turns out to need first-class UI exposure because it's actually being toggled in production ops, add it to a module's section wrapper (rxbm-base-admin-settings-section-wrapper.html or sibling) under category "listener" with key rxbm.listener.<type>.enabled. No code changes elsewhere are needed — the panel and Rxbm.Config.ToggleSetting handle it transparently.

Pitfalls#

  • Listener-type strings are case-sensitive and must match getListenerType() exactly. Misspelling silently falls through to the role gate.
  • The override is second-stage gating. If a listener has its own feature flag check (e.g. cfg.isDueDateNotificationsEnabled()) AND uses RxbmInstanceAwareListener, both must pass. Disabling the per-type override is enough to silence the listener even if the feature flag is on.
  • The override resolution checks the directory before nuxeo.conf. If you set nuxeo.conf but a directory row exists, the directory wins.
  • RxbmConfigService.isListenerEnabledForInstance (base-core)
  • RxbmConfigService.readListenerOverride (private helper added P3.A)
  • Rxbm.Config.ToggleSetting Automation operation
  • rxbm_dir_admin_settings SQL directory schema
  • RxbmInstanceAwareListener base class