Skip to content

Add subscribe-typed so hu meter echo can decode a topic whose publisher advertises no type #300

Description

@YuanYuYuan

hu meter echo and hu meter delay cannot decode a topic whose publisher advertises no type at all. The operator may know the type and hold its .msg on disk. There is still no way to tell hu what the type is.

This is the one case the .msg fallback in #298 cannot reach, and #298 records why:

publisher advertises discovery answers .msg fallback outcome
type name + hash yes not needed decodes
type name + hash no fires decodes, if the .msg is on HIROZ_MSG_PATH
nothing (EMPTY_TOPIC_TYPE) no cannot fire reports the failure, exits non-zero

Row 3 is this issue.

Why the fallback cannot cover it

The fallback needs a type name to know which .msg to load, and the only source is the graph. parse_liveliness yields type_info: None when a token carries EMPTY_TOPIC_TYPE (crates/hiroz-protocol/src/format/rmw_zenoh.rs:222), so there is no name to resolve.

The host says so itself, at crates/hiroz-union/src/plugin/wasm/host/ros.rs:54:

no publisher or subscriber on /scan advertises a type, so there is no type name to
look up -- `subscribe` carries only a topic, and these commands have no --type flag

Proposed change

Two parts:

  1. subscribe-typed: func(topic: string, type-name: string) -> result<subscription, plugin-error> in crates/hiroz-union/wit/v0.1/hu-plugin.wit, beside the existing subscribe. The host resolves the named type through load_schema and skips discovery.
  2. A --type <name> flag on hu meter echo and hu meter delay, which routes to it.

The host already holds every piece: load_schema, ros_type_name_from_dds, and create_dyn_sub(topic, schema). Only the plumbing is missing.

Compatibility: less costly than it looks, with one snag

Adding an import to the world is additive at the component-model level. A guest compiled against the older world does not import subscribe-typed, so it still instantiates against a host that offers it. The plugins shipped in hu-v0.1.0 should therefore keep working without a rebuild.

That last claim is reasoning, not a measurement. Confirm it before relying on it. Build the new host, load an unmodified hu_meter-0.1.0.wasm from the published release, then run hu meter hz. It is a five-minute check and it decides whether this needs a coordinated plugin release.

The snag is hu's own guard rather than the ABI. crates/hiroz-union/src/plugin/install.rs:267 compares the registry index's wit_world against HOST_WIT_WORLD with exact string equality:

if index.wit_world != HOST_WIT_WORLD {
    bail!("plugin index targets WIT world {} but this hu hosts {}. ...")
}

So bumping the world to hu:plugin@0.2.0 for an additive change makes an older published index uninstallable on a newer hu. The plugins in that index would run correctly. The check cannot express "the host is newer, and newer is compatible".

That leaves a decision this issue should settle rather than assume:

option effect
Add the function, leave the world at 0.1.0 nothing breaks; the world string stops describing the world honestly
Bump to 0.2.0 and keep exact equality honest version; forces a plugin re-release for a change that needs none
Bump, and make the guard accept an older plugin world honest version, no forced re-release; needs a compatibility rule the guard can evaluate

The third option is the only one that stays honest without imposing busywork. Do it before the world changes for the first time, not after.

Alternatives considered

A HU_TYPE_OVERRIDE environment variable, read host-side. It needs no WIT change. It also applies to every topic in the process, while these commands take one topic at a time. It trades a clean flag for a footgun.

Make subscribe take an option<string>. This changes an existing function's signature, which genuinely does break older guests. Strictly worse than adding one.

Related

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions