v0.2.7-pre.009-fix.002
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 206
|
||||
# version: 207
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.2.7-pre.9.fix.1"
|
||||
version = "0.2.7-pre.9.fix.2"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/rpc_transactions.rs
|
||||
// version: 9
|
||||
// version: 10
|
||||
|
||||
#[test]
|
||||
fn transaction_encoding_strings_match_current_and_legacy_wire_labels() {
|
||||
@@ -325,15 +325,36 @@ fn serve_transaction_once(body: &'static str) -> (std::string::String, std::thre
|
||||
let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("fixture listener must bind");
|
||||
let address = listener.local_addr().expect("fixture listener address must resolve");
|
||||
let handle = std::thread::spawn(move || {
|
||||
let (mut stream, _) = listener.accept().expect("fixture server must accept one request");
|
||||
let request = read_transaction_request(&mut stream);
|
||||
let response = format!("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", body.len(), body,);
|
||||
std::io::Write::write_all(&mut stream, response.as_bytes()).expect("fixture response must write");
|
||||
return request;
|
||||
loop {
|
||||
let (mut stream, _) = listener.accept().expect("fixture server must accept one request");
|
||||
let request = read_transaction_request(&mut stream);
|
||||
if !transaction_request_complete(request.as_bytes()) {
|
||||
continue;
|
||||
}
|
||||
let response = format!("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", body.len(), body,);
|
||||
std::io::Write::write_all(&mut stream, response.as_bytes()).expect("fixture response must write");
|
||||
return request;
|
||||
}
|
||||
});
|
||||
return (format!("http://{address}"), handle);
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "current_thread")]
|
||||
async fn transaction_fixture_ignores_abandoned_connection_before_complete_request() {
|
||||
let (url, handle) = serve_transaction_once(include_str!("../fixtures/http/get_transaction.null.json"));
|
||||
let address = url.strip_prefix("http://").expect("fixture URL must use HTTP");
|
||||
let abandoned = std::net::TcpStream::connect(address).expect("abandoned fixture connection must connect");
|
||||
drop(abandoned);
|
||||
let pool = transaction_pool_for_url(url.as_str());
|
||||
let result = pool
|
||||
.get_transaction(&crate::HttpRoleName::new("default"), "fixture-signature", std::option::Option::None)
|
||||
.await
|
||||
.expect("fixture must remain available after abandoned pre-request connection");
|
||||
assert!(result.is_none());
|
||||
let request = handle.join().expect("fixture server must join");
|
||||
assert_eq!(transaction_request_body(request.as_str())["method"], serde_json::json!("getTransaction"));
|
||||
}
|
||||
|
||||
fn serve_transaction_status_and_count(status_line: &'static str) -> (std::string::String, std::thread::JoinHandle<(usize, std::string::String)>) {
|
||||
let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("fixture listener must bind");
|
||||
let address = listener.local_addr().expect("fixture listener address must resolve");
|
||||
|
||||
94
deltas/0.2.7/pre.009-fix.002.md
Normal file
94
deltas/0.2.7/pre.009-fix.002.md
Normal file
@@ -0,0 +1,94 @@
|
||||
<!-- file: deltas/0.2.7/pre.009-fix.002.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.2.7-pre.009-fix.002` — robustesse du fixture HTTP one-shot Transactions
|
||||
|
||||
## Base
|
||||
|
||||
Base directe publiée :
|
||||
|
||||
```text
|
||||
0.2.7-pre.009-fix.001
|
||||
Cargo 0.2.7-pre.9.fix.1
|
||||
```
|
||||
|
||||
La validation opérateur de `fix.001` confirme :
|
||||
|
||||
- `cargo fmt --all` : vert ;
|
||||
- audit Python KSP : vert ;
|
||||
- `cargo check --workspace` : vert ;
|
||||
- `cargo clippy --workspace --all-targets` : vert ;
|
||||
- premier `cargo test -p ksp-onchain-transport-lib` : 294 tests unitaires verts, 33 tests d'API publique verts, 22 tests de release completeness verts ;
|
||||
- le passage ultérieur via `cargo test --workspace` reproduit une seule défaillance intermittente dans un canari HTTP historique `getTransaction`, avec `http_connection_failed / Connection refused` sur son endpoint local one-shot.
|
||||
|
||||
Le wrapper WebSocket `pre.009` et le correctif Clippy `fix.001` ne sont pas en cause : le même test `getTransaction` est passé quelques secondes auparavant dans le premier run Transport.
|
||||
|
||||
## Signal technique
|
||||
|
||||
```text
|
||||
livraison = 0.2.7-pre.009-fix.002
|
||||
workspace.package.version = 0.2.7-pre.9.fix.2
|
||||
commit = v0.2.7-pre.009-fix.002
|
||||
```
|
||||
|
||||
Aucun tag Git n'est requis pour ce fix de prerelease.
|
||||
|
||||
## Diagnostic
|
||||
|
||||
Le helper historique `serve_transaction_once` consommait sans distinction la première connexion TCP acceptée :
|
||||
|
||||
```text
|
||||
accept
|
||||
-> read_transaction_request
|
||||
-> réponse fixture
|
||||
-> fermeture du listener
|
||||
```
|
||||
|
||||
`read_transaction_request` peut cependant revenir sur EOF avant qu'une requête HTTP complète ait été reçue. Une connexion locale ouverte puis abandonnée avant l'envoi complet de la requête pouvait donc consommer le serveur one-shot. Une tentative cliente suivante rencontrait alors un listener déjà fermé et pouvait échouer avec `Connection refused`.
|
||||
|
||||
Cette faiblesse appartient uniquement au fixture de test local. Aucun changement du runtime HTTP ou WebSocket n'est requis.
|
||||
|
||||
## Correction
|
||||
|
||||
`serve_transaction_once` ignore désormais toute connexion qui se termine avant que `transaction_request_complete(...)` soit vrai. Le body fixture n'est consommé et le listener n'est terminé qu'après réception d'une requête HTTP complète.
|
||||
|
||||
Un canari déterministe est ajouté :
|
||||
|
||||
```text
|
||||
transaction_fixture_ignores_abandoned_connection_before_complete_request
|
||||
```
|
||||
|
||||
Il ouvre volontairement une première connexion TCP locale puis la ferme sans envoyer de requête, avant d'exécuter un `getTransaction` normal. Le fixture doit rester disponible et servir correctement la requête complète suivante.
|
||||
|
||||
Le correctif est exclusivement test-only : aucun fichier `src/`, aucun DTO, aucune règle de retry, aucun wrapper RPC et aucune sémantique WebSocket ne changent.
|
||||
|
||||
## Fichiers
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
crates/ksp-onchain-transport-lib/unit_tests/rpc_transactions.rs
|
||||
deltas/0.2.7/pre.009-fix.002.md
|
||||
```
|
||||
|
||||
`ROADMAP.md`, `CHANGELOG.md`, le plan et le document de validation restent inchangés.
|
||||
|
||||
## Validation attendue
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
cargo test -p ksp-onchain-transport-lib
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
Comptages Transport attendus :
|
||||
|
||||
```text
|
||||
unit tests = 295
|
||||
public API tests = 33
|
||||
release completeness = 22
|
||||
```
|
||||
|
||||
Les validations Cargo doivent être exécutées par l'opérateur ; elles ne sont pas revendiquées depuis l'environnement de préparation du delta.
|
||||
Reference in New Issue
Block a user