seed-rs / seed

A Rust framework for creating web apps
MIT License
3.81k stars 155 forks source link

Websocket API changed from 0.8 to 0.9 #678

Closed wuerges closed 2 years ago

wuerges commented 2 years ago

Hello, I have a small project that uses Seed for the front-end: https://github.com/wuerges/maratona-animeitor-rust/

I'm updating the project's dependencies and the project is breaking when I change the seed version from 0.8 to 0.9.

I think I must be doing something silly. Could someone shed me some light?

The way things were set up in version 0.8 was like this: My service would produce a sequence of JSON messages of the rust RunTuple type, than derives both I used serde_json to create these messages and send them one by one, each one in their own WebSocket message:

➜  maratona-animeitor-rust git:(tokio_update) ✗ websocat ws://127.0.0.1:9091/allruns_ws
{"id":198836082,"time":8,"team_login":"teambrbr10","prob":"K","answer":"No"}
{"id":198985583,"time":8,"team_login":"teambrbr32","prob":"K","answer":{"Yes":8}}
{"id":199354284,"time":8,"team_login":"teambrbr40","prob":"K","answer":"No"}
{"id":199468485,"time":9,"team_login":"teambrbr4","prob":"K","answer":{"Yes":9}}
{"id":199513986,"time":9,"team_login":"teambrbr44","prob":"M","answer":"No"}
...

The message is produced directly from the Rust type, using serde derive:

#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct RunTuple {
    pub id: i64,
    pub time: i64,
    pub team_login: String,
    pub prob: String,
    pub answer: Answer,
}

I used serde_json to send the message:

async fn convert_and_send(tx: &mut SplitSink<warp::ws::WebSocket, Message>, r : RunTuple) -> bool {
    let m = serde_json::to_string(&r).map(Message::text).expect("Expected a message");
    tx.send(m).await.is_ok()
}

Then I used WebSocketMessage.json() to parse it:

let run : data::RunTuple = m.json().expect("Expected a RunTuple");

This worked well in seed 0.8.

When I updated to seed 0.9, I'm getting a SerdeError when I call the m.json() method:

"Websocket error: {}" JsonError(
    Serde(
        JsValue("invalid type: string "{\"id\":329154707,\"time\":225,\"team_login\":\"teambrbr20\",\"prob\":\"J\",\"answer\":\"No\"}", expected struct RunTuple at line 1 column 96"),
    ),
)
package.js:806 "Websocket error: {}" JsonError(
    Serde(
        JsValue("invalid type: string "{\"id\":329164608,\"time\":225,\"team_login\":\"teambrbr36\",\"prob\":\"M\",\"answer\":\"No\"}", expected struct RunTuple at line 1 column 96"),
    ),
)
package.js:806 "Websocket error: {}" JsonError(
    Serde(
        JsValue("invalid type: string "{\"id\":329197109,\"time\":225,\"team_login\":\"teambrbr3\",\"prob\":\"D\",\"answer\":\"No\"}", expected struct RunTuple at line 1 column 95"),
    ),
)

Was there a serde api change for parsing Json values from WebSocket messages?

wuerges commented 2 years ago

This is the code with more context, using the a Timer component from my app (simpler, easier to debug):

Msg::TimerUpdate(m) => {
            // Gets the text of the websocket message
            let text = m.text().expect("text");

            // Gets the JsValue: WORKS!
            let js_value : JsValue = JsValue::from_str(&text);
            log!(js_value);

            // Gets the data::TimerData directly from the text: WORKS!
            let timer_serde : data::TimerData = serde_json::from_str(&text).expect("timer data");
            log!(timer_serde);

            // Gets the data::TimerData from the JsValue: BROKEN =/
            let timer_into_serde : data::TimerData = js_value.into_serde().expect("timer data");
            // Gets the data::TimerData from the message directly: same error as previous line =/
            // let timer_into_serde : data::TimerData = m.json().expect("timer data");
            log!(timer_into_serde);
}

This is the complete stack trace:

<div aria-expanded="true" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; outline-width: 0px; flex: 0 0 auto; color: rgb(189, 198, 207); font-family: menlo, monospace; font-size: 11px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(41, 0, 0); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><span class="source-code" style="box-sizing: border-box; min-width: 0px; min-height: 0px; font-family: var(--source-code-font-family); white-space: pre-wrap; font-size: var(--source-code-font-size) !important; line-height: 1.2;"><span class="console-message-text" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-error-text-color) !important;">panicked at 'timer data: JsonError(Serde(JsValue("invalid type: string "{\"current_time\":18000,\"score_freeze_time\":240}", expected struct TimerData at line 1 column 52")))', src<span class="devtools-link" title="/timer.rs" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">/timer.rs:53</span>:63

Stack:

Error
    at <span class="devtools-link" title="http://localhost:9091/pkg/package.js" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package.js:894:21</span>
    at logError (<span class="devtools-link" title="http://localhost:9091/pkg/package.js" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package.js:215:18</span>)
    at imports.wbg.__wbg_new_693216e109162396 (<span class="devtools-link" title="http://localhost:9091/pkg/package.js" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package.js:893:66</span>)
    at console_error_panic_hook::Error::new::h1c39fd35afbbb4a5 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[18822]:0x4b58ef</span>)
    at console_error_panic_hook::hook_impl::hdfedb59762f54421 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[2276]:0x261c3b</span>)
    at console_error_panic_hook::hook::hedca99b1de3e78ef (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[21089]:0x4d4663</span>)
    at core::ops::function::Fn::call::h1130f098708501a8 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[17501]:0x4a0ecb</span>)
    at std::panicking::rust_panic_with_hook::he2a025723e105e28 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[5031]:0x3330ff</span>)
    at std::panicking::begin_panic_handler::{{closure}}::hd9f8c213ec91b9d5 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[8237]:0x3c178c</span>)
    at std::sys_common::backtrace::__rust_end_short_backtrace::h6efd730283875809 (<span class="devtools-link" title="http://localhost:9091/pkg/package_bg.wasm" role="link" tabindex="-1" style="box-sizing: border-box; min-width: 0px; min-height: 0px; color: var(--override-console-link-color); text-decoration: underline; cursor: pointer; word-break: break-all;">http://localhost:9091/pkg/package_bg.wasm:wasm-function[24225]:0x4f1b77</span>)

</span></span></div><div class="" role="group" style="box-sizing: border-box; min-width: 0px; min-height: 0px; flex: 0 0 auto; color: rgb(189, 198, 207); font-family: menlo, monospace; font-size: 11px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(41, 0, 0); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><span class="monospace" style="display: inline-block; --monospace-font-size:11px; --monospace-font-family:menlo,monospace; --source-code-font-size:11px; --source-code-font-family:menlo,monospace; box-sizing: border-box; min-width: 0px; min-height: 0px; font-family: var(--monospace-font-family); font-size: var(--monospace-font-size) !important;">

  | (anonymous) | @ | package.js:888
-- | -- | -- | --
  | logError | @ | package.js:215
  | imports.wbg.__wbg_error_09919627ac0992f5 | @ | package.js:886
  | $console_error_panic_hook::error::h616a196825dc61ff | @ | package_bg.wasm:0x38dc48
  | $console_error_panic_hook::hook_impl::hdfedb59762f54421 | @ | package_bg.wasm:0x261d34
  | $console_error_panic_hook::hook::hedca99b1de3e78ef | @ | package_bg.wasm:0x4d4663
  | $core::ops::function::Fn::call::h1130f098708501a8 | @ | package_bg.wasm:0x4a0ecb
  | $std::panicking::rust_panic_with_hook::he2a025723e105e28 | @ | package_bg.wasm:0x3330ff
  | $std::panicking::begin_panic_handler::{{closure}}::hd9f8c213ec91b9d5 | @ | package_bg.wasm:0x3c178c
  | $std::sys_common::backtrace::__rust_end_short_backtrace::h6efd730283875809 | @ | package_bg.wasm:0x4f1b77
  | $rust_begin_unwind | @ | package_bg.wasm:0x4c2516
  | $core::panicking::panic_fmt::hb02133958c1e7d35 | @ | package_bg.wasm:0x4c85e3
  | $core::result::unwrap_failed::h68fdaca771c68bb6 | @ | package_bg.wasm:0x3ebc6e
  | $core::result::Result<T,E>::expect::h45f295aeab189c71 | @ | package_bg.wasm:0x31dae6
  | $client::timer::update::hb58141fbf574aa26 | @ | package_bg.wasm:0xa2f61
  | $core::ops::function::FnOnce::call_once::hdb69693728f65cde | @ | package_bg.wasm:0x3d53aa
  | $seed::app::App<Ms,Mdl,INodes>::start::{{closure}}::h1510bae19fd7da34 | @ | package_bg.wasm:0x328af0
  | $<alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h280fdc4bb796e790 | @ | package_bg.wasm:0x2fcf50
  | $seed::app::App<Ms,Mdl,INodes>::process_queue_message::haaebd5c43b10dca3 | @ | package_bg.wasm:0x13f9b7
  | $seed::app::App<Ms,Mdl,INodes>::process_effect_queue::h4afb546df8fe9675 | @ | package_bg.wasm:0x18849a
  | $seed::app::App<Ms,Mdl,INodes>::update_with_option::h2cfe323f4352b621 | @ | package_bg.wasm:0x29fea3
  | $seed::app::App<Ms,Mdl,INodes>::mailbox::{{closure}}::h9fd1b2abf28ef90f | @ | package_bg.wasm:0x410646
  | $seed::virtual_dom::mailbox::Mailbox<Ms>::send::h6b6b005681754c86 | @ | package_bg.wasm:0x2d351a
  | $seed::browser::web_socket::builder::create_js_handler::{{closure}}::h0dbcdc9feb6292da | @ | package_bg.wasm:0x2e8d7c
  | $<dyn core::ops::function::Fn<(A,)>+Output = R as wasm_bindgen::closure::WasmClosure>::describe::invoke::hd98873b86701ab5c | @ | package_bg.wasm:0x362e50
  | __wbg_adapter_28 | @ | package.js:235
  | real

</span></div>
wuerges commented 2 years ago

These are the changes that caused the error: https://github.com/wuerges/maratona-animeitor-rust/pull/23/files

flosse commented 2 years ago

@wuerges thanks for reporting the issue. I'll have a look at it next week.

flosse commented 2 years ago

I just tried the websocket example in the seed repo and I can confirm that this is bug :disappointed:

flosse commented 2 years ago

@wuerges could you test your code with #693?