Skip to content

Re-calling observe()/enable_observation() silently terminates existing subscribers #54

Description

@yokuze

enable_observation() calls disable_observation() first, dropping the previous
ObservableSqliteDatabase and its broadcast broker. The broker owns the only
broadcast::Sender, so every Receiver handed out earlier gets RecvError::Closed on its
next recv() — the change stream just ends, with no error attributable to a cause and no
notification to whoever set up that subscription.

The crate-level behavior is documented ("the previous observer is disabled first … causing
existing subscriber streams to terminate. Callers must re-subscribe"), but the observe
IPC command exposes it to independent callers who cannot coordinate a re-subscribe.
Observation is effectively per webview window over one shared cached wrapper, so a second
window calling Database.load(key).observe(...) on a key a first window already observes
tears down the first window's broker — the first window's subscribe callback silently
stops firing, with no error to either window.

Repro

Minimal, runnable repro (cargo run, prints an explicit verdict; the subscriber created
after the re-observe still receives its event, proving the write published and the probe is
sound):
https://github.com/yokuze/mcve/tree/23aa4a2acc7e0956ba499751770d4c54b9451da1/cases/004-sqlx-sqlite-toolkit-reobserve-kills-existing-subscribers

Root cause (rev e1b3836)

  • enable_observation drops the current observer before installing the new one (doc comment states existing streams terminate): wrapper.rs#L390-L402
  • ObservationBroker owns the sole change_tx: broadcast::Sender: broker.rs#L52-L58
  • observe command calls remove_for_db + enable_observation, exposing the teardown to independent callers: src/commands.rs#L573-L617

Expected

Re-observing should not silently disconnect existing subscribers — e.g. make
observe/enable_observation idempotent when the requested table set and config are
unchanged (keep the existing broker), support additive/reference-counted observers, or at
minimum deliver a distinguishable close reason so a caller can tell "someone re-observed"
apart from a normal shutdown.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions