feat: add gRPC client with config-based server address and album support

- Add tonic/prost gRPC client connecting to music-agregator service
- Add config.yaml for configurable server host/port
- Add build.rs for proto compilation from music-agregator
- Update Artist/Album models to match proto with MonitorState enum
- Convert album list from GetArtists response
- Fix album click selection with correct layout offsets
- Improve monitor state icons for better visibility
This commit is contained in:
Alexander
2026-05-08 23:10:15 +02:00
parent 620bd374de
commit e77e854d2e
14 changed files with 1812 additions and 50 deletions
+73
View File
@@ -0,0 +1,73 @@
use tokio::sync::mpsc;
use tonic::transport::Channel;
use crate::proto::music_agregator_v1::music_agregator_service_client::MusicAgregatorServiceClient;
pub use crate::proto::music_agregator_v1::{AlbumDetail, ArtistSummary, GetArtistsRequest};
#[derive(Debug)]
pub enum GrpcRequest {
GetArtists,
}
#[derive(Debug)]
pub enum GrpcResponse {
Artists(Vec<ArtistSummary>),
Error(String),
}
pub struct GrpcClient {
music: MusicAgregatorServiceClient<Channel>,
}
impl GrpcClient {
pub async fn connect(addr: &str) -> Result<Self, tonic::transport::Error> {
let channel = Channel::from_shared(addr.to_string())
.expect("valid uri")
.connect()
.await?;
Ok(Self {
music: MusicAgregatorServiceClient::new(channel),
})
}
pub async fn get_artists(&mut self) -> Result<Vec<ArtistSummary>, tonic::Status> {
let response = self.music.get_artists(GetArtistsRequest {}).await?;
Ok(response.into_inner().artists)
}
}
pub fn spawn_grpc_worker(
addr: String,
) -> (mpsc::Sender<GrpcRequest>, mpsc::Receiver<GrpcResponse>) {
let (req_tx, mut req_rx) = mpsc::channel::<GrpcRequest>(32);
let (resp_tx, resp_rx) = mpsc::channel::<GrpcResponse>(32);
tokio::spawn(async move {
let client = match GrpcClient::connect(&addr).await {
Ok(c) => c,
Err(e) => {
let _ = resp_tx.send(GrpcResponse::Error(e.to_string())).await;
return;
}
};
let mut client = client;
while let Some(request) = req_rx.recv().await {
let response = match request {
GrpcRequest::GetArtists => match client.get_artists().await {
Ok(artists) => GrpcResponse::Artists(artists),
Err(e) => GrpcResponse::Error(e.to_string()),
},
};
if resp_tx.send(response).await.is_err() {
break;
}
}
});
(req_tx, resp_rx)
}