580d80a86e
Bridges the synchronous thread-per-connection host to the async
transfer-market/pile handlers WITHOUT flipping the classifier. classify()
is untouched; production still proxies every economy route to Python. The
new dispatch is exercised only by the integration harness via
Server::try_handle_economy — handler wiring, not authority cutover.
async_bridge.rs: AsyncBridge owns ONE process-lifetime multi-threaded Tokio
runtime, shared by every connection via Arc. block_on() runs a future from
the sync dispatch thread; if invoked from within an ambient runtime it
offloads onto its own runtime + a std channel instead of panicking
("cannot start a runtime from within a runtime"). 4 unit tests incl. the
nested-runtime-safety case and concurrent multi-thread drivers.
lib.rs: EconomyRoute + classify_economy (mirrors the Python route table:
credits, purchasegroup, store/transaction, purchased, item DELETE/PUT,
ut/delete match/item/trade, auctionhouse/transfermarket, tradePile, trade).
EconomyServices (Core econ transport + durable MarketStore/PileStore + the
bridge + the pack-content pool), attached via Server::with_economy (kept out
of `new`/`from_config` so existing tests build a DB-less Server; production
from_config attachment is the barrier step). Server::try_handle_economy
dispatches: sync handlers (credits/purchasegroup/store-buy/pack-open/
quick-sell/match) inline; async handlers (market list/query/buy/cancel,
move) on the bridge via owned `async move` blocks. build_content_pool
derives the resolvable FIFA∩Core candidate pool from Core content.
market.rs: FIX the load-bearing hazard the FakeEconomy tests missed — the
async market handlers call the BLOCKING reqwest Core client, which panics
(reqwest::blocking::wait::enter) when run while a Tokio runtime is entered.
off_runtime() hops each Core call to a fresh OS thread with no runtime
entered, so blocking is legal. handle_move_items resolver gains `+ Sync`
(future must be Send for the bridge).
tests/economy_integration.rs: economy_full_sequence_through_dispatch drives
the WHOLE cluster through the REAL Server dispatch + bridge against a live
in-process Core (seeded with fifa17 dev content: 100k coins + owned cards),
on a plain OS thread (direct bridge path), over the real blocking
HttpCoreClient — no fakes: Store BUY (pool draw + shape + debit 400 + mint 5),
credits, quick-sell (reverse-resolve + credit), match WIN (+400), market
list->query->buy->query(sold)->second-buy-fails(no double debit), cancel
(cancelled not buyable), move-items, then reopen the durable market/pile
stores from disk (sold + pile persist). Deterministic. start_core_seeded
loads fifa17 dev content so /collection renders real definitions.
Tests: host 68 lib (+4 bridge) + 2 economy_integration + 24 host_test, all
green; adapter unchanged-green; clippy -D warnings + fmt clean.
38 lines
1.9 KiB
TOML
38 lines
1.9 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"] }
|
|
|
|
[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"
|