sdk_relay/IMPROVEMENTS.md
4NK Dev b6f09c952b
All checks were successful
build-and-push-ext / build_push (push) Successful in 8s
ci: docker_tag=ext - Update Dockerfile to use dev4 branch for sdk_common
2025-09-21 08:23:07 +00:00

173 lines
5.4 KiB
Markdown

# Améliorations de la séquence de démarrage de sdk_relay
## Problème actuel
- Le serveur WebSocket ne démarre qu'après le scan complet des blocs
- Les services dépendants (ihm_client, etc.) ne peuvent pas se connecter pendant le scan
- Le scan peut prendre plusieurs minutes et bloquer complètement le service
## Solutions proposées
### 1. Démarrage immédiat des serveurs (Recommandé)
```rust
// Dans main.rs, démarrer les serveurs AVANT le scan
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// ... configuration ...
// DÉMARRER LES SERVEURS IMMÉDIATEMENT
let try_socket = TcpListener::bind(config.ws_url).await?;
let listener = try_socket;
// Démarrer le serveur de santé immédiatement
tokio::spawn(start_health_server(8091));
// Démarrer le serveur WebSocket dans une tâche séparée
let ws_handle = tokio::spawn(async move {
while let Ok((stream, addr)) = listener.accept().await {
tokio::spawn(handle_connection(stream, addr, our_sp_address));
}
});
// FAIRE LE SCAN EN ARRIÈRE-PLAN
tokio::spawn(async move {
if let Err(e) = scan_blocks(current_tip - last_scan, &config.blindbit_url).await {
eprintln!("Scan error: {}", e);
}
});
// Attendre que le serveur WebSocket soit prêt
ws_handle.await?;
Ok(())
}
```
### 2. Mode "dégradé" pendant le scan
```rust
// Ajouter un état de service
enum ServiceState {
Starting,
Scanning,
Ready,
Error,
}
// Le serveur WebSocket accepte les connexions mais répond avec un état
async fn handle_connection(stream: TcpStream, addr: SocketAddr, state: Arc<Mutex<ServiceState>>) {
let current_state = state.lock().await;
match *current_state {
ServiceState::Scanning => {
// Répondre avec un message indiquant que le service est en cours de scan
send_message(stream, json!({
"status": "scanning",
"message": "Service is scanning blocks, please wait..."
})).await;
},
ServiceState::Ready => {
// Traitement normal des messages
handle_normal_connection(stream).await;
},
_ => {
// Répondre avec une erreur
send_error(stream, "Service not ready").await;
}
}
}
```
### 3. Scan incrémental en arrière-plan
```rust
// Modifier le scan pour qu'il soit non-bloquant
async fn start_background_scan(start_block: u32, end_block: u32, blindbit_url: &str) {
let mut current = start_block;
while current <= end_block {
match scan_single_block(current, blindbit_url).await {
Ok(_) => {
current += 1;
// Mettre à jour le last_scan dans le wallet
update_last_scan(current).await;
},
Err(e) => {
eprintln!("Error scanning block {}: {}", current, e);
// Attendre un peu avant de réessayer
tokio::time::sleep(Duration::from_secs(5)).await;
}
}
}
}
```
### 4. Healthcheck amélioré
```rust
async fn start_health_server(port: u16) {
let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await.unwrap();
while let Ok((stream, _)) = listener.accept().await {
tokio::spawn(async move {
let response = match get_service_state().await {
ServiceState::Ready => json!({"status": "ok", "scan_complete": true}),
ServiceState::Scanning => json!({"status": "ok", "scan_complete": false, "message": "Scanning in progress"}),
ServiceState::Starting => json!({"status": "starting", "scan_complete": false}),
ServiceState::Error => json!({"status": "error", "scan_complete": false}),
};
let response_str = response.to_string();
let http_response = format!(
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\nContent-Type: application/json\r\n\r\n{}",
response_str.len(),
response_str
);
let _ = stream.write_all(http_response.as_bytes()).await;
});
}
}
```
## Implémentation recommandée
### Étape 1 : Modifier main.rs
1. Démarrer les serveurs WebSocket et de santé immédiatement
2. Faire le scan en arrière-plan dans une tâche séparée
3. Ajouter un état de service partagé
### Étape 2 : Modifier le healthcheck
1. Retourner l'état du scan dans la réponse
2. Permettre aux services de savoir si le scan est terminé
### Étape 3 : Modifier docker-compose.yml
```yaml
sdk_relay:
# ... configuration existante ...
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8091/"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s # Donner plus de temps pour le démarrage initial
```
### Étape 4 : Modifier les services dépendants
```yaml
ihm_client:
depends_on:
sdk_relay:
condition: service_healthy
# Ajouter une vérification de l'état du scan
environment:
- SDK_RELAY_SCAN_TIMEOUT=300 # 5 minutes max d'attente
```
## Avantages
- ✅ Services disponibles immédiatement
- ✅ Scan non-bloquant
- ✅ Meilleure expérience utilisateur
- ✅ Monitoring de l'état du scan
- ✅ Récupération d'erreur améliorée
## Migration
1. Implémenter les changements dans sdk_relay
2. Tester avec un scan réduit
3. Déployer en production
4. Surveiller les logs et métriques