Skip to content

connections: introspection - a connection describing the device to build #428

Description

@coretl

Raised at the request of @tomkane-dls, in the spec attached to this comment on #424: introspection is "a larger design problem than it looked and belongs in its own PR". #424 removes it; this issue is where it comes back. Part of the #388 series.

What was there, and is now gone

Connection was generic in T, and connect() returned a value describing the device — for EigerConnection, a DetectorInfo carrying the API version and the tuple of parameter keys the detector reports.

At startup, the runner opened each connection, kept what connect() returned, and passed it to Controller.build() for the controllers holding that connection. build() used it to create structure that cannot be known from config — for Eiger, one attribute per reported parameter key. A controller that did not introspect declared build(self) with no parameter, and the framework inspected the signature to decide whether to pass one.

On every reconnect, the runner called connect() again and compared the new value against the one from startup. If they differed, the device had come back describing itself differently. build() cannot re-run — the controller tree is fixed after startup, and pythonSoftIOC cannot create records after iocInit — so there was no way to accommodate the new shape, and the application exited rather than continuing against a structure that no longer matched the hardware.

The methodology above is an open question, not a plan to re-apply. It is recorded here so nothing is lost.

The open problem

A connection whose existence depends on introspection cannot be declared in fastcs.yaml, because it does not exist at config-parse time. A device reporting seven sub-devices, each needing its own link, has no way to express them.

Supporting that means giving back the things #424 was able to delete:

  • collecting connections from the tree after the build phase, rather than the runner's list being exactly what the launcher built;
  • deduplicating them by identity;
  • opening them mid-walk rather than all up front, in dependency order;
  • accepting that they take framework defaults and cannot declare depends_on.

No known device at Diamond needs this — the multiplexed alternative, one link with the sub-device as a command parameter, is what temperature_attr.py already does for its ramps.

Where things stand meanwhile

A controller that must ask the device what it has still can, and the Eiger demo still does: build runs with every connection already open, so the walk is ordinary driver code in EigerDetector.build rather than a framework mechanism. What is no longer available is the framework carrying that answer or comparing it on reconnect.

Two smaller pieces would also want revisiting here:

  • ControllerRunner.fatal_error. The channel is still there, but nothing in the framework sets it now: its one producer was the introspection mismatch. Whatever this issue lands will most likely be its producer again.
  • The comparison itself. != requires the result to compare to a single bool, which a dataclass of plain fields does and an array of values does not. If the mechanism returns, that constraint needs stating in the design rather than discovered by a driver.

Questions to settle

  1. Does the framework carry the description at all, or does build simply ask the device itself (as it does today) and introspection become a documented pattern rather than a mechanism?
  2. If it is a mechanism: does it hang off Connection.connect()'s return value, or a property on the connection the runner reads (floated in the review of controllers: ControllerRunner, plus native timestamps and severity on attributes #420, and it avoids the two-signatures-for-build wart)?
  3. Is a re-describing device fatal, or is there a shape of controller tree that could accommodate it?
  4. Is the connection-per-introspected-sub-device case in scope, and is it worth the four deletions above?

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    decisionDesign decision to settle with the team (produces an ADR); not for the autonomous nightly job

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions