pispas_modules/
persistence.rs

1use async_trait::async_trait;
2use easy_trace::prelude::{debug, error, info};
3use serde_json::{Value};
4use std::collections::HashMap;
5use std::sync::Arc;
6use tokio::sync::Mutex;
7use crate::service::{Service, WebSocketWrite};
8use std::io::{Read, Write};
9use std::net::TcpStream;
10use std::path::Path;
11use sharing::service::{Action, SafeHandle};
12use sharing::crypto;
13
14const PERSISTENCE_PASSWORD: &str = "R4nd0mlyG3n3r4t3dP4ssw0rd";
15
16/// Version of the PersistenceService module.
17pub const PERSISTENCE_VERSION: &str = "1.0.0";
18
19/// Persistence service implementation for handling key-value storage operations.
20pub struct PersistenceService {
21    /// In-memory cache of the key-value store
22    pub cache: Arc<Mutex<HashMap<String, Value>>>,
23    /// Handle from service.exe OR direct file handle
24    pub file_handle: Arc<Mutex<Option<SafeHandle>>>,
25    /// Path to the persistence file
26    pub file_path: String,
27    /// Whether we're using service.exe protection
28    pub using_service_protection: bool,
29}
30
31impl PersistenceService {
32    /// Creates a new instance of the PersistenceService.
33    pub fn new() -> Self {
34        info!("PersistenceService initialized (version: {})", PERSISTENCE_VERSION);
35
36        let file_path = sharing::paths::get_persistance_path();
37        let service = PersistenceService {
38            cache: Arc::new(Mutex::new(HashMap::new())),
39            file_handle: Arc::new(Mutex::new(None)),
40            file_path: file_path.display().to_string(),
41            using_service_protection: false,
42        };
43
44        service
45    }
46
47    /// Initialize the service - gets handles and loads data
48    pub async fn initialize(&mut self) -> Result<(), String> {
49        // Try to get handle from service.exe first
50        match self.try_get_handle_from_service() {
51            Ok(handle) => {
52                info!("Got handle from service.exe successfully");
53                self.using_service_protection = true;
54                *self.file_handle.lock().await = Some(handle);
55            }
56            Err(e) => {
57                error!("Failed to get handle from service.exe: {}", e);
58                info!("Opening file directly...");
59
60                // Open file directly and get handle
61                match self.try_open_file_directly_with_handle() {
62                    Ok(handle) => {
63                        info!("Got direct file handle successfully");
64                        *self.file_handle.lock().await = Some(handle);
65                    }
66                    Err(e) => {
67                        error!("Failed to open file directly: {}", e);
68                        info!("PersistenceService will work in memory-only mode");
69                    }
70                }
71            }
72        }
73
74        // Try to load existing data if we have any handle
75        if let Err(e) = self.try_load_data().await {
76            error!("Failed to load existing data: {}", e);
77        }
78
79        Ok(())
80    }
81
82    /// Attempts to get a file handle from service.exe via pipe
83    fn try_get_handle_from_service(&self) -> Result<SafeHandle, String> {
84        info!("Requesting file handle from service.exe for: {}", self.file_path);
85
86        let mut stream = match TcpStream::connect(sharing::CHANNEL_NAME) {
87            Ok(stream) => stream,
88            Err(e) => return Err(format!("Could not connect to service.exe: {}", e)),
89        };
90
91        info!("Connected to service.exe pipe successfully");
92
93        // Usar el enum Action existente
94        let action = Action::GetHandle(self.file_path.clone());
95        match stream.write_all(action.to_string().as_bytes()) {
96            Ok(_) => {},
97            Err(e) => return Err(format!("Failed to send GET_HANDLE request: {}", e)),
98        }
99
100        info!("GET_HANDLE request sent, waiting for response...");
101
102        // Read response from service.exe
103        let mut buffer = [0; 1024];
104        let bytes_read = match stream.read(&mut buffer) {
105            Ok(bytes) => bytes,
106            Err(e) => return Err(format!("Failed to read response: {}", e)),
107        };
108
109        let response = String::from_utf8_lossy(&buffer[..bytes_read]);
110        info!("Received response from service.exe: {}", response);
111
112        if response.starts_with("HANDLE_OK:") {
113            // Extract handle value
114            let handle_str = response.strip_prefix("HANDLE_OK:").unwrap_or("");
115            match handle_str.parse::<usize>() {
116                Ok(handle_value) => {
117                    let handle = SafeHandle::new(handle_value as *mut std::ffi::c_void);
118                    info!("File handle received from service.exe: {:?}", handle_value);
119                    Ok(handle)
120                }
121                Err(_) => Err("Invalid handle format in response".to_string()),
122            }
123        } else if response.starts_with("HANDLE_ERROR:") {
124            let error_msg = response.strip_prefix("HANDLE_ERROR:").unwrap_or("Unknown error");
125            Err(format!("Service.exe error: {}", error_msg))
126        } else {
127            Err("Unexpected response from service.exe".to_string())
128        }
129    }
130
131    /// Opens the file directly and returns a SafeHandle
132    ///
133    #[cfg(not(target_os = "windows"))]
134    fn try_open_file_directly_with_handle(&self) -> Result<SafeHandle, String> {
135        use std::fs::OpenOptions;
136        use std::os::unix::io::AsRawFd;
137        
138        info!("Opening persistence file directly: {}", self.file_path);
139
140        // Create directory if it doesn't exist
141        if let Some(parent) = Path::new(&self.file_path).parent() {
142            match std::fs::create_dir_all(parent) {
143                Ok(_) => {},
144                Err(e) => return Err(format!("Failed to create directory: {}", e)),
145            }
146        }
147
148
149        let file = match OpenOptions::new()
150            .read(true)
151            .write(true)
152            .create(true)
153            .open(&self.file_path) {
154            Ok(file) => file,
155            Err(e) => return Err(format!("Failed to open file: {}", e)),
156        };
157
158        let handle = file.as_raw_fd() as *mut std::ffi::c_void;
159        std::mem::forget(file); // Keep file open
160
161        Ok(SafeHandle::new(handle))
162    }
163    #[cfg(target_os = "windows")]
164    fn try_open_file_directly_with_handle(&self) -> Result<SafeHandle, String> {
165        info!("Opening persistence file directly: {}", self.file_path);
166
167        // Create directory if it doesn't exist
168        if let Some(parent) = Path::new(&self.file_path).parent() {
169            match std::fs::create_dir_all(parent) {
170                Ok(_) => {},
171                Err(e) => return Err(format!("Failed to create directory: {}", e)),
172            }
173        }
174
175        use std::fs::OpenOptions;
176        use std::os::windows::io::AsRawHandle;
177
178        let file = match OpenOptions::new()
179            .read(true)
180            .write(true)
181            .create(true)
182            .open(&self.file_path) {
183            Ok(file) => file,
184            Err(e) => return Err(format!("Failed to open file: {}", e)),
185        };
186
187        let handle = file.as_raw_handle() as *mut std::ffi::c_void;
188        std::mem::forget(file); // Keep file open
189
190        Ok(SafeHandle::new(handle))
191    }
192
193    /// Reads data using the SafeHandle if available, otherwise fallback to fs::read
194    async fn read_file_data(&self) -> Result<Vec<u8>, String> {
195        let file_handle = self.file_handle.lock().await;
196
197        if let Some(safe_handle) = *file_handle {
198            if safe_handle.is_valid() {
199                info!("Reading file using {} handle",
200                      if self.using_service_protection { "service" } else { "direct" });
201                drop(file_handle); // Release lock before reading
202                return self.read_with_handle(&safe_handle);
203            }
204        }
205        drop(file_handle);
206
207        // Fallback to standard file read
208        info!("Reading file using fallback fs::read");
209        match std::fs::read(&self.file_path) {
210            Ok(data) => Ok(data),
211            Err(e) => Err(format!("Failed to read persistence file: {}", e)),
212        }
213    }
214
215    /// Reads data using a SafeHandle
216    /// Writes data using a SafeHandle (multiplataforma)
217    /// Reads data using a SafeHandle (multiplataforma)
218    fn read_with_handle(&self, handle: &SafeHandle) -> Result<Vec<u8>, String> {
219        #[cfg(target_os = "windows")]
220        {
221            use winapi::um::fileapi::{ReadFile, SetFilePointer, GetFileSize};
222            use winapi::um::errhandlingapi::GetLastError;
223            use winapi::um::winbase::FILE_BEGIN;
224            use winapi::um::handleapi::INVALID_HANDLE_VALUE;
225
226            let handle_value = handle.get_handle();
227
228            // 🔍 VERIFICAR QUE EL HANDLE ES VÁLIDO
229            if handle_value.is_null() || handle_value == INVALID_HANDLE_VALUE {
230                return Err("Invalid handle value".to_string());
231            }
232
233            info!("Windows: Using file handle: {:?}", handle_value);
234
235            // Reset file pointer to beginning
236            let seek_result = unsafe {
237                SetFilePointer(handle_value, 0, std::ptr::null_mut(), FILE_BEGIN)
238            };
239
240            if seek_result == 0xFFFFFFFF {
241                info!("SetFilePointer failed, checking for error");
242                let error_code = unsafe { GetLastError() };
243                return Err(format!("SetFilePointer failed with error: {}", error_code));
244            }
245
246            // Get file size - VERIFICAR ERROR
247            let file_size = unsafe { GetFileSize(handle_value, std::ptr::null_mut()) };
248
249            if file_size == 0xFFFFFFFF {
250                let error_code = unsafe { GetLastError() };
251                info!("GetFileSize failed, checking for error");
252                return Err(format!("GetFileSize failed with error: {} (handle may be invalid)", error_code));
253            }
254
255            info!("File size from handle: {} bytes", file_size);
256
257            if file_size == 0 {
258                info!("File is empty, returning empty vector");
259                return Ok(Vec::new());
260            }
261
262            // Read file data
263            let mut buffer = vec![0u8; file_size as usize];
264            let mut bytes_read: u32 = 0;
265
266            info!("Reading {} bytes from file handle: {:?}", file_size, handle_value);
267
268            let result = unsafe {
269                ReadFile(
270                    handle_value,
271                    buffer.as_mut_ptr() as *mut std::ffi::c_void,
272                    file_size,
273                    &mut bytes_read,
274                    std::ptr::null_mut(),
275                )
276            };
277
278            if result == 0 {
279                let error_code = unsafe { GetLastError() };
280                return Err(format!("ReadFile failed with error: {}", error_code));
281            }
282
283            buffer.truncate(bytes_read as usize);
284            info!("Successfully read {} bytes", bytes_read);
285            Ok(buffer)
286        }
287
288        #[cfg(target_os = "macos")]
289        {
290            use std::os::unix::io::FromRawFd;
291            use std::io::Read;
292
293            let fd = handle.get_handle() as i32;
294
295            if fd < 0 {
296                return Err("Invalid file descriptor".to_string());
297            }
298
299            info!("macOS: Using file descriptor: {}", fd);
300
301            // Crear un File desde el raw fd
302            let mut file = unsafe { std::fs::File::from_raw_fd(fd) };
303
304            // Seek al inicio
305            use std::io::Seek;
306            if let Err(e) = file.seek(std::io::SeekFrom::Start(0)) {
307                return Err(format!("Failed to seek to start: {}", e));
308            }
309
310            // Leer el contenido completo
311            let mut buffer = Vec::new();
312            match file.read_to_end(&mut buffer) {
313                Ok(bytes_read) => {
314                    info!("macOS: Successfully read {} bytes", bytes_read);
315
316                    // Importante: evitar que el File se cierre automáticamente
317                    std::mem::forget(file);
318
319                    Ok(buffer)
320                }
321                Err(e) => Err(format!("Failed to read from file descriptor: {}", e))
322            }
323        }
324
325        #[cfg(target_os = "linux")]
326        {
327            use std::os::unix::io::FromRawFd;
328            use std::io::Read;
329
330            let fd = handle.get_handle() as i32;
331
332            if fd < 0 {
333                return Err("Invalid file descriptor".to_string());
334            }
335
336            info!("Linux: Using file descriptor: {}", fd);
337
338            // En Linux, similar a macOS pero con algunas diferencias
339            let mut file = unsafe { std::fs::File::from_raw_fd(fd) };
340
341            // Seek al inicio
342            use std::io::Seek;
343            if let Err(e) = file.seek(std::io::SeekFrom::Start(0)) {
344                return Err(format!("Failed to seek to start: {}", e));
345            }
346
347            // Leer usando read_to_end
348            let mut buffer = Vec::new();
349            match file.read_to_end(&mut buffer) {
350                Ok(bytes_read) => {
351                    info!("Linux: Successfully read {} bytes", bytes_read);
352
353                    // Evitar que se cierre automáticamente
354                    std::mem::forget(file);
355
356                    Ok(buffer)
357                }
358                Err(e) => Err(format!("Failed to read from file descriptor: {}", e))
359            }
360        }
361
362        #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
363        {
364            // Fallback para otras plataformas
365            error!("Platform not supported for handle-based file reading");
366            Err("Platform not supported for handle-based file reading".to_string())
367        }
368    }
369    /// Tries to load existing data from the persistence file
370    async fn try_load_data(&self) -> Result<(), String> {
371        let data = self.read_file_data().await?;
372
373        if data.is_empty() {
374            info!("Persistence file is empty, starting with empty cache");
375            return Ok(());
376        }
377
378        // Try to decrypt the data (crypto::decrypt expects &Vec<u8>)
379        let decrypted_data = match crypto::decrypt(&data, PERSISTENCE_PASSWORD) {
380            Ok(decrypted) => decrypted,
381            Err(e) => {
382                error!("Failed to decrypt persistence file: {}", e);
383                info!("Starting with empty cache due to decryption failure");
384                return Ok(()); // Don't fail, just start empty
385            }
386        };
387
388        info!("Successfully decrypted persistence file");
389
390        // Try to deserialize the decrypted JSON data
391        let loaded_data = match serde_json::from_slice::<HashMap<String, Value>>(&decrypted_data) {
392            Ok(data) => data,
393            Err(e) => {
394                error!("Failed to parse decrypted data as JSON: {}", e);
395                info!("Starting with empty cache");
396                return Ok(()); // Don't fail, just start empty
397            }
398        };
399
400        // Load data into cache - now we can use await directly
401        let mut cache = self.cache.lock().await;
402        *cache = loaded_data;
403        let count = cache.len();
404        drop(cache);
405
406        info!("Successfully loaded {} keys from encrypted persistence file", count);
407        Ok(())
408    }
409
410    /// Saves the current cache to the persistence file with encryption
411    async fn save_to_file(&self) -> Result<(), String> {
412        let cache = self.cache.lock().await;
413
414        // Serialize and encrypt
415        let data_bytes = match serde_json::to_vec_pretty(&*cache) {
416            Ok(bytes) => bytes,
417            Err(e) => return Err(format!("Failed to serialize cache: {}", e)),
418        };
419
420        let encrypted_data = match crypto::encrypt(&data_bytes, PERSISTENCE_PASSWORD) {
421            Ok(encrypted) => encrypted,
422            Err(e) => return Err(format!("Failed to encrypt persistence data: {}", e)),
423        };
424
425        // Write using available handle
426        let file_handle = self.file_handle.lock().await;
427        if let Some(safe_handle) = *file_handle {
428            if safe_handle.is_valid() {
429                drop(file_handle); // Release lock before async call
430                match self.write_with_handle(&safe_handle, &encrypted_data).await {
431                    Ok(_) => {
432                        info!("Saved {} keys using {} handle",
433                          cache.len(),
434                          if self.using_service_protection { "service" } else { "direct" });
435                        return Ok(());
436                    }
437                    Err(e) => {
438                        error!("Failed to write with handle: {}", e);
439                        // Continue to fallback
440                    }
441                }
442            }
443        }
444
445        // Fallback to tokio fs (memory-only mode recovery)
446        match tokio::fs::write(&self.file_path, encrypted_data).await {
447            Ok(_) => {
448                info!("Saved {} keys using fallback write", cache.len());
449                Ok(())
450            }
451            Err(e) => Err(format!("Failed to write persistence file: {}", e)),
452        }
453    }
454
455    /// Writes data using a SafeHandle
456    /// Writes data using a SafeHandle (multiplataforma)
457    async fn write_with_handle(&self, handle: &SafeHandle, data: &[u8]) -> Result<(), String> {
458            #[cfg(target_os = "windows")]
459            {
460                use winapi::um::fileapi::{WriteFile, SetFilePointer, SetEndOfFile};
461                use winapi::um::errhandlingapi::GetLastError;
462                use winapi::um::winbase::FILE_BEGIN;
463
464                let handle_value = handle.get_handle();
465
466                info!("Windows: Writing {} bytes to handle: {:?}", data.len(), handle_value);
467
468                // Reset file pointer to beginning
469                unsafe {
470                    SetFilePointer(handle_value, 0, std::ptr::null_mut(), FILE_BEGIN);
471                }
472
473                let mut bytes_written: u32 = 0;
474                let result = unsafe {
475                    WriteFile(
476                        handle_value,
477                        data.as_ptr() as *const std::ffi::c_void,
478                        data.len() as u32,
479                        &mut bytes_written,
480                        std::ptr::null_mut(),
481                    )
482                };
483
484                if result == 0 {
485                    let error_code = unsafe { GetLastError() };
486                    return Err(format!("WriteFile failed with error: {}", error_code));
487                }
488
489                // Truncate file to the data we just wrote
490                unsafe {
491                    SetEndOfFile(handle_value);
492                }
493
494                info!("Windows: Successfully wrote {} bytes", bytes_written);
495                Ok(())
496        }
497
498        #[cfg(target_os = "macos")]
499        {
500            use std::os::unix::io::FromRawFd;
501            use std::io::{Write, Seek};
502
503            let fd = handle.get_handle() as i32;
504
505            if fd < 0 {
506                return Err("Invalid file descriptor".to_string());
507            }
508
509            info!("macOS: Writing {} bytes to fd: {}", data.len(), fd);
510
511            // Crear File desde raw fd
512            let mut file = unsafe { std::fs::File::from_raw_fd(fd) };
513
514            // Seek al inicio y truncar
515            if let Err(e) = file.seek(std::io::SeekFrom::Start(0)) {
516                return Err(format!("Failed to seek to start: {}", e));
517            }
518
519            // Truncar archivo primero
520            if let Err(e) = file.set_len(0) {
521                return Err(format!("Failed to truncate file: {}", e));
522            }
523
524            // Escribir datos
525            match file.write_all(data) {
526                Ok(_) => {
527                    // Forzar flush
528                    if let Err(e) = file.flush() {
529                        return Err(format!("Failed to flush file: {}", e));
530                    }
531
532                    info!("macOS: Successfully wrote {} bytes", data.len());
533
534                    // Evitar que se cierre automáticamente
535                    std::mem::forget(file);
536
537                    Ok(())
538                }
539                Err(e) => Err(format!("Failed to write to file descriptor: {}", e))
540            }
541        }
542
543        #[cfg(target_os = "linux")]
544        {
545            use std::os::unix::io::FromRawFd;
546            use std::io::{Write, Seek};
547
548            let fd = handle.get_handle() as i32;
549
550            if fd < 0 {
551                return Err("Invalid file descriptor".to_string());
552            }
553
554            info!("Linux: Writing {} bytes to fd: {}", data.len(), fd);
555
556            // Similar a macOS
557            let mut file = unsafe { std::fs::File::from_raw_fd(fd) };
558
559            // Seek y truncar
560            if let Err(e) = file.seek(std::io::SeekFrom::Start(0)) {
561                return Err(format!("Failed to seek to start: {}", e));
562            }
563
564            if let Err(e) = file.set_len(0) {
565                return Err(format!("Failed to truncate file: {}", e));
566            }
567
568            // Escribir
569            match file.write_all(data) {
570                Ok(_) => {
571                    if let Err(e) = file.flush() {
572                        return Err(format!("Failed to flush file: {}", e));
573                    }
574
575                    info!("Linux: Successfully wrote {} bytes", data.len());
576
577                    // No cerrar automáticamente
578                    std::mem::forget(file);
579
580                    Ok(())
581                }
582                Err(e) => Err(format!("Failed to write to file descriptor: {}", e))
583            }
584        }
585
586        #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
587        {
588            error!("Platform not supported for handle-based file writing");
589            Err("Platform not supported for handle-based file writing".to_string())
590        }
591    }
592
593    /// Gets a value by key
594    async fn get_value(&self, key: &str) -> Option<Value> {
595        let cache = self.cache.lock().await;
596        cache.get(key).cloned()
597    }
598
599    /// Sets a value for a key
600    pub async fn set_value(&self, key: String, value: Value) -> Result<(), String> {
601        {
602            let mut cache = self.cache.lock().await;
603            cache.insert(key.clone(), value);
604        }
605
606        // Save to file after updating cache
607        match self.save_to_file().await {
608            Ok(_) => {
609                info!("Set value for key: {}", key);
610                Ok(())
611            }
612            Err(e) => Err(e),
613        }
614    }
615
616    /// Deletes a value by key
617    pub async fn delete_value(&self, key: &str) -> Result<bool, String> {
618        let removed = {
619            let mut cache = self.cache.lock().await;
620            cache.remove(key).is_some()
621        };
622
623        if removed {
624            // Save to file after deletion
625            match self.save_to_file().await {
626                Ok(_) => {
627                    info!("Deleted value for key: {}", key);
628                    Ok(true)
629                }
630                Err(e) => Err(e),
631            }
632        } else {
633            info!("Key not found for deletion: {}", key);
634            Ok(false)
635        }
636    }
637
638    /// Closes the handle with service.exe if we have one
639    async fn close_handle_with_service(&self) -> Result<(), String> {
640        let service_handle = self.file_handle.lock().await;
641        if service_handle.is_none() {
642            info!("No service handle to close");
643            return Ok(());
644        }
645        drop(service_handle); // Release lock
646
647        info!("Closing handle with service.exe for: {}", self.file_path);
648
649        let mut stream = match TcpStream::connect(sharing::CHANNEL_NAME) {
650            Ok(stream) => stream,
651            Err(e) => return Err(format!("Could not connect to service.exe for CLOSE_HANDLE: {}", e)),
652        };
653
654        // Usar el enum Action existente
655        let action = Action::CloseHandle(self.file_path.clone());
656        match stream.write_all(action.to_string().as_bytes()) {
657            Ok(_) => {},
658            Err(e) => return Err(format!("Failed to send CLOSE_HANDLE request: {}", e)),
659        }
660
661        // Read response
662        let mut buffer = [0; 1024];
663        let bytes_read = match stream.read(&mut buffer) {
664            Ok(bytes) => bytes,
665            Err(e) => return Err(format!("Failed to read CLOSE_HANDLE response: {}", e)),
666        };
667
668        let response = String::from_utf8_lossy(&buffer[..bytes_read]);
669        info!("CLOSE_HANDLE response: {}", response);
670        Ok(())
671    }
672
673    /// Processes a persistence action from WebSocket message
674    async fn process_action(&self, action: Value, _write: WebSocketWrite) -> (i32, String) {
675        // Extraer comando, key y value del ACTION object
676        let action_obj = match action.get("ACTION").and_then(|a| a.as_object()) {
677            Some(obj) => obj,
678            None => {
679                error!("Missing or invalid ACTION object");
680                return (1, "Missing ACTION object".to_string());
681            }
682        };
683
684        let command = action_obj.get("command").and_then(|c| c.as_str()).unwrap_or("UNKNOWN");
685        let key = action_obj.get("key").and_then(|k| k.as_str()).unwrap_or("");
686        let value = action_obj.get("value");
687
688        info!("Processing persistence command: {} for key: {}", command, key);
689
690        match command.to_uppercase().as_str() {
691            "GET" => {
692                if key.is_empty() {
693                    error!("Missing key parameter for GET command");
694                    return (1, "Missing key parameter".to_string());
695                }
696
697                match self.get_value(key).await {
698                    Some(value) => {
699                        info!("Retrieved value for key: {}", key);
700                        (0, serde_json::to_string(&value).unwrap_or("null".to_string()))
701                    }
702                    None => {
703                        info!("Key not found: {}", key);
704                        (0, "Key not found".to_string())
705                    }
706                }
707            }
708            "SET" => {
709                if key.is_empty() {
710                    error!("Missing key parameter for SET command");
711                    return (1, "Missing key parameter".to_string());
712                }
713
714                let value = match value {
715                    Some(v) => v.clone(),
716                    None => {
717                        error!("Missing value parameter for SET command");
718                        return (1, "Missing value parameter".to_string());
719                    }
720                };
721
722                match self.set_value(key.to_string(), value.clone()).await {
723                    Ok(_) => {
724                        info!("Set value for key: {}", key);
725                        (0, format!("Value set successfully, size of value: {}", value.to_string().len()))
726                    }
727                    Err(e) => {
728                        error!("Failed to set value: {}", e);
729                        (1, format!("Failed to set value: {}", e))
730                    }
731                }
732            }
733            "DEL" => {
734                if key.is_empty() {
735                    error!("Missing key parameter for DELETE command");
736                    return (1, "Missing key parameter".to_string());
737                }
738
739                match self.delete_value(key).await {
740                    Ok(was_deleted) => {
741                        if was_deleted {
742                            info!("Deleted key: {}", key);
743                            (0, "Key deleted successfully".to_string())
744                        } else {
745                            info!("Key not found for deletion: {}", key);
746                            (0, "Key not found".to_string())
747                        }
748                    }
749                    Err(e) => {
750                        error!("Failed to delete value: {}", e);
751                        (1, format!("Failed to delete value: {}", e))
752                    }
753                }
754            }
755            _ => {
756                error!("Unknown persistence command: {}", command);
757                (1, "Unknown command".to_string())
758            }
759        }
760    }
761}
762
763#[async_trait]
764impl Service for PersistenceService {
765    /// Executes a persistence service action based on the provided JSON input.
766    async fn run(&self, action: Value, write: WebSocketWrite) -> (i32, String) {
767        debug!("PersistenceService: Running action: {:?}", action);
768        self.process_action(action, write).await
769    }
770
771    /// Converts the service instance into a `dyn Any` reference.
772    fn as_any(&self) -> &dyn std::any::Any {
773        self
774    }
775
776    /// Stops the persistence service and performs cleanup.
777    fn stop_service(&self) {
778        info!("PersistenceService: Stopping service");
779
780        // Close handle with service.exe if we have one
781        let rt = tokio::runtime::Runtime::new().unwrap();
782        rt.block_on(async {
783            if let Err(e) = self.close_handle_with_service().await {
784                error!("Failed to close handle with service: {}", e);
785            }
786        });
787
788        info!("PersistenceService stopped");
789    }
790
791    /// Returns the version of the PersistenceService module.
792    fn get_version(&self) -> String {
793        PERSISTENCE_VERSION.to_string()
794    }
795}