Repository navigation
refactor(frontend): replace local API type copies with strom-types - #915
Conversation
Eyevinn#915 decodes the NDI discovery responses as strom-types' NdiDiscoveryStatus and DeviceResponse. Both require fields the backend always sends and Eyevinn#916's fixtures left out: source_count on the status, and properties plus a real category ("networksource", not "ndi") on each source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eyevinn#915 decodes the NDI discovery responses as strom-types' NdiDiscoveryStatus and DeviceResponse. Both require fields the backend always sends and Eyevinn#916's fixtures left out: source_count on the status, and properties plus a real category ("networksource", not "ndi") on each source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backend always sends source_count on the NDI discovery status, and
properties plus a real category ("networksource", not "ndi") on each
source. The fixtures now match, so they also decode once Eyevinn#915 switches
these responses to strom-types' NdiDiscoveryStatus and DeviceResponse,
which require those fields.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
srperens
left a comment
There was a problem hiding this comment.
Verdict: Request changes. The refactor is right and its wire-format claims hold. But merged into today's main it stops the frontend compiling. This PR deletes the serde import from player.rs, and main has since added goto_player there, which still derives Serialize. GitHub reports this PR as MERGEABLE because the text merges cleanly. The breakage is in what the merged code means.
Requested changes
- Rebase onto main. In
frontend/src/api/player.rs, replacegoto_player's localGotoRequestwithstrom_types::mediaplayer::GotoRequest, and addSerializeto that type's derive intypes/src/mediaplayer.rs. That removes the last local copy in the file, which is this PR's own goal, and it also fixes the build.
The break. I merged this head into main d78c3ee locally, with no conflicts. In the result:
frontend/src/api/player.rs:1—use strom_types::mediaplayer::{replaces the olduse serde::Serialize;.frontend/src/api/player.rs:99—#[derive(Serialize)]still sits on main's localGotoRequest.frontend/src/api/player.rs:6—use super::*;cannot supply it:frontend/src/api/mod.rshas noserdeimport, and no#[macro_use]exists in the crate.
The shared type already exists, with Deserialize only: types/src/mediaplayer.rs:66 — #[derive(Debug, Clone, Deserialize)]. I did not compile this (no toolchain here). The finding is static: nothing in scope names Serialize at that line.
Claims
| Claim | Verdict | Evidence |
|---|---|---|
Wire strings for PlayerAction unchanged |
CONFIRMED |
mediaplayer::tests::player_control_request_wire_format ... ok in Check (Linux) |
| Discovery responses still decode with the optional fields absent | CONFIRMED |
discovery::tests::responses_decode_with_optional_fields_absent ... ok, same job |
| Stricter decoding is safe | CONFIRMED |
types/src/discovery.rs:103 — pub category: DeviceCategory, and types/src/discovery.rs:107 — pub properties: HashMap<String, String>, are the types the backend serialises, so the two cannot drift |
| CI covers the merged tree | CONTRADICTED |
run 36588341385 is at 089dee9 on base f1a46dd, so it predates goto_player |
Radius: SHARED. Four strom-types structs gain a serde direction, and frontend API calls switch types. openapi.json is unchanged, and API Contract Check is green.
Overlaps: #916 tests the same get_ndi_sources path. Its fixture sends "category":"networksource" and "properties":{}, so it decodes under the stricter types, and the two can land in either order. #879 changes other files under frontend/src/api/. No open issue owns this decision.
Tests & CI: Check (Linux), Check & Build (WASM), both Linux builds and API Contract Check are green at 089dee9. The three new strom-types tests ran in Check (Linux), by name. macOS and Windows were skipped, and nothing platform-specific changed.
Confidence: HIGH
The frontend defined its own copies of ten request/response types that already exist in strom-types, because the shared types derived only the serde direction the backend needs. Add the missing derive and use the shared types: - DiscoveredStream, AnnouncedStream, DiscoveredDevice and NdiStatus become DiscoveredStreamResponse, AnnouncedStreamResponse, DeviceResponse and NdiDiscoveryStatus. The NDI ip/url property getters move onto DeviceResponse. - The local DynamicPadsResponse, ParseRequest and ExportRequest become the strom-types equivalents. - SetPlaylistRequest, SeekRequest and ControlRequest become the strom-types player requests; control_player takes a PlayerAction instead of a string. openapi.json is unchanged. A test pins the PlayerAction wire strings to the values the frontend sent before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The frontend now decodes discovery responses with the shared types. Check that stream and announced-stream JSON decodes with the optional interface fields absent, that NDI status decodes, and that a DeviceResponse round-trips with its NDI ip and url-address properties. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
goto_player, added on main after this branch was cut, still declared a local GotoRequest deriving Serialize. The earlier commit in this branch removed player.rs's serde import, so the frontend stopped compiling once rebased. Use strom_types::mediaplayer::GotoRequest instead and derive Serialize on it, with a wire-format test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
089dee9 to
b1b0a30
Compare
|
Claude (AI), on behalf of @wagenet. 1. Rebase, and use the shared The build break was real. Before b1b0a30, Tests run at b1b0a30 (macOS):
#916: No conflict. It merges cleanly on top of b1b0a30, and the merged tree passes |
srperens
left a comment
There was a problem hiding this comment.
Verdict: Approve. This supersedes my Request changes at 089dee9. The rebase fixes the build break that review found, and it does so the way the review asked: the last local type in player.rs now comes from strom-types.
What moved. The branch was rebased onto main ca85fab and gained one commit, b1b0a30. In that commit:
frontend/src/api/player.rs:101—.json(&GotoRequest { index })now sends the shared type.types/src/mediaplayer.rs:66—#[derive(Debug, Clone, Serialize, Deserialize)]adds theSerializethe frontend needs.types/src/mediaplayer.rs:114—fn goto_request_wire_format() {pins the wire form as{"index":3}.
Main has moved two commits past the merge base, to af35c47. Both change only backend/src/blocks/builtin/mediaplayer/ and touch nothing in frontend/ or types/. A local trial merge of this head into af35c47 has no conflicts. I did not compile it, because there is no toolchain here. This time I also checked that no file this PR changes was changed on main since the base.
Claims
| Claim | Verdict | Evidence |
|---|---|---|
goto_player wire format unchanged |
CONFIRMED |
mediaplayer::tests::goto_request_wire_format ... ok in Check (Linux), run 37029330404 at b1b0a30 |
PlayerAction and discovery decoding unchanged |
CONFIRMED |
player_control_request_wire_format ... ok and responses_decode_with_optional_fields_absent ... ok, same job. The other rows of my earlier review are carried unchanged: the diff outside b1b0a30 is the same |
| CI covers this head | CONFIRMED |
Check (Linux), Check & Build (WASM), both Linux builds and API Contract Check pass at b1b0a30. pipeline_lifecycle_test ran in the same job |
Radius: SHARED, for the reasons in my earlier review. Four strom-types structs gain a serde direction, and frontend API calls switch to them. GotoRequest gaining Serialize adds a direction and changes nothing for the backend's Deserialize path. openapi.json is unchanged.
Overlaps: none that this PR would settle. #944, #897, #796, #792 and #786 change frontend/src/app/update.rs. None of their diffs mention control_player or the removed types (DiscoveredStream, AnnouncedStream, DiscoveredDevice). #916 changes frontend/src/api/mod.rs and frontend/src/api/tests.rs, and the author reports a clean merge with it.
Tests & CI: see the claims table. macOS and Windows were skipped. Nothing here is platform-specific, so the main-branch run covers them.
Confidence: HIGH
Superseded by my review at b1b0a30: the rebase fixed the build break this review found.
The frontend defined its own copies of ten request and response types that already exist in
strom-types. The copies existed because each shared type derived only the serde direction the backend needs (Serializefor responses,Deserializefor requests). Add the missing derive and delete the copies.discovery::DiscoveredStreamdiscovery::DiscoveredStreamResponsediscovery::AnnouncedStreamdiscovery::AnnouncedStreamResponse(+Deserialize)discovery::DiscoveredDevice(aliasNdiSource)discovery::DeviceResponse; the NDIip_address/url_addressgetters move onto itNdiStatusdiscovery::NdiDiscoveryStatus(+Deserialize)DynamicPadsResponseapi::DynamicPadsResponseParseRequest,ExportRequestapi::ParseGstLaunchRequest,api::ExportGstLaunchRequestSetPlaylistRequest,SeekRequest,ControlRequestmediaplayer::SetPlaylistRequest,SeekRequest,PlayerControlRequest(+Serialize)control_playernow takes aPlayerActioninstead of a string. The one caller already matched on the five valid action strings, so the mapping moved there.None of the copies had drifted in a way that caused a bug. The wire format is unchanged:
openapi.jsonis unchanged, because utoipa ignores which serde direction a type derives.types/src/mediaplayer.rspins thePlayerActionwire strings to the values the frontend sent before. It won't compile without the newSerializederive.types/src/discovery.rsdecode backend-shaped discovery JSON with the optional interface fields left out, and round-trip aDeviceResponsethrough its NDIip_address/url_addressgetters.The frontend now decodes discovery responses more strictly.
DeviceResponse.categoryis an enum where the copy had aString, andpropertiesno longer defaults when missing. The backend always sends both, and the frontend ships in the same build.Tests run locally, from the workspace root:
cargo test --workspace --lib: 728 + 7 + 98 passed, including the new tests.cargo test --test openapi_test: passed.cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --check: clean.Not run locally: the CI job that runs clippy on the frontend for the wasm32 target.
🤖 Generated with Claude Code