11use crate :: zinit:: config;
22use crate :: { app:: api:: Status , zinit} ;
33use async_trait:: async_trait;
4- use jsonrpsee:: core:: RpcResult ;
4+ use jsonrpsee:: core:: { RpcResult , SubscriptionResult } ;
55use jsonrpsee:: proc_macros:: rpc;
66use jsonrpsee:: types:: { ErrorCode , ErrorObject , ErrorObjectOwned } ;
7+ use jsonrpsee:: PendingSubscriptionSink ;
78use serde_json:: { Map , Value } ;
89use std:: collections:: HashMap ;
910use std:: str:: FromStr ;
11+ use tokio_stream:: StreamExt ;
1012
1113use super :: api:: Api ;
1214
@@ -180,11 +182,10 @@ impl ZinitServiceApiServer for Api {
180182
181183 async fn kill ( & self , name : String , signal : String ) -> RpcResult < ( ) > {
182184 if let Ok ( sig) = nix:: sys:: signal:: Signal :: from_str ( & signal. to_uppercase ( ) ) {
183-
184- self . zinit
185- . kill ( name, sig)
186- . await
187- . map_err ( |_e| ErrorObjectOwned :: from ( ErrorCode :: InternalError ) )
185+ self . zinit
186+ . kill ( name, sig)
187+ . await
188+ . map_err ( |_e| ErrorObjectOwned :: from ( ErrorCode :: InternalError ) )
188189 } else {
189190 Err ( ErrorObjectOwned :: from ( ErrorCode :: InternalError ) )
190191 }
@@ -205,7 +206,9 @@ impl ZinitServiceApiServer for Api {
205206
206207 // Check if the service file already exists
207208 if file_path. exists ( ) {
208- return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError ( SERVICE_ALREADY_EXISTS ) ) ) ;
209+ return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError (
210+ SERVICE_ALREADY_EXISTS ,
211+ ) ) ) ;
209212 }
210213
211214 // Convert the JSON content to YAML
@@ -236,7 +239,9 @@ impl ZinitServiceApiServer for Api {
236239
237240 // Check if the service file exists
238241 if !file_path. exists ( ) {
239- return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError ( SERVICE_NOT_FOUND ) ) ) ;
242+ return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError (
243+ SERVICE_NOT_FOUND ,
244+ ) ) ) ;
240245 }
241246
242247 // Delete the file
@@ -260,7 +265,9 @@ impl ZinitServiceApiServer for Api {
260265
261266 // Check if the service file exists
262267 if !file_path. exists ( ) {
263- return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError ( SERVICE_NOT_FOUND ) ) ) ;
268+ return Err ( ErrorObjectOwned :: from ( ErrorCode :: ServerError (
269+ SERVICE_NOT_FOUND ,
270+ ) ) ) ;
264271 }
265272
266273 // Read the file content
@@ -294,11 +301,17 @@ pub trait ZinitSystemApi {
294301#[ async_trait]
295302impl ZinitSystemApiServer for Api {
296303 async fn shutdown ( & self ) -> RpcResult < ( ) > {
297- self . zinit . shutdown ( ) . await . map_err ( |_e| ErrorObjectOwned :: from ( ErrorCode :: ServerError ( SHUTTING_DOWN ) ) )
304+ self . zinit
305+ . shutdown ( )
306+ . await
307+ . map_err ( |_e| ErrorObjectOwned :: from ( ErrorCode :: ServerError ( SHUTTING_DOWN ) ) )
298308 }
299-
309+
300310 async fn reboot ( & self ) -> RpcResult < ( ) > {
301- self . zinit . reboot ( ) . await . map_err ( |_| ErrorObjectOwned :: from ( ErrorCode :: InternalError ) )
311+ self . zinit
312+ . reboot ( )
313+ . await
314+ . map_err ( |_| ErrorObjectOwned :: from ( ErrorCode :: InternalError ) )
302315 }
303316}
304317
@@ -310,13 +323,61 @@ pub trait ZinitLoggingApi {
310323 /// Subscribe to log messages generated by zinit and monitored services.
311324 /// An optional filter can be provided to only receive logs containing the filter string.
312325 /// The subscription returns a stream of log lines (String).
313- #[ subscription( name = "subscribeLogs" , item = String , unsubscribe = "log_unsubscribe" ) ]
314- async fn log_subscribe ( & self , filter : Option < String > ) ;
326+ #[ subscription( name = "subscribeLogs" , item = String ) ]
327+ async fn log_subscribe ( & self , filter : Option < String > ) -> SubscriptionResult ;
315328}
316329
317330#[ async_trait]
318331impl ZinitLoggingApiServer for Api {
319332 async fn logs ( & self , name : Option < String > ) -> RpcResult < Vec < String > > {
320- self . zinit . logs ( )
333+ let filter = name. map ( |n| format ! ( "{n}:" ) ) ;
334+ Ok (
335+ tokio_stream:: wrappers:: ReceiverStream :: new ( self . zinit . logs ( true , false ) . await )
336+ . filter_map ( |l| {
337+ if let Some ( ref filter) = filter {
338+ if l[ 4 ..] . starts_with ( filter) {
339+ Some ( l. to_string ( ) )
340+ } else {
341+ None
342+ }
343+ } else {
344+ Some ( l. to_string ( ) )
345+ }
346+ } )
347+ . collect ( )
348+ . await ,
349+ )
350+ }
351+
352+ async fn log_subscribe (
353+ & self ,
354+ sink : PendingSubscriptionSink ,
355+ name : Option < String > ,
356+ ) -> SubscriptionResult {
357+ let sink = sink. accept ( ) . await ?;
358+ let filter = name. map ( |n| format ! ( "{n}:" ) ) ;
359+ let mut stream =
360+ tokio_stream:: wrappers:: ReceiverStream :: new ( self . zinit . logs ( false , true ) . await )
361+ . filter_map ( |l| {
362+ if let Some ( ref filter) = filter {
363+ if l[ 4 ..] . starts_with ( filter) {
364+ Some ( l. to_string ( ) )
365+ } else {
366+ None
367+ }
368+ } else {
369+ Some ( l. to_string ( ) )
370+ }
371+ } ) ;
372+ while let Some ( log) = stream
373+ . next ( )
374+ . await
375+ {
376+ if sink. send ( log. into ( ) ) . await . is_err ( ) {
377+ break ;
378+ }
379+ }
380+
381+ Ok ( ( ) )
321382 }
322383}
0 commit comments