0.3.5-alpha.4
This commit is contained in:
208
deltas/0.3.5/alpha.4.md
Normal file
208
deltas/0.3.5/alpha.4.md
Normal file
@@ -0,0 +1,208 @@
|
||||
<!-- file: deltas/0.3.5/alpha.4.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.5-alpha.4
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.5-alpha.3`, validée par l'utilisateur le 2026-09-21 avec fmt, audits, check workspace, Clippy strict, les sept tests du contrat realtime commun et les huit tests WebTransport entièrement verts.
|
||||
|
||||
La validation réellement fournie est conservée dans `history/0.3.5/alpha.3.md`.
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer la robustesse du chemin fiable WebTransport natif avant de créer le smoke runtime public. Cette tranche porte limites/deadlines, lifecycle, cancellation et cas négatifs de framing, sans introduire encore WASM, datagrams, fallback ou benchmark.
|
||||
|
||||
La version passe à :
|
||||
|
||||
```text
|
||||
0.3.5-alpha.4
|
||||
```
|
||||
|
||||
## Configuration et limites
|
||||
|
||||
Nouveau `WebTransportConfig` partagé par les configs client/server, avec defaults POC explicites :
|
||||
|
||||
```text
|
||||
max_message_size = 1 MiB
|
||||
connect_timeout = 10 s
|
||||
primary_stream_timeout = 5 s
|
||||
send_timeout = 5 s
|
||||
```
|
||||
|
||||
La configuration est immutable par builders copiés et validée avant bind/connect. Sont refusés :
|
||||
|
||||
- `max_message_size == 0` ;
|
||||
- une borne qui ne tient pas dans le champ de longueur `u32` sur les plateformes où cela peut arriver ;
|
||||
- une deadline nulle.
|
||||
|
||||
La borne n'est plus une constante cachée : sender et receiver utilisent chacun la configuration transport associée à leur session. Le receiver contrôle toujours la longueur avant allocation.
|
||||
|
||||
## Deadlines et backpressure
|
||||
|
||||
Le client borne la tentative d'établissement complète par `connect_timeout`.
|
||||
|
||||
Le listener conserve une attente non bornée du prochain pair, comportement normal d'un serveur idle. Une fois la requête WebTransport CONNECT matérialisée, la réponse serveur est bornée par `connect_timeout`.
|
||||
|
||||
Ouverture et accept du stream bidirectionnel primaire sont bornés par `primary_stream_timeout`.
|
||||
|
||||
Un send complet — header puis payload — est borné par `send_timeout`. La backpressure reste celle du flow-control QUIC : aucune queue applicative artificielle n'est introduite. Si le flow-control empêche l'envoi de terminer dans la deadline, le résultat observable est `TransportErrorKind::Timeout`.
|
||||
|
||||
`receive()` n'impose volontairement aucun timeout d'idle. L'absence de message n'est pas une erreur transport ; la future peut être bornée/annulée par l'appelant.
|
||||
|
||||
## Cancellation sûre du receive
|
||||
|
||||
Le receiver n'utilise plus une lecture monolithique header/payload. Il garde un état incrémental :
|
||||
|
||||
```text
|
||||
header bytes read
|
||||
payload allocation after validated length
|
||||
payload bytes read
|
||||
```
|
||||
|
||||
La primitive de lecture amont utilisée est cancel-safe. Si une future `receive()` est abandonnée après une partie de la frame, l'état acquis reste dans `WebTransportReceiver` et l'appel suivant reprend au bon octet.
|
||||
|
||||
Cela permet de combiner un wait externe borné avec le contrat `RealtimeReceiver` sans perdre de bytes ni désynchroniser le framing.
|
||||
|
||||
## Close, reset, abort et drop
|
||||
|
||||
Le FIN propre reste `RealtimeSender::close()`.
|
||||
|
||||
Le backend concret expose en complément :
|
||||
|
||||
```text
|
||||
WebTransportSender::abort(code)
|
||||
WebTransportReceiver::abort(code)
|
||||
```
|
||||
|
||||
Le premier reset la direction d'envoi ; le second stoppe la direction de réception.
|
||||
|
||||
Un sender ou receiver encore actif au moment de son drop est aborté explicitement au lieu de laisser le backend transformer implicitement le drop en FIN propre.
|
||||
|
||||
Un `send()` annulé en cours d'écriture est terminal : un guard reset le stream, car une frame dont seulement le header ou une partie du payload a été écrit ne peut pas être reprise sans ambiguïté. Une cancellation de `receive()` reste au contraire reprenable grâce au parseur incrémental.
|
||||
|
||||
## Framing négatif et mapping d'erreurs
|
||||
|
||||
Les nouvelles branches explicites sont :
|
||||
|
||||
- longueur entrante supérieure à `max_message_size` -> `MessageTooLarge`, avant allocation, puis stop de la direction ;
|
||||
- EOF à frontière de frame -> `TransportReceive::Closed` ;
|
||||
- EOF au milieu du header ou du payload -> `Protocol` ;
|
||||
- reset/STOP distant -> `Aborted` ;
|
||||
- stream/session fermé proprement -> `Closed` ;
|
||||
- état de stream invalide rapporté par le backend -> `Protocol` ;
|
||||
- deadline dépassée -> `Timeout` ;
|
||||
- autre erreur de session -> `Io`.
|
||||
|
||||
Les types d'erreurs Quinn/WebTransport restent privés à la crate backend.
|
||||
|
||||
## Tests
|
||||
|
||||
Les tests unitaires ajoutent :
|
||||
|
||||
- validation des defaults et configurations invalides ;
|
||||
- mapping reset/STOP, close et erreur protocolaire ;
|
||||
- cancellation d'un `receive()` après deux octets de header puis reprise exacte ;
|
||||
- header ou payload tronqué par FIN -> `Protocol`.
|
||||
|
||||
Le nouveau `tests/robustness.rs` prouve en loopback :
|
||||
|
||||
- rejet outbound d'un message supérieur à la borne avant écriture ;
|
||||
- rejet inbound d'une longueur supérieure à la borne avant allocation ;
|
||||
- reset explicite sender observé comme `Aborted` par le pair ;
|
||||
- abort explicite receiver rendant immédiatement sa moitié locale terminale ;
|
||||
- drop sender sans `close()` observé comme `Aborted`, pas comme FIN propre ;
|
||||
- deadline d'accept du stream primaire lorsque le pair n'en ouvre aucun.
|
||||
|
||||
Aucun test de saturation artificielle n'est ajouté : provoquer de façon déterministe le flow-control QUIC sans s'appuyer sur des internals amont élargirait inutilement la tranche. Le mécanisme est borné par `send_timeout` et sera aussi exercé indirectement par les smokes/mesures ultérieurs.
|
||||
|
||||
## API et documentation
|
||||
|
||||
`src/lib.rs` réexporte `WebTransportConfig` conformément aux règles d'exports du workspace.
|
||||
|
||||
`README.md` et `USAGE.md` de la crate documentent les limites, le scope exact des deadlines, les différences FIN/abort/drop et les garanties de cancellation.
|
||||
|
||||
Le plan `005` est réconcilié avec les décisions réellement matérialisées. `ROADMAP.md` et `CHANGELOG.md` restent inchangés : la mission macro de `0.3.5` n'est pas modifiée par cette alpha.
|
||||
|
||||
## Dépendances
|
||||
|
||||
Aucune nouvelle crate n'est introduite.
|
||||
|
||||
`tokio`, déjà présent dans le workspace et déjà utilisé comme dev-dependency de la crate, devient aussi une dépendance runtime locale avec la feature `time`, car le backend porte désormais ses deadlines opérationnelles.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
crates/common/game-realtime-webtransport-lib/Cargo.toml
|
||||
crates/common/game-realtime-webtransport-lib/README.md
|
||||
crates/common/game-realtime-webtransport-lib/USAGE.md
|
||||
crates/common/game-realtime-webtransport-lib/src/lib.rs
|
||||
crates/common/game-realtime-webtransport-lib/src/webtransport.rs
|
||||
crates/common/game-realtime-webtransport-lib/unit_tests/webtransport.rs
|
||||
docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md
|
||||
```
|
||||
|
||||
Nouveaux fichiers :
|
||||
|
||||
```text
|
||||
crates/common/game-realtime-webtransport-lib/src/config.rs
|
||||
crates/common/game-realtime-webtransport-lib/tests/robustness.rs
|
||||
crates/common/game-realtime-webtransport-lib/unit_tests/config.rs
|
||||
history/0.3.5/alpha.3.md
|
||||
deltas/0.3.5/alpha.4.md
|
||||
```
|
||||
|
||||
## Validation exécutée dans l'environnement de génération
|
||||
|
||||
L'environnement de génération ne possède pas de toolchain Rust. Aucun `cargo fmt`, `cargo check`, Clippy ou test n'est donc attribué à cette livraison.
|
||||
|
||||
Les audits statiques disponibles ont été exécutés sur le candidat final :
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 275 file(s))
|
||||
Distribution layout audit: clean (50 required path(s), 8 forbidden path(s) absent)
|
||||
Targeted alpha.4 consistency audit: clean
|
||||
```
|
||||
|
||||
Le compteur Markdown correspond à la reconstruction de travail issue du ZIP taggé et des deltas appliqués ; il n'est pas utilisé comme invariant contre le checkout utilisateur.
|
||||
|
||||
Le ZIP delta a ensuite été appliqué sur une copie propre de `0.3.5-alpha.3`. L'overlay reproduit exactement le candidat `alpha.4`, contient 14 fichiers utiles et repasse les mêmes audits Rust/workspace, Markdown et distribution, ainsi que le contrôle ciblé de version/cohérence. `unzip -t` ne signale aucune erreur.
|
||||
|
||||
## Validation utilisateur demandée
|
||||
|
||||
Cette tranche modifie le backend runtime et son graphe local de features Tokio. La gate ciblée est :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo fmt --all -- --check
|
||||
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
|
||||
python3 scripts/audit_distribution_layout.py
|
||||
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
|
||||
cargo test -p game-realtime-transport-lib --all-targets --all-features
|
||||
cargo test -p game-realtime-webtransport-lib --all-targets --all-features
|
||||
|
||||
cargo tree -p game-realtime-webtransport-lib --edges normal
|
||||
cargo tree -i game-realtime-webtransport-lib --workspace --edges normal
|
||||
```
|
||||
|
||||
Le contrat commun est retesté pour garantir que les nouvelles catégories de lifecycle du backend restent compatibles avec son API transport-neutral.
|
||||
|
||||
Le tree direct vérifie le passage de Tokio en dépendance runtime locale ; le tree inverse conserve la preuve qu'aucune crate engine/gameplay n'a acquis le backend concret.
|
||||
|
||||
Aucun smoke executable n'est attendu dans cette tranche. Le smoke natif hors harness reste strictement réservé à `alpha.5` afin de respecter la taille d'un delta.
|
||||
|
||||
## Suite après validation
|
||||
|
||||
Si la gate est propre, ouvrir `0.3.5-alpha.5` pour créer/finaliser `game-realtime-webtransport-smoke`, effectuer un round-trip localhost hors `#[test]`, produire un `PASS` déterministe et contrôler le graphe runtime.
|
||||
|
||||
Un défaut fermé de cette tranche produit d'abord `0.3.5-alpha.4.fix.N` au lieu d'ouvrir `alpha.5`.
|
||||
Reference in New Issue
Block a user