fix(qconnect): align queue load payload and inbound diagnostics
cx
This commit is contained in:
3 files changed
+91
-8
No files matched your search
@@ -187,8 +187,7 @@ fn map_queue_command(command: &QueueCommand) -> Result<QConnectMessage, Protocol
|
|||||||
let shuffle_mode = optional_bool(&command.payload, "shuffle_mode", false);
|
let shuffle_mode = optional_bool(&command.payload, "shuffle_mode", false);
|
||||||
let context_uuid = optional_uuid_bytes(&command.payload, &["context_uuid"])?;
|
let context_uuid = optional_uuid_bytes(&command.payload, &["context_uuid"])?;
|
||||||
let autoplay_reset = optional_bool(&command.payload, "autoplay_reset", false);
|
let autoplay_reset = optional_bool(&command.payload, "autoplay_reset", false);
|
||||||
let autoplay_loading =
|
let autoplay_loading = optional_bool(&command.payload, "autoplay_loading", false);
|
||||||
optional_bool(&command.payload, "autoplay_loading", autoplay_reset);
|
|
||||||
|
|
||||||
Ok(QConnectMessage {
|
Ok(QConnectMessage {
|
||||||
message_type: Some(QConnectMessageType::MessageTypeCtrlSrvrQueueLoadTracks as i32),
|
message_type: Some(QConnectMessageType::MessageTypeCtrlSrvrQueueLoadTracks as i32),
|
||||||
@@ -1084,7 +1083,7 @@ mod tests {
|
|||||||
assert_eq!(load.shuffle_seed, Some(3344));
|
assert_eq!(load.shuffle_seed, Some(3344));
|
||||||
assert_eq!(load.shuffle_pivot_index, Some(1));
|
assert_eq!(load.shuffle_pivot_index, Some(1));
|
||||||
assert_eq!(load.autoplay_reset, Some(true));
|
assert_eq!(load.autoplay_reset, Some(true));
|
||||||
assert_eq!(load.autoplay_loading, Some(true));
|
assert_eq!(load.autoplay_loading, Some(false));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
load.queue_version_ref
|
load.queue_version_ref
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1100,6 +1099,37 @@ mod tests {
|
|||||||
assert_eq!(load.context_uuid.as_ref().map(|uuid| uuid.len()), Some(16));
|
assert_eq!(load.context_uuid.as_ref().map(|uuid| uuid.len()), Some(16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn defaults_queue_load_tracks_autoplay_loading_to_false_when_omitted() {
|
||||||
|
let command = QueueCommand::new(
|
||||||
|
QueueCommandType::CtrlSrvrQueueLoadTracks,
|
||||||
|
"f997cd72-d2ce-4121-a89b-75bf2be251ec",
|
||||||
|
QueueVersion::new(3, 9),
|
||||||
|
json!({
|
||||||
|
"track_ids": [2001, 2002, 2003],
|
||||||
|
"queue_position": 2,
|
||||||
|
"shuffle_mode": false,
|
||||||
|
"shuffle_pivot_index": 2,
|
||||||
|
"context_uuid": "a3f7be0f-3854-44c6-9194-c93cedec322a",
|
||||||
|
"autoplay_reset": true
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let payload = encode_queue_command_batch(&command).expect("batch payload");
|
||||||
|
let decoded = QConnectMessages::decode(payload.as_slice()).expect("decode batch");
|
||||||
|
let load = decoded.messages[0]
|
||||||
|
.ctrl_srvr_queue_load_tracks
|
||||||
|
.as_ref()
|
||||||
|
.expect("queue load payload");
|
||||||
|
|
||||||
|
assert_eq!(load.queue_position, Some(2));
|
||||||
|
assert_eq!(load.shuffle_mode, Some(false));
|
||||||
|
assert_eq!(load.shuffle_pivot_index, Some(2));
|
||||||
|
assert_eq!(load.autoplay_reset, Some(true));
|
||||||
|
assert_eq!(load.autoplay_loading, Some(false));
|
||||||
|
assert_eq!(load.context_uuid.as_ref().map(|uuid| uuid.len()), Some(16));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encodes_renderer_state_updated_report_with_queue_version() {
|
fn encodes_renderer_state_updated_report_with_queue_version() {
|
||||||
let report = RendererReport::new(
|
let report = RendererReport::new(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, OnceLock},
|
sync::{Arc, OnceLock},
|
||||||
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -12,7 +13,7 @@ use qconnect_app::{
|
|||||||
};
|
};
|
||||||
use qconnect_transport_ws::{NativeWsTransport, WsTransportConfig};
|
use qconnect_transport_ws::{NativeWsTransport, WsTransportConfig};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::{json, Value};
|
||||||
use tauri::async_runtime::JoinHandle;
|
use tauri::async_runtime::JoinHandle;
|
||||||
use tauri::{AppHandle, Emitter, State};
|
use tauri::{AppHandle, Emitter, State};
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
@@ -308,6 +309,38 @@ struct QconnectRemoteSyncState {
|
|||||||
session: QconnectSessionState,
|
session: QconnectSessionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn queue_payload_track_preview(payload: &Value, key: &str) -> Vec<i64> {
|
||||||
|
payload
|
||||||
|
.get(key)
|
||||||
|
.and_then(Value::as_array)
|
||||||
|
.map(|tracks| {
|
||||||
|
tracks
|
||||||
|
.iter()
|
||||||
|
.filter_map(|track| track.get("track_id").and_then(Value::as_i64))
|
||||||
|
.take(8)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_qconnect_diagnostic(app_handle: &AppHandle, channel: &str, level: &str, payload: Value) {
|
||||||
|
let ts = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.map(|duration| duration.as_millis() as u64)
|
||||||
|
.unwrap_or(0);
|
||||||
|
if let Err(err) = app_handle.emit(
|
||||||
|
"qconnect:diagnostic",
|
||||||
|
json!({
|
||||||
|
"ts": ts,
|
||||||
|
"channel": channel,
|
||||||
|
"level": level,
|
||||||
|
"payload": payload,
|
||||||
|
}),
|
||||||
|
) {
|
||||||
|
log::warn!("[QConnect] Failed to emit diagnostic {channel}: {err}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct QconnectSessionState {
|
pub struct QconnectSessionState {
|
||||||
pub session_uuid: Option<String>,
|
pub session_uuid: Option<String>,
|
||||||
@@ -587,6 +620,20 @@ impl QconnectServiceState {
|
|||||||
}
|
}
|
||||||
qconnect_transport_ws::TransportEvent::InboundQueueServerEvent(evt) => {
|
qconnect_transport_ws::TransportEvent::InboundQueueServerEvent(evt) => {
|
||||||
log::info!("[QConnect] <-- Inbound queue event: {} payload={}", evt.message_type(), evt.payload);
|
log::info!("[QConnect] <-- Inbound queue event: {} payload={}", evt.message_type(), evt.payload);
|
||||||
|
emit_qconnect_diagnostic(
|
||||||
|
&app_for_errors,
|
||||||
|
"qconnect:inbound_queue_event",
|
||||||
|
"info",
|
||||||
|
json!({
|
||||||
|
"message_type": evt.message_type(),
|
||||||
|
"action_uuid": evt.action_uuid.clone(),
|
||||||
|
"queue_version": evt.queue_version,
|
||||||
|
"track_count": evt.payload.get("tracks").and_then(|value| value.as_array()).map(|tracks| tracks.len()).unwrap_or(0),
|
||||||
|
"autoplay_track_count": evt.payload.get("autoplay_tracks").and_then(|value| value.as_array()).map(|tracks| tracks.len()).unwrap_or(0),
|
||||||
|
"preview_track_ids": queue_payload_track_preview(&evt.payload, "tracks"),
|
||||||
|
"preview_autoplay_track_ids": queue_payload_track_preview(&evt.payload, "autoplay_tracks"),
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
qconnect_transport_ws::TransportEvent::InboundRendererServerCommand(cmd) => {
|
qconnect_transport_ws::TransportEvent::InboundRendererServerCommand(cmd) => {
|
||||||
log::info!("[QConnect] <-- Inbound renderer command: {} payload={}", cmd.message_type(), cmd.payload);
|
log::info!("[QConnect] <-- Inbound renderer command: {} payload={}", cmd.message_type(), cmd.payload);
|
||||||
|
|||||||
@@ -530,17 +530,23 @@ export async function loadQconnectQueue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const normalizedStartIndex = Math.max(0, Math.min(startIndex, Math.max(trackIds.length - 1, 0)));
|
||||||
|
const shuffleSeed = shuffleMode
|
||||||
|
? Math.floor(Math.random() * 0x1_0000_0000)
|
||||||
|
: undefined;
|
||||||
const payload = {
|
const payload = {
|
||||||
track_ids: trackIds,
|
track_ids: trackIds,
|
||||||
queue_position: startIndex,
|
queue_position: shuffleMode ? 0 : normalizedStartIndex,
|
||||||
|
shuffle_seed: shuffleSeed,
|
||||||
|
shuffle_pivot_index: normalizedStartIndex,
|
||||||
shuffle_mode: shuffleMode,
|
shuffle_mode: shuffleMode,
|
||||||
context_uuid: crypto.randomUUID(),
|
context_uuid: crypto.randomUUID(),
|
||||||
autoplay_reset: true,
|
autoplay_reset: true,
|
||||||
autoplay_loading: true
|
autoplay_loading: false
|
||||||
};
|
};
|
||||||
await emitQconnectDiagnostic('qconnect:queue_load_tracks', 'info', {
|
await emitQconnectDiagnostic('qconnect:queue_load_tracks', 'info', {
|
||||||
track_count: trackIds.length,
|
track_count: trackIds.length,
|
||||||
start_index: startIndex,
|
start_index: normalizedStartIndex,
|
||||||
shuffle_mode: shuffleMode,
|
shuffle_mode: shuffleMode,
|
||||||
preview_track_ids: trackIds.slice(0, 8),
|
preview_track_ids: trackIds.slice(0, 8),
|
||||||
payload
|
payload
|
||||||
@@ -550,7 +556,7 @@ export async function loadQconnectQueue(
|
|||||||
console.log('[QConnect/LoadQueue] SUCCESS');
|
console.log('[QConnect/LoadQueue] SUCCESS');
|
||||||
await emitQconnectDiagnostic('qconnect:queue_load_sent', 'info', {
|
await emitQconnectDiagnostic('qconnect:queue_load_sent', 'info', {
|
||||||
track_count: trackIds.length,
|
track_count: trackIds.length,
|
||||||
start_index: startIndex,
|
start_index: normalizedStartIndex,
|
||||||
shuffle_mode: shuffleMode,
|
shuffle_mode: shuffleMode,
|
||||||
preview_track_ids: trackIds.slice(0, 8)
|
preview_track_ids: trackIds.slice(0, 8)
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user