feat(fifa17): attach economy services in Server::from_config
Wire the PRODUCTION constructor so the economy authority is not test-only. Server::from_config now builds one process-lifetime AsyncBridge, opens the durable MarketStore + PileStore (paths from config), shares one HttpCoreClient as both CoreAccess and CoreEconomy, builds the content pool from Core, and attaches EconomyServices via with_economy. Stores/bridge are host-lifetime, never per request. - config.rs: required OPENFUT_MARKET_DB / OPENFUT_PILE_DB (durable file paths; must survive host restart — no temp defaults). - Fail-closed startup: a bridge/store that cannot initialize returns Err from from_config (host refuses to start) — NEVER a silent omission or a Python economy fallback. Test: from_config_constructs_and_serves_economy — builds the Server via the REAL from_config (disposable config: temp market/pile/identity + a catalog file derived from seeded content + the real tables dir) against a live Core, drives credits / purchasegroup / Store BUY / market list-query-buy through it, then rebuilds from the SAME config after a Core restart and asserts the balance persisted. host 71 lib + 3 integration + 24 host_test green; clippy/fmt clean.
This commit is contained in:
@@ -1829,19 +1829,55 @@ impl Server {
|
||||
let store = openfut_identity::JsonIdentityStore::open(&cfg.identity_store_path)
|
||||
.map_err(|e| format!("opening identity store {}: {e}", cfg.identity_store_path))?;
|
||||
let resolver = Arc::new(Fifa17IdentityResolver::new(catalog, Arc::new(store)));
|
||||
Ok(Server {
|
||||
core: Arc::new(HttpCoreClient::new(
|
||||
cfg.core_url.clone(),
|
||||
Fifa17WireItemIdPolicy::GAME,
|
||||
)),
|
||||
entities: Arc::new(entities),
|
||||
// One HTTP client, shared as both the read (`CoreAccess`) and the economy
|
||||
// (`CoreEconomy`) transport — the same Core, one connection policy.
|
||||
let client = Arc::new(HttpCoreClient::new(
|
||||
cfg.core_url.clone(),
|
||||
Fifa17WireItemIdPolicy::GAME,
|
||||
));
|
||||
let core: Arc<dyn CoreAccess> = client.clone();
|
||||
let econ: Arc<dyn CoreEconomy> = client;
|
||||
let entities = Arc::new(entities);
|
||||
|
||||
// Economy authority services: one runtime bridge + the two durable
|
||||
// host-owned SQLite stores (opened here, at host lifetime, NEVER per
|
||||
// request) + the content pool. A store that cannot open is a hard startup
|
||||
// failure — NEVER a silent omission or a Python economy fallback.
|
||||
let bridge = Arc::new(
|
||||
crate::async_bridge::AsyncBridge::new()
|
||||
.map_err(|e| format!("building economy runtime bridge: {e}"))?,
|
||||
);
|
||||
let market_path = cfg.market_db_path.clone();
|
||||
let market = Arc::new(
|
||||
bridge
|
||||
.block_on(async move { crate::market_store::MarketStore::open(&market_path).await })
|
||||
.map_err(|e| format!("opening market store {}: {e}", cfg.market_db_path))?,
|
||||
);
|
||||
let pile_path = cfg.pile_db_path.clone();
|
||||
let piles = Arc::new(
|
||||
bridge
|
||||
.block_on(async move { crate::pile_store::PileStore::open(&pile_path).await })
|
||||
.map_err(|e| format!("opening pile store {}: {e}", cfg.pile_db_path))?,
|
||||
);
|
||||
// Content pool from Core's current inventory (empty ⇒ Store fails closed,
|
||||
// never mints/debits — an honest degrade if Core is not yet seeded).
|
||||
let pool = Arc::new(build_content_pool(core.as_ref(), resolver.as_ref()));
|
||||
let economy = Arc::new(EconomyServices {
|
||||
econ,
|
||||
market,
|
||||
piles,
|
||||
bridge,
|
||||
pool,
|
||||
});
|
||||
|
||||
Ok(Server::new(
|
||||
core,
|
||||
entities,
|
||||
resolver,
|
||||
pass: Arc::new(PassClient::new(cfg.python_upstream.clone())),
|
||||
persona_id: cfg.persona_id,
|
||||
sessions: Arc::new(Mutex::new(SessionStore::new())),
|
||||
start: Instant::now(),
|
||||
economy: None,
|
||||
})
|
||||
Arc::new(PassClient::new(cfg.python_upstream.clone())),
|
||||
cfg.persona_id,
|
||||
)
|
||||
.with_economy(economy))
|
||||
}
|
||||
|
||||
/// Assemble the shared squad dependencies (Core access + the one production
|
||||
|
||||
Reference in New Issue
Block a user