v0.2.7-pre.007
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<!-- file: docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Plan `0.2.7` — WebSocket Solana standard
|
||||
|
||||
> **Statut : actif, `0.2.7-pre.005`.** `pre.004-fix.001` est validé opérateur. `pre.005` durcit la session physique avec limites adversariales, control frames, purge des pending requests et shutdown explicite borné. Les subscriptions typed restent différées.
|
||||
> **Statut : actif, `0.2.7-pre.007`.** `pre.006-fix.001` est validé opérateur. `pre.007` active le reconnect borné, le resubscribe déterministe, le compteur de continuity gaps et les races unsubscribe/reconnect. Les wrappers typed publics restent différés.
|
||||
|
||||
## 1. Objet et base vérifiée
|
||||
|
||||
@@ -490,6 +490,8 @@ Le handle public `WsSession` communique avec cet actor par canal bounded. Aucun
|
||||
|
||||
`pre.006` matérialise le registry dans ce même actor. L'ACK `*Subscribe` lie atomiquement le remote ID au `WsSubscriptionId` local avant le dispatch des notifications suivantes. La création générique typed reste crate-private ; `WsSubscription<T>` devient le handle public commun pour `id/state/recv/unsubscribe`. Les channels de notification sont bornés et typed via un dispatcher actor type-erased. Les remote IDs restent absents de l'API publique et des snapshots.
|
||||
|
||||
`pre.007` active la résilience physique déjà paramétrée par `WsSessionSettings`. Une perte I/O, EOF, Close distant inattendu ou violation protocolaire structurelle invalide les remote IDs et incrémente `continuity_gap_count`. Le reconnect utilise un nombre fini d'essais, un backoff exponentiel borné sans jitter et surveille le shutdown pendant backoff et handshake. Avec `ActiveSubscriptions`, les subscriptions encore désirées sont remises en `Resubscribing` puis restaurées séquentiellement par `WsSubscriptionId` croissant avant le retour complet à `Active`; avec `Never`, elles deviennent terminales sans empêcher la reconnexion physique. La cancellation locale gagne pendant reconnect et un ACK tardif déclenche un unsubscribe distant best-effort sans réactivation locale.
|
||||
|
||||
### 9.4 Identités
|
||||
|
||||
```text
|
||||
@@ -879,7 +881,7 @@ pre.003 DONE — std.transport V2 HTTP+WS + backward V1 + discriminateur WS + s
|
||||
pre.004 DONE — deps tokio-tungstenite/futures-util + actor physique + handshake/read/write + pending JSON-RPC + serveur local
|
||||
pre.005 DONE — limites frame/message/request + control frames + cancellation/close/shutdown + adversarial socket tests
|
||||
pre.006 DONE — registry subscriptions + IDs locaux + generic subscribe/unsubscribe engine + channels typed bounded
|
||||
pre.007 reconnect borné + resubscribe déterministe + continuity gap + races unsubscribe/reconnect
|
||||
pre.007 DONE — reconnect borné + resubscribe déterministe + continuity gap + races unsubscribe/reconnect
|
||||
pre.008 backpressure per-sub + overflow/limits + leak/lifecycle adversarial tests
|
||||
pre.009 wrappers stable lot A : account + program + logs, DTOs/options/KSP-TRANSPORT-007
|
||||
pre.010 wrappers stable lot B : signature + slot + root, terminaison signature/KSP-TRANSPORT-007
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!-- file: docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
|
||||
# Validation `0.2.7` — WebSocket Solana standard
|
||||
|
||||
> **Statut : matrice active, `0.2.7-pre.005`.** Settings/lifecycle `pre.002`, Config V2 `pre.003`, session physique `pre.004` et durcissement limits/control/shutdown `pre.005` sont matérialisés. Registry subscriptions, reconnect et wrappers typed restent ouverts.
|
||||
> **Statut : matrice active, `0.2.7-pre.007`.** Settings/lifecycle `pre.002`, Config V2 `pre.003`, session physique `pre.004`, durcissement `pre.005`, registry `pre.006` et reconnect/resubscribe `pre.007` sont matérialisés. Backpressure per-sub et wrappers typed restent ouverts.
|
||||
|
||||
## 1. Baseline normative
|
||||
|
||||
@@ -216,8 +216,8 @@ Les votes observés sont gossip/pre-consensus ; aucune garantie d'entrée dans l
|
||||
| JSON borné indirectement par message | oversized + malformed fixture | Planned |
|
||||
| queues notifications bornées | capacité settings, channel futur | Partial `pre.002` |
|
||||
| pending RPC borné + timeout | map actor bornée + timeout request | **Done `pre.004`** |
|
||||
| reconnect loop bornée | repeated disconnect fixture | Planned |
|
||||
| unsubscribe pendant reconnect ne resubscribe pas | race fixture | Planned |
|
||||
| reconnect loop bornée | repeated disconnect fixture | Done `pre.007` |
|
||||
| unsubscribe pendant reconnect ne resubscribe pas | race fixture | Done `pre.007` |
|
||||
| signature terminale ne resubscribe pas | terminal fixture | Planned |
|
||||
| shutdown ne bloque pas | peer hostile/no close ack fixture | Planned |
|
||||
| no Store/Program/Wallet/Config dep dans Transport | cargo tree + source canary | Planned |
|
||||
@@ -368,7 +368,7 @@ outbound JSON-RPC > borne message/frame -> rejet avant socket write, session Act
|
||||
inbound frame/message oversized -> rejet Tungstenite avant parse JSON, session Failed
|
||||
pending request silencieuse -> timeout + purge de capacité, session Active
|
||||
Ping distant -> Pong automatique flushé, session Active
|
||||
Close distant propre -> Closed et non Failed
|
||||
Close distant propre -> checkpoint `pre.005` Closed ; à partir de `pre.007`, perte physique reprise par reconnect borné
|
||||
WsSession::close() -> Closing -> Closed
|
||||
close() annule les pending requests avec ws_session_closed
|
||||
peer hostile qui ne répond pas au Close -> shutdown borné
|
||||
@@ -390,7 +390,7 @@ remote -> local mapping actor-owned
|
||||
subscribe generic crate-private, wrappers publics futurs
|
||||
unsubscribe handle public, bool Solana préservé
|
||||
notification queue typed + bounded
|
||||
reconnect/resubscribe non, pre.007
|
||||
reconnect/resubscribe non à ce checkpoint ; matérialisé en pre.007
|
||||
backpressure adversarial complet non, pre.008
|
||||
```
|
||||
|
||||
@@ -410,6 +410,43 @@ snapshot -> local IDs + remote_bound uniquement
|
||||
|
||||
Le registry est détenu par le même actor que le socket et la pending map JSON-RPC. Aucun caller ne manipule le socket ni le remote ID. Les wrappers publics `accountSubscribe`, `programSubscribe`, etc. restent volontairement différés aux lots `pre.009+` afin de ne pas exposer une API raw provider-extension intermédiaire.
|
||||
|
||||
|
||||
## 9.5 Checkpoint reconnect/resubscribe `pre.007`
|
||||
|
||||
Surface matérialisée :
|
||||
|
||||
```text
|
||||
reconnect triggers EOF, Close distant inattendu, I/O/TLS/WebSocket/protocole structurel
|
||||
reconnect budget fini, configurable
|
||||
backoff exponentiel borné, sans jitter
|
||||
shutdown pendant reconnect prioritaire, annule backoff/handshake
|
||||
continuity_gap_count incrémenté une fois par perte de continuité logique
|
||||
remote IDs après perte invalidés immédiatement
|
||||
ActiveSubscriptions resubscribe local-ID croissant
|
||||
Never aucune restauration automatique
|
||||
budget reset seulement après retour complet à Active
|
||||
unsubscribe pendant reconnect cancellation locale gagnante
|
||||
ACK resubscribe tardif cleanup distant best-effort, aucune réactivation locale
|
||||
backfill HTTP aucun
|
||||
lossless guarantee aucune
|
||||
```
|
||||
|
||||
Gates déterministes ajoutés :
|
||||
|
||||
```text
|
||||
remote Close + budget insuffisant -> Reconnecting puis Failed, jamais boucle infinie
|
||||
2 subscriptions -> resubscribe dans l'ordre WsSubscriptionId 1 puis 2
|
||||
remote IDs 101/202 -> remappés 301/302 sans changer les IDs locaux
|
||||
params de subscribe -> conservés et rejoués à l'identique
|
||||
unsubscribe pendant backoff -> sub Closed et absente de la sélection resubscribe
|
||||
unsubscribe après émission resubscribe -> ACK tardif nettoyé par *Unsubscribe best-effort
|
||||
policy Never -> session reconnectée Active, subscription terminale Failed
|
||||
2 pertes séparées avec max_retries=1 -> deux recoveries possibles, budget réinitialisé après Active
|
||||
continuity_gap_count -> 1 puis 2 sur deux pertes distinctes
|
||||
```
|
||||
|
||||
Les requests applicatives en vol au moment d'une perte physique échouent ; Transport ne les rejoue pas implicitement. La restauration ne promet aucune continuité lossless et n'effectue aucun backfill HTTP. Les remote subscription IDs restent strictement internes et sont remplacés à chaque ACK de resubscribe.
|
||||
|
||||
## 10. Validation du gate `pre.001`
|
||||
|
||||
Exécuté dans le sandbox :
|
||||
|
||||
Reference in New Issue
Block a user