-
Notifications
You must be signed in to change notification settings - Fork 2
Migration Guide
Welcome to the WarEra Python Client migration guide! Find your target version below to see what changes you need to make to upgrade.
Version 0.2.3 is a feature-rich upgrade bringing the Python wrapper to the absolute cutting edge, including massive new architectural controls over batching, caching, and concurrency.
If upgrading from 0.2.2, no code changes are required! Just bump your package version.
However, you can now take advantage of the following new architectural features:
- CancellationScope (AbortController Parity): You can now gracefully cancel complex async workflows or pagination loops. Background batch engines will automatically prune cancelled tasks before they are sent over the network!
-
Persistent Caching: The SWR Cache engine now supports pluggable
CacheBackendimplementations. You can natively persistgameConfigand static lookup data across bot restarts using the built-inSQLiteCacheBackend. -
Request Priority Queuing: You can tag requests with
priority=RequestPriority.HIGH. The batching engine will surgically slice these critical tasks into the very next physical HTTP chunk, bypassing massive background queues. -
Customizable Batch Limits: You can now safely customize the underlying HTTP chunk limits via
max_batch_sizeduring client instantiation, giving you strict memory control for IoT or constrained environments. -
Built-in Telemetry Hooks: You can pass a
TelemetryHooksobject to observe internal rate-limit sleep durations, chunk payload efficiencies, and cache hit ratios for Datadog/Prometheus tracking.
Version 0.2.2 introduces massive internal stability and memory-safety patches following a comprehensive architecture audit. The public API surface is completely backwards-compatible, but the underlying engines have changed.
If you are upgrading from 0.2.0 or 0.2.1, no code changes are required! Just bump your package version.
However, note the following behavioral improvements:
-
OOM Memory Protection: The background synchronous thread wrapper now utilizes backpressure on the generator queue. If you use
get_paginated(auto_items=True)in synchronous mode over thousands of items, it will no longer bloat your RAM. -
Cache Safety:
async_memoizenow enforces a strict 1000-item LRU cap, and properly hashes complex dictionary arguments to prevent cache collisions. -
Cursor Parsing: JS Date string truncation was rebuilt robustly (
split(" GMT")[0]) to prevent timezone parsing crashes on pagination endpoints. -
Batching Resilience: The
InvalidStateErrorrace conditions in_auto_batch_flushwere resolved, and rate-limit headers properly track out-of-order network responses.
If you are upgrading from 0.1.x, please read the v0.2.0 Migration Guide below as there were massive breaking changes to the pagination engines, including the removal of paginate() and auto_paginate=True in favor of get_paginated(auto_items=True) and collect_all().
Version 0.2.0 introduces a modernized Developer Experience (DX) focused on implicit performance and simpler syntax. We've introduced a global API module, a supercharged time-slicing pagination engine, and smart caching.
Here is what you need to know to upgrade your code from 0.1.x.
You no longer need to manually instantiate and manage WareraClient unless you specifically want to manage multiple sessions. The warera module itself now acts as the client.
Before:
import asyncio
from warera import WareraClient
async def main():
async with WareraClient() as client:
user = await client.user.get_by_id("123")After:
import asyncio
import warera
async def main():
user = await warera.user.get_by_id("123")If you need to set an API key dynamically, you can use warera.set_api_key("...") (or warera.sync.set_api_key("...")), or simply set the WARERA_API_KEY environment variable.
(Note: The old WareraClient context manager still exists and is fully supported if you prefer the classic approach).
The get_many() methods on all resources (e.g., user.get_many(), company.get_many()) have been updated. They now use the BatchSession engine internally to split huge lists of IDs into compliant chunks of 50 procedures, fetching them all concurrently over the network.
Before:
users = await client.user.get_many(["1", "2", "3", ...], batch_size=50)After:
# Pass 10,000 IDs if you want, it will automatically chunk and fire concurrently.
users = await warera.user.get_many(["1", "2", "3", ...])In 0.1.x, we relied heavily on generator loops. In 0.2.0, pagination has been modernized:
-
auto_items=True: To yield single items across pages, simply passauto_items=Trueto any paginated method. This replaces the oldpaginate()wrapper. (Note: The oldpaginate()wrapper andauto_paginate=Trueparameter have been fully removed in 0.2.0). -
collect_all(): Completely rewritten. It now uses a parallel time-slicing engine with synthetic cursors. Instead of fetching pages sequentially, it splits the history into chunks and fetches them all concurrently, resulting in a >5x speedup for massive datasets!
Usage:
# Async item generator
async for party in client.party.get_paginated(country_id="7", auto_items=True):
print(party.name)
# Collect all items instantly in parallel
all_parties = await client.party.collect_all(country_id="7")Warning
Extreme Throughput Caution: The collect_all and get_many engines default to an extreme concurrency of 500 (and time_slice_days=0.2) to perfectly saturate the 500 req/min API rate limit. While the client safely protects against 429 errors and DDoS mitigation logic by jittering bursts, this concurrency can cause 502 Bad Gateway errors on the API side if querying heavy endpoints (like thousands of transactions), or hit OS File Descriptor limits locally.
You can globally dial down the concurrency limit by setting the WARERA_MAX_CONCURRENCY environment variable (e.g. export WARERA_MAX_CONCURRENCY=50), or by overriding concurrency=100 and time_slice_days=1 directly in the collect_all method call.
Static resources like warera.game_config.get() or warera.country.get_all() are now cached using a highly optimized Stale-While-Revalidate (SWR) pattern. You don't need to wrap these calls in your own cache loops anymore; the SDK does it for you. It instantly serves stale data (if available) while firing a background task to refresh the cache seamlessly.
The client now defaults to HTTP/2. By keeping a single TCP connection alive and multiplexing requests, API round-trip times are significantly faster, dropping overhead massively compared to 0.1.x.
We've introduced complete visibility into the SDK's mechanics (conceptually mirroring tRPC's httpBatchLink and "Links" middleware):
-
Standard Logging: You can now enable
logging.getLogger("warera").setLevel(logging.DEBUG)to watch exactly when the engine queues procedures, flushes batches, hits cache (stale vs fresh), and automatically sleeps on rate limits. -
Configurable Batch Delays:
WareraClientnow accepts anauto_batch_delay(default: 5ms) allowing you to manually tune the batching collection window to your exact requirements. -
Event Hooks:
WareraClientnow exposesevent_hooks={"request": [...], "response": [...]}which perfectly matches the functionality of tRPC Links, allowing you to inject Prometheus metrics, datadog loggers, or raw JSON debuggers on every network call.
To achieve 100% architectural parity with the TypeScript wrapper's createRetryFetch, we've implemented an advanced HTTP Retry Engine directly into the core HttpSession.
If a request fails due to a transient network error or specific API response codes (408, 409, 425, 429, 500, 502, 503, 504), the client will automatically retry the request up to max_retries times. It leverages exponential backoff with uniform random jittering to prevent thundering herd problems.
You can completely control this via the WareraClient configuration:
client = warera.WareraClient(
max_retries=3,
initial_delay_ms=250,
max_delay_ms=5000,
backoff_multiplier=2.0,
jitter=True,
retryable_status_codes={408, 409, 425, 429, 500, 502, 503, 504}, # Customize which errors trigger a retry
headers={"X-My-Proxy": "1"} # You can now also inject custom headers globally!
)Previously, static resources returned by gameConfig.getGameConfig were lazily mapped to dict[str, Any]. We've eliminated this to provide strict static typings and IDE autocomplete support!
Over 75 nested structures (e.g., GameConfigBadges, UpgradeConfigBunkerLevel, ItemConcrete) have been natively generated from the TypeScript Responses.d.ts definitions.
config = await warera.game_config.get()
print(config.badge.coffee.reward) # Fully strictly typed and auto-completable!- action_log
- alliance
- article
- battle
- battle_loot_summary
- battle_order
- battle_ranking
- company
- country
- donation
- election
- event
- game_config
- game_stat
- government
- inventory
- item_trading
- mercenary_contract_auction
- mu
- mu_member
- party
- ranking
- region
- round
- search
- tournament
- transaction
- upgrade
- user
- work
- work_offer
- worker