From 988569e27a6d7aa87366a1f211b82e0b0da28198 Mon Sep 17 00:00:00 2001 From: hitalin Date: Sun, 19 Jul 2026 20:16:54 +0900 Subject: [PATCH] =?UTF-8?q?refactor(streaming):=20=E3=82=A4=E3=83=99?= =?UTF-8?q?=E3=83=B3=E3=83=88=20envelope=20=E3=81=AB=20specta=20=E3=82=92?= =?UTF-8?q?=E4=BB=98=E4=B8=8E=E3=81=97=20state=20=E3=82=92=20enum=20?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit notedeck#781 Phase 2。全ストリーミングイベント envelope struct に Deserialize + specta::Type (cfg_attr) を付与し、tauri-specta の collect_events! に載せられるようにする。StreamStatusEvent.state は 自由文字列から StreamConnectionState enum (connected / reconnecting / disconnected、serde lowercase でワイヤ不変) に変更。 Co-Authored-By: Claude Fable 5 --- src/streaming.rs | 67 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/streaming.rs b/src/streaming.rs index dbab214..e797268 100644 --- a/src/streaming.rs +++ b/src/streaming.rs @@ -91,7 +91,18 @@ fn ws_config() -> WebSocketConfig { // --- Event payloads --- -#[derive(Debug, Clone, Serialize)] +/// `stream-status` で報告する接続状態 (#781)。 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[serde(rename_all = "lowercase")] +pub enum StreamConnectionState { + Connected, + Reconnecting, + Disconnected, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamNoteEvent { pub account_id: String, @@ -99,7 +110,8 @@ pub struct StreamNoteEvent { pub note: Arc, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamNotificationEvent { pub account_id: String, @@ -107,7 +119,8 @@ pub struct StreamNotificationEvent { pub notification: NormalizedNotification, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamMentionEvent { pub account_id: String, @@ -115,7 +128,8 @@ pub struct StreamMentionEvent { pub note: Arc, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamChatMessageEvent { pub account_id: String, @@ -123,7 +137,8 @@ pub struct StreamChatMessageEvent { pub message: ChatMessage, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamChatMessageDeletedEvent { pub account_id: String, @@ -142,7 +157,8 @@ struct ChatReactionWsBody { user: Option, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamChatMessageReactedEvent { pub account_id: String, @@ -152,7 +168,8 @@ pub struct StreamChatMessageReactedEvent { pub user: Option, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamChatMessageUnreactedEvent { pub account_id: String, @@ -162,7 +179,8 @@ pub struct StreamChatMessageUnreactedEvent { pub user: Option, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamMainEvent { pub account_id: String, @@ -171,7 +189,8 @@ pub struct StreamMainEvent { pub body: Value, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamNoteUpdatedEvent { pub account_id: String, @@ -182,7 +201,8 @@ pub struct StreamNoteUpdatedEvent { pub update: NoteUpdateBody, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamNoteCaptureEvent { pub account_id: String, @@ -191,11 +211,12 @@ pub struct StreamNoteCaptureEvent { pub update: NoteUpdateBody, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "specta", derive(specta::Type))] #[serde(rename_all = "camelCase")] pub struct StreamStatusEvent { pub account_id: String, - pub state: String, + pub state: StreamConnectionState, } // --- Internal commands sent to the WebSocket task --- @@ -300,16 +321,16 @@ impl StreamingManager { // 取り逃した状態遷移をここで補正できる (楽観的に connected と // 見なす JS 側ロジックを置かないための供給側の責務)。 let state = if handle.connected.load(std::sync::atomic::Ordering::Relaxed) { - "connected" + StreamConnectionState::Connected } else { - "reconnecting" + StreamConnectionState::Reconnecting }; emit_or_log!( self.emitter, "stream-status", StreamStatusEvent { account_id: account_id.to_string(), - state: state.to_string(), + state, } ); return Ok(()); @@ -391,7 +412,11 @@ impl StreamingManager { "stream-status", StreamStatusEvent { account_id: account_id.to_string(), - state: if connected { "connected" } else { "reconnecting" }.to_string(), + state: if connected { + StreamConnectionState::Connected + } else { + StreamConnectionState::Reconnecting + }, } ); @@ -434,7 +459,7 @@ impl StreamingManager { "stream-status", StreamStatusEvent { account_id: account_id.to_string(), - state: "disconnected".to_string(), + state: StreamConnectionState::Disconnected, } ); } @@ -480,7 +505,7 @@ impl StreamingManager { "stream-status", StreamStatusEvent { account_id: account_id.to_string(), - state: "connected".to_string(), + state: StreamConnectionState::Connected, } ); } @@ -1000,7 +1025,7 @@ async fn connection_task( "stream-status", StreamStatusEvent { account_id: account_id.clone(), - state: "reconnecting".to_string(), + state: StreamConnectionState::Reconnecting, } ); @@ -1047,7 +1072,7 @@ async fn connection_task( "stream-status", StreamStatusEvent { account_id: account_id.clone(), - state: "connected".to_string(), + state: StreamConnectionState::Connected, } ); @@ -1809,7 +1834,7 @@ async fn polling_loop( "stream-status", StreamStatusEvent { account_id: account_id.clone(), - state: "reconnecting".to_string(), + state: StreamConnectionState::Reconnecting, } );