- Archiver 131 .md dans docs/archive/root-md/ - Archiver 22 .json dans docs/archive/root-json/ - Conserver 7 .md utiles (README, CONTRIBUTING, CHANGELOG, etc.) - Conserver package.json, package-lock.json, turbo.json - Ajouter README d'index dans chaque archive
29 KiB
Migration Chat-Server Rust : i64 → UUID — Rapport complet
Date : 2025-01-27
Service : veza-chat-server (Rust/Axum)
Objectif : Migrer tous les IDs de i64 vers Uuid pour cohérence avec le schéma DB et le backend Go
Résumé exécutif
- Fichiers à modifier : ~25 fichiers
- Structs à migrer : 8 structures principales
- Requêtes SQL à mettre à jour : ~50+ requêtes SQLx
- Messages WebSocket à migrer : 5+ types de messages
- Estimation temps : 4-6 heures
- Risque : Moyen (nécessite tests exhaustifs)
État actuel :
- ✅ Schéma DB : Utilise
UUID(colonnesuuid) mais aussiBIGSERIAL(colonnesid) - ❌ Code Rust : Utilise
i64pour la plupart des IDs - ✅ Frontend : Envoie déjà des UUID strings
- ⚠️ Backend Go : Mixte (certains handlers utilisent encore
int64)
Problème identifié : Le schéma DB a une cohabitation BIGSERIAL/UUID :
- Colonnes
id:BIGSERIAL(i64) - Colonnes
uuid:UUID(Uuid) - Le code Rust utilise les colonnes
id(i64) alors qu'il devrait utiliseruuid
1. Cartographie complète
1.1 Structures avec IDs à migrer
| Struct | Fichier | Champs i64 | Champs déjà Uuid | Action | Priorité |
|---|---|---|---|---|---|
Room |
src/hub/channels.rs |
id: i64, owner_id: i64 |
uuid: Uuid |
Supprimer id, renommer uuid→id, migrer owner_id |
🔴 Haute |
RoomMember |
src/hub/channels.rs |
id: i64, conversation_id: i64, user_id: i64 |
- | Migrer tous vers Uuid |
🔴 Haute |
RoomMessage |
src/hub/channels.rs |
id: i64, author_id: i64, conversation_id: i64, parent_message_id: Option<i64> |
uuid: Uuid |
Supprimer id, renommer uuid→id, migrer autres |
🔴 Haute |
RoomStats |
src/hub/channels.rs |
room_id: i64 |
- | Migrer vers Uuid |
🟡 Moyenne |
EnhancedRoomMessage |
src/hub/channels.rs |
id: i64, author_id: i32, room_id: Option<i32> |
- | Migrer vers Uuid |
🟡 Moyenne |
AuditLog |
src/hub/audit.rs |
id: i64, user_id: Option<i64> |
- | Migrer vers Uuid |
🟡 Moyenne |
SecurityEvent |
src/hub/audit.rs |
id: i64, user_id: Option<i64> |
- | Migrer vers Uuid |
🟡 Moyenne |
UserActivity |
src/hub/audit.rs |
user_id: i64 |
- | Migrer vers Uuid |
🟡 Moyenne |
RoomAuditSummary |
src/hub/audit.rs |
room_id: i64 |
- | Migrer vers Uuid |
🟡 Moyenne |
Message |
src/models/message.rs |
- | id: Uuid, conversation_id: Uuid, sender_id: Uuid |
✅ Déjà migré | ✅ OK |
WsInbound |
src/messages.rs |
to_user_id: i32, with: i32 |
- | Migrer vers Uuid (string) |
🔴 Haute |
Total : 10 structures à migrer (8 avec i64, 2 déjà OK)
1.2 Requêtes SQLx à mettre à jour
Fichier : src/hub/channels.rs
| Fonction | Ligne | Requête | Champs i64 concernés | Modification |
|---|---|---|---|---|
create_room |
139-152 | INSERT INTO conversations ... RETURNING id, uuid, ... |
id, owner_id |
Utiliser uuid au lieu de id, migrer owner_id |
join_room |
198-220 | SELECT id, uuid, ... FROM conversations WHERE id = $1 |
room_id, user_id |
Utiliser uuid au lieu de id |
leave_room |
254-290 | SELECT id, ... FROM conversations WHERE id = $1 |
room_id, user_id |
Utiliser uuid |
send_room_message |
347-412 | INSERT INTO messages ... RETURNING id |
room_id, author_id, message_id, parent_message_id |
Utiliser uuid pour tous |
pin_message |
416-450 | UPDATE messages ... WHERE id = $2 |
room_id, message_id, user_id |
Utiliser uuid |
fetch_room_history |
462-546 | SELECT id, uuid, ... FROM messages WHERE conversation_id = $1 |
room_id, user_id, message_id |
Utiliser uuid |
fetch_pinned_messages |
548-593 | SELECT ... FROM messages WHERE conversation_id = $1 |
room_id, user_id |
Utiliser uuid |
get_room_stats |
594-623 | SELECT c.id as room_id, ... |
room_id |
Utiliser uuid |
list_room_members |
625-670 | SELECT ... FROM conversation_members WHERE conversation_id = $1 |
room_id, user_id |
Utiliser uuid |
Total dans channels.rs : ~20 requêtes à modifier
Fichier : src/hub/audit.rs
| Fonction | Ligne | Requête | Champs i64 concernés | Modification |
|---|---|---|---|---|
log_action |
81-100 | INSERT INTO audit_logs ... RETURNING id |
user_id: Option<i64> |
Migrer vers Option<Uuid> |
log_security_event |
112-137 | INSERT INTO security_events ... RETURNING id |
user_id: Option<i64> |
Migrer vers Option<Uuid> |
log_room_created |
150-173 | log_action(..., room_id: i64, owner_id: i64) |
room_id, owner_id |
Migrer vers Uuid |
log_member_change |
174-207 | log_action(..., room_id: i64, target_user_id: i64, ...) |
room_id, user_ids |
Migrer vers Uuid |
log_message_modified |
207-244 | log_action(..., message_id: i64, room_id: i64, ...) |
Tous les IDs | Migrer vers Uuid |
log_moderation_action |
244-297 | log_action(..., room_id: i64, ...) |
Tous les IDs | Migrer vers Uuid |
get_room_audit_logs |
297-346 | SELECT ... FROM audit_logs WHERE ... |
room_id, requesting_user_id |
Migrer vers Uuid |
get_room_security_events |
347-398 | SELECT ... FROM security_events WHERE ... |
room_id, requesting_user_id |
Migrer vers Uuid |
generate_room_activity_report |
399-515 | SELECT ... WHERE room_id = $1 |
room_id, requesting_user_id |
Migrer vers Uuid |
get_room_audit_summary |
516-551 | SELECT c.id as room_id, ... |
room_id, requesting_user_id |
Migrer vers Uuid |
detect_suspicious_patterns |
552-590 | SELECT ... WHERE room_id = $1 |
room_id |
Migrer vers Uuid |
Total dans audit.rs : ~15 requêtes à modifier
Autres fichiers
| Fichier | Fonctions impactées | Requêtes | Priorité |
|---|---|---|---|
src/hub/direct_messages.rs |
Toutes fonctions DM | ~10 requêtes | 🔴 Haute |
src/repository/room_repository.rs |
Toutes méthodes | ~8 requêtes | 🔴 Haute |
src/repository/message_repository.rs |
Toutes méthodes | ~8 requêtes | 🔴 Haute |
src/message_store.rs |
Store/retrieve | ~5 requêtes | 🟡 Moyenne |
src/services/room_service.rs |
Service layer | ~5 requêtes | 🟡 Moyenne |
Total estimé : ~60 requêtes SQLx à modifier
1.3 Conversions/parsing d'ID à migrer
| Fichier | Ligne | Code actuel | Code cible | Contexte |
|---|---|---|---|---|
src/messages.rs |
21 | to_user_id: i32 |
to_user_id: String (UUID string) |
WebSocket inbound |
src/messages.rs |
33 | with: i32 |
with: String (UUID string) |
WebSocket inbound |
src/hub/channels.rs |
122 | owner_id: i64 |
owner_id: Uuid |
Paramètre fonction |
src/hub/channels.rs |
189 | room_id: i64, user_id: i64 |
room_id: Uuid, user_id: Uuid |
Paramètres fonction |
src/hub/channels.rs |
326 | author_id: i64 |
author_id: Uuid |
Paramètre fonction |
src/hub/channels.rs |
339 | author_id as i32 |
Supprimer conversion | Rate limiting |
src/hub/channels.rs |
383 | message.get("id") → i64 |
message.get("uuid") → Uuid |
Récupération ID |
src/hub/audit.rs |
81 | user_id: Option<i64> |
user_id: Option<Uuid> |
Paramètre fonction |
src/hub/audit.rs |
150 | room_id: i64, owner_id: i64 |
room_id: Uuid, owner_id: Uuid |
Paramètres fonction |
Patterns de conversion à chercher :
as i64/as i32: Conversions explicites.parse::<i64>(): Parsing depuis stringget::<i64, _>("id"): Récupération depuis SQLx Rowvalidate_user_id(user_id as i32): Validation avec conversion
1.4 Messages/DTOs WebSocket à migrer
| Struct | Fichier | Champs i64 | Sérialisé en JSON | Impact client | Action |
|---|---|---|---|---|---|
WsInbound::DirectMessage |
src/messages.rs |
to_user_id: i32 |
Oui | ❌ Frontend envoie UUID string | Migrer vers String (UUID) |
WsInbound::DmHistory |
src/messages.rs |
with: i32 |
Oui | ❌ Frontend envoie UUID string | Migrer vers String (UUID) |
RoomMessage |
src/hub/channels.rs |
id: i64, author_id: i64, conversation_id: i64 |
Oui | ⚠️ Frontend attend UUID string | Migrer vers Uuid (sérialisé en string) |
Room |
src/hub/channels.rs |
id: i64, owner_id: i64 |
Oui | ⚠️ Frontend attend UUID string | Migrer vers Uuid |
RoomMember |
src/hub/channels.rs |
id: i64, user_id: i64 |
Oui | ⚠️ Frontend attend UUID string | Migrer vers Uuid |
Note importante : Le frontend envoie déjà des UUID strings (voir apps/web/src/features/chat/types/index.ts). Le problème est que le Rust attend des i32/i64.
1.5 Schéma DB (source de vérité)
Analyse du schéma : migrations/001_create_clean_database.sql
| Table | Colonne ID | Type DB | Colonne UUID | Type DB | Type Rust actuel | Conforme | Action |
|---|---|---|---|---|---|---|---|
users |
id |
BIGSERIAL |
uuid |
UUID |
i64 |
❌ | Utiliser uuid |
conversations |
id |
BIGSERIAL |
uuid |
UUID |
i64 |
❌ | Utiliser uuid |
conversation_members |
id |
BIGSERIAL |
- | - | i64 |
❌ | PROBLÈME : Pas de colonne UUID |
messages |
id |
BIGSERIAL |
uuid |
UUID |
i64 |
❌ | Utiliser uuid |
audit_logs |
id |
BIGSERIAL |
- | - | i64 |
❌ | PROBLÈME : Pas de colonne UUID |
security_events |
id |
BIGSERIAL |
- | - | i64 |
❌ | PROBLÈME : Pas de colonne UUID |
Problème majeur identifié :
- Les tables
conversation_members,audit_logs,security_eventsn'ont PAS de colonne UUID - Elles utilisent uniquement
BIGSERIALpour les IDs - Solution : Soit ajouter des colonnes UUID (migration DB), soit utiliser les IDs BIGSERIAL mais les convertir en UUID côté application
Recommandation : Utiliser les colonnes uuid existantes et ajouter des migrations pour les tables sans UUID.
2. Impacts et dépendances
2.1 Communication avec le backend Go
| Direction | Endpoint/Event | Format ID actuel (Rust) | Format attendu (Go) | Action |
|---|---|---|---|---|
| Go → Rust | WebSocket token (JWT) | user_id dans JWT : int64 |
user_id : uuid.UUID |
⚠️ PROBLÈME : JWT contient int64 |
| Go → Rust | HTTP webhook (si existe) | user_id: i64 |
user_id: string (UUID) |
Vérifier si webhooks existent |
| Rust → Go | Webhook callback (si existe) | user_id: i64 |
user_id: string (UUID) |
Migrer vers UUID |
Problème identifié : Le backend Go génère des tokens JWT avec user_id en uuid.UUID, mais le chat-server Rust pourrait s'attendre à un int64. À vérifier dans src/auth.rs et src/jwt_manager.rs.
2.2 Communication avec le Frontend
| Message WS | Direction | Champ | Type actuel (Rust) | Type Frontend | Compatible | Action |
|---|---|---|---|---|---|---|
NewMessage |
Server→Client | message_id |
i64 (number) |
string (UUID) |
❌ | Migrer vers Uuid (sérialisé en string) |
NewMessage |
Server→Client | sender_id |
i64 (number) |
string (UUID) |
❌ | Migrer vers Uuid |
NewMessage |
Server→Client | conversation_id |
i64 (number) |
string (UUID) |
❌ | Migrer vers Uuid |
join_room |
Client→Server | room |
String (nom) |
string (nom ou UUID) |
✅ | OK (utilise nom, pas ID) |
direct_message |
Client→Server | to_user_id |
i32 (number) |
string (UUID) |
❌ | Migrer vers String (UUID) |
dm_history |
Client→Server | with |
i32 (number) |
string (UUID) |
❌ | Migrer vers String (UUID) |
Résultat : ❌ Incompatible - Le frontend envoie/reçoit des UUID strings, mais le Rust attend/envoie des i64.
2.3 Tests existants
| Fichier test | Test | Utilise i64 | Modification |
|---|---|---|---|
src/hub/channels.rs (tests inline) |
test_room_creation |
Probable | Changer en Uuid::new_v4() |
tests/integration_test.rs (si existe) |
Tests d'intégration | Probable | Migrer vers UUID |
| Tests unitaires | Tous | Probable | Migrer vers UUID |
Action : Vérifier avec grep -r "#\[test\]" veza-chat-server/src/ et mettre à jour tous les tests.
3. Plan de migration détaillé
3.1 Ordre des modifications (bottom-up)
Étape 1 : Préparation (sans changement fonctionnel)
- Vérifier
Cargo.toml:uuidavec features["v4", "serde"]✅ (déjà présent) - Vérifier
Cargo.toml:sqlxavec featureuuid✅ (déjà présent) - Créer branche :
git checkout -b fix/chat-server-uuid-migration - Tag de sauvegarde :
git tag pre-uuid-migration-chat-server
Étape 2 : Migration des structs (du plus simple au plus complexe)
Ordre recommandé :
src/models/message.rs- ✅ Déjà migré, vérifier seulementsrc/messages.rs- MigrerWsInbound(simple, pas de DB)src/hub/channels.rs- MigrerRoom,RoomMember,RoomMessage(complexe)src/hub/audit.rs- Migrer structs d'audit- Autres structs dans autres fichiers
Étape 3 : Migration des requêtes SQLx
Ordre recommandé :
src/hub/channels.rs- Toutes les requêtes (fonctions principales)src/hub/audit.rs- Toutes les requêtes d'auditsrc/hub/direct_messages.rs- Requêtes DMsrc/repository/*.rs- Repositories- Autres fichiers avec requêtes SQL
Étape 4 : Migration handlers/WebSocket
src/websocket/handler.rs- Handlers WebSocketsrc/websocket/broadcast.rs- Broadcast messagessrc/message_handler.rs- Message handlers- Autres handlers
Étape 5 : Tests
- Mettre à jour tous les tests unitaires
- Mettre à jour les tests d'intégration
- Ajouter des tests de conversion UUID
3.2 Modifications fichier par fichier
Fichier : src/messages.rs
Modification : Migrer WsInbound pour accepter des UUID strings
// AVANT
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum WsInbound {
#[serde(rename = "direct_message")]
DirectMessage {
to_user_id: i32, // ❌
content: String,
},
#[serde(rename = "dm_history")]
DmHistory {
with: i32, // ❌
limit: i64,
}
}
// APRÈS
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
pub enum WsInbound {
#[serde(rename = "direct_message")]
DirectMessage {
to_user_id: String, // ✅ UUID string depuis frontend
content: String,
},
#[serde(rename = "dm_history")]
DmHistory {
with: String, // ✅ UUID string depuis frontend
limit: i64,
}
}
Fonctions impactées : Aucune (juste parsing)
Fichier : src/hub/channels.rs
Modification 1 : Struct Room
// AVANT
#[derive(Debug, FromRow, Serialize, Deserialize)]
pub struct Room {
pub id: i64, // ❌
pub uuid: Uuid, // ✅ Existe déjà
pub name: String,
pub description: Option<String>,
pub owner_id: i64, // ❌
pub is_public: bool,
pub is_archived: bool,
pub max_members: Option<i32>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
// APRÈS
#[derive(Debug, FromRow, Serialize, Deserialize)]
pub struct Room {
pub id: Uuid, // ✅ Renommé depuis uuid
pub name: String,
pub description: Option<String>,
pub owner_id: Uuid, // ✅ Migré
pub is_public: bool,
pub is_archived: bool,
pub max_members: Option<i32>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
Modification 2 : Struct RoomMember
// AVANT
#[derive(Debug, FromRow, Serialize, Deserialize)]
pub struct RoomMember {
pub id: i64, // ❌
pub conversation_id: i64, // ❌
pub user_id: i64, // ❌
pub role: String,
pub joined_at: DateTime<Utc>,
pub left_at: Option<DateTime<Utc>>,
pub is_muted: bool,
}
// APRÈS
#[derive(Debug, FromRow, Serialize, Deserialize)]
pub struct RoomMember {
pub id: Uuid, // ✅
pub conversation_id: Uuid, // ✅
pub user_id: Uuid, // ✅
pub role: String,
pub joined_at: DateTime<Utc>,
pub left_at: Option<DateTime<Utc>>,
pub is_muted: bool,
}
Modification 3 : Struct RoomMessage
// AVANT
#[derive(Debug, FromRow, Serialize)]
pub struct RoomMessage {
pub id: i64, // ❌
pub uuid: Uuid, // ✅ Existe déjà
pub author_id: i64, // ❌
pub author_username: String,
pub conversation_id: i64, // ❌
pub content: String,
pub parent_message_id: Option<i64>, // ❌
// ...
}
// APRÈS
#[derive(Debug, FromRow, Serialize)]
pub struct RoomMessage {
pub id: Uuid, // ✅ Renommé depuis uuid
pub author_id: Uuid, // ✅
pub author_username: String,
pub conversation_id: Uuid, // ✅
pub content: String,
pub parent_message_id: Option<Uuid>, // ✅
// ...
}
Modification 4 : Fonction create_room
// AVANT
pub async fn create_room(
hub: &ChatHub,
owner_id: i64, // ❌
name: &str,
// ...
) -> Result<Room> {
let room_uuid = Uuid::new_v4();
let conversation = query_as::<_, Room>("
INSERT INTO conversations (uuid, type, name, description, owner_id, is_public, max_members)
VALUES ($1, 'public_room', $2, $3, $4, $5, $6)
RETURNING id, uuid, name, description, owner_id, is_public, is_archived, max_members, created_at, updated_at
")
.bind(room_uuid)
.bind(owner_id) // ❌ i64
// ...
}
// APRÈS
pub async fn create_room(
hub: &ChatHub,
owner_id: Uuid, // ✅
name: &str,
// ...
) -> Result<Room> {
let room_uuid = Uuid::new_v4();
let conversation = query_as::<_, Room>("
INSERT INTO conversations (uuid, type, name, description, owner_id, is_public, max_members)
VALUES ($1, 'public_room', $2, $3, $4, $5, $6)
RETURNING uuid as id, name, description, owner_id, is_public, is_archived, max_members, created_at, updated_at
")
.bind(room_uuid)
.bind(owner_id) // ✅ Uuid
// ...
}
Note : La requête SQL doit utiliser uuid as id pour mapper la colonne uuid vers le champ id de la struct.
Modification 5 : Fonction send_room_message
// AVANT
pub async fn send_room_message(
hub: &ChatHub,
room_id: i64, // ❌
author_id: i64, // ❌
username: &str,
content: &str,
parent_message_id: Option<i64>, // ❌
metadata: Option<Value>
) -> Result<i64> { // ❌ Retourne i64
// ...
let message = query("
INSERT INTO messages (uuid, author_id, conversation_id, content, parent_message_id, metadata, status)
VALUES ($1, $2, $3, $4, $5, $6, 'sent')
RETURNING id, created_at
")
.bind(message_uuid)
.bind(author_id) // ❌ i64
.bind(room_id) // ❌ i64
.bind(parent_message_id) // ❌ Option<i64>
// ...
let message_id: i64 = message.get("id"); // ❌
// ...
Ok(message_id) // ❌
}
// APRÈS
pub async fn send_room_message(
hub: &ChatHub,
room_id: Uuid, // ✅
author_id: Uuid, // ✅
username: &str,
content: &str,
parent_message_id: Option<Uuid>, // ✅
metadata: Option<Value>
) -> Result<Uuid> { // ✅ Retourne Uuid
// ...
let message = query("
INSERT INTO messages (uuid, author_id, conversation_id, content, parent_message_id, metadata, status)
VALUES ($1, $2, $3, $4, $5, $6, 'sent')
RETURNING uuid as id, created_at
")
.bind(message_uuid)
.bind(author_id) // ✅ Uuid
.bind(room_id) // ✅ Uuid
.bind(parent_message_id) // ✅ Option<Uuid>
// ...
let message_id: Uuid = message.get("id"); // ✅ (depuis uuid as id)
// ...
Ok(message_id) // ✅
}
Toutes les autres fonctions : Même pattern - remplacer i64 par Uuid dans les paramètres et utiliser uuid as id dans les requêtes SQL.
Fichier : src/hub/audit.rs
Modification : Toutes les fonctions utilisent i64 pour les IDs. Migrer vers Uuid.
// AVANT
pub async fn log_action(
hub: &ChatHub,
action: &str,
details: Value,
user_id: Option<i64>, // ❌
// ...
) -> Result<i64> { // ❌
// ...
}
// APRÈS
pub async fn log_action(
hub: &ChatHub,
action: &str,
details: Value,
user_id: Option<Uuid>, // ✅
// ...
) -> Result<Uuid> { // ✅
// ...
}
Note : Les tables audit_logs et security_events n'ont pas de colonne uuid. Deux options :
- Option A (recommandée) : Ajouter une migration DB pour ajouter des colonnes
uuid - Option B : Garder
BIGSERIALpour ces tables (moins idéal)
3.3 Gestion de la sérialisation JSON
Configuration Serde : Avec uuid = { version = "1.6", features = ["v4", "serde"] }, les Uuid se sérialisent automatiquement en strings.
Vérification : Le JSON produit sera :
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "General"
}
Pas besoin de configuration spéciale - Serde gère automatiquement.
3.4 Gestion des requêtes SQLx
Pattern de migration :
// AVANT (i64)
let room = query_as::<_, Room>("
SELECT id, uuid, name, description, owner_id, is_public, is_archived, max_members, created_at, updated_at
FROM conversations
WHERE id = $1
")
.bind(room_id) // i64
.fetch_one(&pool)
.await?;
// APRÈS (Uuid)
let room = query_as::<_, Room>("
SELECT uuid as id, name, description, owner_id, is_public, is_archived, max_members, created_at, updated_at
FROM conversations
WHERE uuid = $1
")
.bind(room_id) // Uuid
.fetch_one(&pool)
.await?;
Points d'attention :
- Utiliser
uuid as iddans les SELECT pour mapper vers le champidde la struct - Utiliser
WHERE uuid = $1au lieu deWHERE id = $1 - Les paramètres
$1, $2, ...doivent être de typeUuid - SQLx vérifie les types au compile-time - les erreurs seront explicites
4. Gestion des erreurs et rollback
4.1 Points de rollback
Stratégie de commits :
Commit 1 : Préparation
git commit -m "chore(chat-server): prepare UUID migration dependencies"
- Vérifier/ajouter dépendances Cargo.toml ✅ (déjà présentes)
- Créer types/ids.rs si nécessaire (optionnel)
Commit 2 : Migration des structs
git commit -m "refactor(chat-server): migrate structs from i64 to Uuid"
- Modifier toutes les structs
- Le code NE COMPILE PAS encore (c'est normal)
Commit 3 : Migration des requêtes DB
git commit -m "refactor(chat-server): migrate SQLx queries to Uuid"
- Modifier toutes les requêtes SQLx
- Le code devrait compiler maintenant
Commit 4 : Migration handlers/WebSocket
git commit -m "refactor(chat-server): migrate handlers and WS to Uuid"
- Modifier les handlers
- Modifier les messages WS
Commit 5 : Tests
git commit -m "test(chat-server): update tests for UUID migration"
- Mettre à jour tous les tests
- Tous les tests passent
Tag final
git tag chat-server-uuid-migration-complete
4.2 Erreurs attendues et solutions
Erreur 1 : Type mismatch dans query_as!
error: type mismatch: expected `i64`, found `Uuid`
Solution : Vérifier que la struct ET la requête utilisent le même type. Utiliser uuid as id dans le SELECT.
Erreur 2 : Cannot convert i64 to Uuid
error: the trait `From<i64>` is not implemented for `Uuid`
Solution : Il reste du code qui utilise i64 — chercher avec grep -r "i64" src/ | grep -v test
Erreur 3 : Serde désérialisation échoue
error: invalid type: integer, expected a string
Solution : Le client envoie un number au lieu d'un string UUID. Vérifier le frontend ou accepter les deux formats temporairement.
Erreur 4 : SQLx compile-time check échoue
error: column "id" is of type uuid but expression is of type bigint
Solution : La requête SQL utilise encore un paramètre i64. Migrer vers Uuid.
5. Validation et tests
5.1 Tests de non-régression
Tests unitaires Rust
cd veza-chat-server
cargo test
Test d'intégration DB
# Vérifier que les requêtes fonctionnent avec la vraie DB
DATABASE_URL="postgres://..." cargo test --features integration
Test WebSocket manuel
# Avec websocat ou wscat
wscat -c ws://localhost:8080/ws
# Envoyer un message avec UUID
{"type": "join_room", "room": "general"}
{"type": "direct_message", "to_user_id": "550e8400-e29b-41d4-a716-446655440000", "content": "test"}
# Vérifier la réponse (doit contenir des UUID strings, pas des numbers)
Test intégration Backend Go ↔ Chat Server
# Depuis le backend Go, obtenir un token
curl -X GET http://localhost:8080/api/v1/chat/token \
-H "Authorization: Bearer <jwt_token>"
# Vérifier que le token contient un UUID (pas un int64)
Test Frontend
- Ouvrir l'app web
- Rejoindre un chat room
- Envoyer un message
- Vérifier dans la console réseau que les IDs sont des strings UUID
5.2 Checklist finale
Compilation
cargo build --releasepasse sans warningcargo clippypasse sans erreurcargo test— tous les tests passent
Cohérence des types
- Aucun
i64pour des IDs dans src/ (vérifier avecgrep -r "i64" src/ | grep -v test | grep -v limit | grep -v count) - Tous les champs ID sont de type
Uuid - Toutes les requêtes SQLx utilisent
Uuid
Sérialisation JSON
- Les réponses JSON contiennent des UUID strings (pas des numbers)
- Les requêtes JSON acceptent des UUID strings
Intégration
- Le backend Go peut communiquer avec le chat-server
- Le frontend peut se connecter et envoyer/recevoir des messages
- Les IDs dans les messages WebSocket sont des strings
Documentation
- README mis à jour si nécessaire
- Commentaires de code à jour
6. Commandes d'exécution
# Étape 1 : Créer branche
git checkout -b fix/chat-server-uuid-migration
# Étape 2 : Tag de sauvegarde
git tag pre-uuid-migration-chat-server
# Étape 3 : Appliquer les modifications (voir sections 3.2)
# Étape 4 : Tester
cd veza-chat-server
cargo build --release
cargo test
# Étape 5 : Commit
git add .
git commit -m "refactor(chat-server): migrate all IDs from i64 to Uuid"
# Étape 6 : Tag final
git tag chat-server-uuid-migration-complete
7. Questions à clarifier
7.1 Schéma DB - Tables sans UUID
Problème : Les tables conversation_members, audit_logs, security_events n'ont pas de colonne uuid.
Options :
- Ajouter des colonnes UUID (migration DB) - Recommandé
- Garder BIGSERIAL et convertir en UUID côté application - Moins idéal
Recommandation : Créer une migration pour ajouter des colonnes uuid à ces tables.
7.2 Backend Go - Handlers avec int64
Problème : veza-backend-api/internal/api/handlers/chat_handlers.go utilise encore strconv.ParseInt pour les room_id.
Action : Migrer aussi le backend Go (hors scope de ce rapport, mais à noter).
7.3 JWT Tokens - Format user_id
Question : Le JWT généré par le backend Go contient-il user_id en UUID ou int64 ?
Action : Vérifier dans src/auth.rs et src/jwt_manager.rs comment le JWT est parsé.
8. Résumé des modifications
Fichiers à modifier (ordre de priorité)
-
🔴 Haute priorité :
src/messages.rs- WebSocket inbound messagessrc/hub/channels.rs- Structures et fonctions principalessrc/hub/direct_messages.rs- Direct messagessrc/repository/room_repository.rs- Repository layersrc/repository/message_repository.rs- Repository layer
-
🟡 Moyenne priorité :
src/hub/audit.rs- Audit logssrc/services/room_service.rs- Service layersrc/message_store.rs- Message storagesrc/websocket/handler.rs- WebSocket handlerssrc/websocket/broadcast.rs- Broadcast messages
-
🟢 Basse priorité :
- Tests unitaires
- Documentation
- Autres fichiers avec IDs
Statistiques
- Structs à migrer : 10
- Fonctions à modifier : ~40
- Requêtes SQL à mettre à jour : ~60
- Lignes de code à modifier : ~500-800
- Temps estimé : 4-6 heures
Document généré le : 2025-01-27
Prochaine étape : Commencer la migration avec l'étape 1 (préparation)