Conventions Protobuf -- EIP-MemTide¶
Portee¶
Ce document definit les conventions applicables a tous les fichiers Protocol Buffers (.proto) du projet MemTide. Il concerne le depot memtide-proto, source unique de verite pour les definitions gRPC partagees entre les composants de l'organisation (memtide, memtide-gateway, memtide-yapper, FrontL). Tout contributeur modifiant ou creant des fichiers .proto doit s'y conformer sans exception.
1. Syntaxe¶
Tous les fichiers utilisent exclusivement proto3. L'utilisation de proto2 est interdite.
syntax = "proto3";
package memtide.proto;
option go_package = "github.com/EIP-memtide/memtide-proto/gen/go/memtidepb";
2. Conventions de nommage¶
| Element | Convention | Exemple |
|---|---|---|
| Messages | PascalCase |
TopologyData, MemoryBlock |
| Champs | snake_case |
total_bytes, node_id |
| Enums | PascalCase |
TierType, NumaNodeType |
| Valeurs d'enum | UPPER_CASE |
NUMA_DRAM, CXL_EXPANDER |
| Services | PascalCase |
TopologyService, HealthService |
| Methodes RPC | PascalCase |
GetTopology, MigratePages |
| Fichiers | snake_case.proto |
topology_data.proto |
| Packages | lowercase.dotted |
memtide.proto, memtide.v1 |
Regles supplementaires :
- Les noms de messages et services sont des noms :
TopologyData,MigrationStats. - Les methodes RPC sont des verbes :
GetTopology,StreamPages,MigrateMemory. - Les champs booleens utilisent un prefixe semantique :
is_cxl,has_data,ok. - Les champs de quantite incluent l'unite :
total_bytes,uptime_sec,base_freq_ghz.
3. Enumerations¶
Valeur zero obligatoire¶
La premiere valeur doit etre zero avec le suffixe _UNSPECIFIED. Elle sert de sentinelle et ne represente jamais une valeur metier.
enum TierType {
TIER_TYPE_UNSPECIFIED = 0;
TIER_TYPE_NUMA_DRAM = 1;
TIER_TYPE_CXL = 2;
}
Prefixe court¶
Les valeurs d'enum sont prefixees par le nom de l'enum en UPPER_CASE pour eviter les collisions :
| Enum | Prefixe | Exemple de valeurs |
|---|---|---|
TierType |
TIER_TYPE_ |
TIER_TYPE_UNSPECIFIED, TIER_TYPE_NUMA_DRAM |
NumaNodeType |
NUMA_NODE_TYPE_ |
NUMA_NODE_TYPE_UNSPECIFIED, NUMA_NODE_TYPE_DRAM |
Declarer l'enum au niveau du fichier si elle est referencee par plusieurs messages ; l'imbriquer dans un message uniquement si elle lui est strictement privee.
4. Compatibilite wire¶
La compatibilite wire est sacree. Toute rupture empeche les anciens clients de communiquer avec les nouveaux serveurs.
| Action interdite | Consequence |
|---|---|
| Changer le tag numerique d'un champ | Corruption silencieuse |
| Changer le type d'un champ | Deserialisation incorrecte |
| Supprimer un champ | Donnees perdues silencieusement |
| Reutiliser un tag deja utilise | Corruption silencieuse |
| Action autorisee | Securite |
|---|---|
| Ajouter un nouveau champ | Toujours safe |
| Ajouter une nouvelle valeur d'enum | Safe (zero reste UNSPECIFIED) |
| Ajouter une nouvelle methode RPC | Safe |
| Renommer un champ | Safe (wire = tag, pas nom) |
Champs retires : reserved¶
Ne jamais supprimer un champ. Le marquer reserved pour interdire la reutilisation du tag et du nom :
message TopologyData {
reserved 6;
reserved "legacy_field";
CpuInfo cpu_info = 1;
repeated NumaNode nodes = 2;
repeated int32 distance_matrix_flat = 4;
}
Verifier avant chaque commit : buf breaking --against '.git#branch=dev'
5. Definitions de services¶
Nommage des RPC¶
| Pattern | Prefixe | Exemple |
|---|---|---|
| Lecture unitaire | Get |
GetTopology, GetMigrationStats |
| Liste | List |
ListProcesses, ListNodes |
| Action / mutation | Verbe d'action | MigrateMemory, SetPid |
| Stream serveur | Stream |
StreamPages, StreamTopology |
| Health check | Check |
Check |
Streaming¶
- Un RPC de streaming serveur retourne
stream <MessageType>. - Utiliser
google.protobuf.Emptypour les streams sans parametre. - Preferer un message de requete dedie si des filtres sont necessaires.
rpc StreamPages (google.protobuf.Empty) returns (stream PageSnapshot);
rpc StreamNodeMetrics (StreamNodeMetricsRequest) returns (stream NodeMetrics);
Messages Request / Response¶
Chaque RPC definit une paire <MethodName>Request / <MethodName>Response (sauf usage de google.protobuf.Empty). Les reponses avec statut d'erreur incluent string error_message.
message MigrateMemoryRequest {
uint32 pid = 1;
uint64 page_addr = 2;
}
message MigrateMemoryResponse {
bool ok = 1;
string error_message = 2;
}
6. Organisation des fichiers¶
Structure du depot¶
memtide-proto/
memtide.proto # Source unique de verite
buf.yaml # Lint (STANDARD) + breaking (WIRE)
buf.gen.yaml # Plugins de generation (Go, C++)
gen/ # Code genere -- NE JAMAIS EDITER
go/ # Stubs Go (memtide-gateway)
cpp/ # Stubs C++ (memtide, FrontL)
flake.nix # Environnement Nix reproductible
Evolution vers plusieurs fichiers¶
Si le schema grandit, decouper selon la regle un service par fichier :
| Fichier | Contenu |
|---|---|
topology.proto |
TopologyService et ses messages |
migration.proto |
MigrateMemoryService, MigrationStatsService |
health.proto |
HealthService, HealthResponse |
common.proto |
Messages partages (CpuInfo, NumaNode, etc.) |
Tous les fichiers partagent le meme package memtide.proto et s'importent via import "common.proto";.
7. Code genere et workflow¶
Les fichiers dans gen/ sont generes par protoc via Buf. Il est strictement interdit de les modifier manuellement.
| Plugin | Sortie | Consommateurs |
|---|---|---|
protoc-gen-cpp |
gen/cpp/ |
memtide, FrontL |
protoc-gen-grpc-cpp |
gen/cpp/ |
memtide, FrontL |
protoc-gen-go |
gen/go/ |
memtide-gateway |
protoc-gen-go-grpc |
gen/go/ |
memtide-gateway |
Regeneration (depuis un shell Nix) : nix run .#gen-cpp et nix run .#gen-go. Commiter les fichiers generes avec les .proto modifies dans le meme PR.
8. Linting et validation¶
Le projet utilise Buf CLI (buf.yaml : lint STANDARD, breaking WIRE).
| Commande | Role |
|---|---|
buf lint |
Respect des regles STANDARD |
buf breaking --against '.git#branch=dev' |
Compatibilite wire |
La categorie STANDARD impose notamment : PascalCase pour messages/enums/services, snake_case pour les champs, valeur zero _UNSPECIFIED dans les enums, prefixe sur les valeurs d'enum, package et go_package declares. Toute violation bloque le commit.
9. Formatage et commentaires¶
Indentation¶
- 2 espaces (pas de tabulations).
- Une ligne vide entre chaque definition de message, enum ou service.
Commentaires¶
- Utiliser exclusivement
//(pas/* */). - Placer les commentaires au-dessus de l'element documente.
- Documenter chaque message et service ; documenter les champs non triviaux.
- Les commentaires sont rediges en anglais americain (U.S. English).
// Hardware topology of the host machine.
// Includes CPU info, NUMA nodes, sockets, and distance matrix.
message TopologyData {
// Processor identification and capabilities.
CpuInfo cpu_info = 1;
// All NUMA nodes discovered on the host.
repeated NumaNode nodes = 2;
// Row-major flattened NUMA distance matrix.
repeated int32 distance_matrix_flat = 4;
// Side length of the square distance matrix.
uint32 distance_matrix_size = 5;
}
Checklist avant commit¶
syntax = "proto3",packageetgo_packagedeclares.- Nommage conforme (section 2) ; enums avec zero
_UNSPECIFIEDet prefixe (section 3). - Aucun tag existant modifie, change de type ou reutilise (section 4).
buf lintetbuf breaking --against '.git#branch=dev'passent sans erreur.- Stubs generes a jour (
nix run .#gen-cpp,nix run .#gen-go) et commites avec les.proto. - Commentaires en anglais, places au-dessus des elements documentes.