3.3 KiB
Shared runtime placement (shared-runtime-v1 + stateless-v1)
This source declares execution.sharedRuntime: shared-runtime-v1 and
execution.componentModel: stateless-v1 in manifest.yaml. It is a source
declaration only: it is not certified, has no signed archive, and has not been
accepted against a live multi-Workspace deployment. The exact archive still needs
independent review and acceptance runs.
Under shared placement one KeywordAlert object and one KeywordMonitor event
listener serve every installation of the artifact digest. Installation attachments
are lightweight contexts; they do not create another object graph.
Per invocation
keywords,group_ids,admin_id,bot,case_sensitiveandcooldown_secondsare read throughself.get_config()on every group-message invocation, from the plugin or from the listener component'sget_plugin_config(). No config value is stored on the shared object.get_installation_binding()is read per invocation and never retained past the call; it is read when the cooldown table for the current installation is resolved.initialize()is process-scoped and only logs: it runs once per worker with an empty config, before any installation is known.
Per binding, released on revocation
_cooldownsis keyed by the installation scope<instance_uuid>:<workspace_uuid>:<installation_uuid>and then by(group_id, keyword).runtime_revisionis deliberately excluded from the token so a worker upgrade does not hand a tenant a fresh cooldown window.BasePlugin.on_installation_revoked(binding)pops exactly that scope and touches process-local state only — no Host API is available during revocation. Nothing is persisted, so no durable row is involved.- Dedicated (binding-less) workers keep a single binding-less cooldown table, i.e. their existing behaviour.
Known limits
- Cooldowns are in-memory and process-lifetime only (unchanged pre-existing behaviour): a worker restart clears them, and revocation clears a revoked installation's window.
- The per-installation cooldown table grows with the number of distinct (group, keyword) pairs seen by that installation; it is freed by revocation. The runtime revokes on uninstall, disable, Workspace removal and upgrade.
- Revocation is serialized per installation but may overlap with sibling installations' invocations; per-installation state is isolated, nothing is shared.
- Alert delivery runs inside the group-message invocation and therefore uses that invocation's authority; the plugin creates no detached task.
Tests
tests/test_installation_cooldown.py drives one plugin object plus one real
KeywordMonitor component object through two distinct InstallationBindings (same
instance and Workspace, different installation uuids) with the installed SDK's
bind_invocation, over a stub Host that records alert relays. It asserts that the
same message in the same group produces one alert per installation (pre-fix:
one relay total, because A's process-global (group, keyword) cooldown suppressed
B), that the cooldown still suppresses a repeat inside one installation, that
revocation releases only the revoked installation's table (so its next alert is
allowed again while a sibling is untouched), and that the scope token is the full
binding.