b1643309f6
Two real host-dispatch test files (no fakes) driving Server::try_handle_economy against a live in-process Core over the real blocking client + durable MarketStore/PileStore + JsonIdentityStore, each racer its own OS thread (off-runtime pattern). economy_concurrency.rs — 8 races x 50 iterations: A two BUYs (coins for one) -> exactly one 200 + one 461, final 0, one debit. B duplicate owned-pack open -> one redemption, +11 once, entitlement once. C duplicate quick-sell -> one sell + one credit + one removal. D two market buyers -> one win, one debit, one mint, sold once. E reward+BUY -> no lost update (Core relative UPDATE under BEGIN IMMEDIATE). F move+quick-sell / G list+quick-sell -> one coherent transition. H 1000 concurrent mints -> unique + reversible wire ids, monotonic watermark. economy_failure.rs — 10 fault-injection sub-cases, all fail-closed: BUY/open-redeem/generator/pile/identity, quick-sell, move, market reserve/purchase/complete. CRITICAL complete-sale-after-commit = SAFE: the listing is left `reserved` (not active), so the active->reserved reserve CAS can never win again -> not buyable, exactly one debit + one mint. No E3. Fault injection uses test-file CoreEconomy/ExternalIdentityStore doubles plus a NARROW, inert-by-default `StoreFault` seam in market_store.rs + pile_store.rs (the concrete stores have no trait boundary; 3 `tripped()` checks + a field, zero behaviour unless a test arms it). `parking_lot` promoted to a normal dep (the seam's Mutex is used at lib scope). Classifier/ROUTE_AUTHORITY/Python untouched. host lib 71/71; both new tests pass.
41 lines
2.1 KiB
TOML
41 lines
2.1 KiB
TOML
[package]
|
|
name = "openfut-utas-host"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
license = "MIT"
|
|
description = "FIFA 17 UTAS migration host: serves implemented routes (/club) from OpenFUT Core, transparently proxies everything else to the Python UTAS oracle"
|
|
publish = false
|
|
|
|
[dependencies]
|
|
openfut-adapter-fifa17 = { path = "../openfut-adapter-fifa17" }
|
|
openfut-http = { path = "../openfut-http" }
|
|
openfut-identity = { path = "../openfut-identity" }
|
|
serde_json = "1"
|
|
# Plain-HTTP client for Core queries and Python passthrough. UTAS is plaintext
|
|
# HTTP (worker D: no wrap_socket, no cert), so no TLS backend is linked.
|
|
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json"] }
|
|
# Durable FIFA-specific market listing + item-pile state. These are host-owned
|
|
# FIFA policy stores (NOT generic Core inventory), backed by their own SQLite
|
|
# file, opened exactly like openfut-core/src/db.rs::init_pool (WAL-once +
|
|
# foreign_keys + busy_timeout, BEGIN IMMEDIATE for writes).
|
|
sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio"] }
|
|
# Seeded RNG for the Store pack-content generator injected into the economy
|
|
# writer handlers (`economy_store`). Production seeds it from entropy (so minted
|
|
# Core instance ids never collide); tests seed a fixed value for reproducibility.
|
|
rand = "0.8"
|
|
# One process-lifetime runtime drives the async transfer-market / pile handlers
|
|
# (sqlx runtime-tokio). Created once in `Server::from_config`, shared via `Arc`;
|
|
# the `AsyncBridge` bridges the synchronous thread-per-connection dispatch to it.
|
|
tokio = { version = "1", features = ["rt-multi-thread"] }
|
|
# Fast, non-poisoning mutex guarding the in-memory hot paths of the durable
|
|
# market/pile stores (used in `src/market_store.rs` / `src/pile_store.rs`).
|
|
parking_lot = "0.12"
|
|
|
|
[dev-dependencies]
|
|
parking_lot = "0.12"
|
|
# Real host<->Core integration harness: spawn Core (axum) against a disposable
|
|
# temp-file SQLite and drive the real CoreEconomy transport (no fakes).
|
|
openfut-core = { path = "../openfut-core" }
|
|
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net"] }
|
|
axum = "0.7"
|