- Call from
handler
intodata_processing
withMatchInfoRequest
data - GET API data from aoe2net
- make all requests that are needed for getting all valuable information for matchinfo
- Add a language parameter to call from the frontend to use translations
- GET and CACHE (in-memory DB,
Arc<Mutex<T>>
) commonly used translations (ENG, ESP, GER, ITA, FRA, POR) at system startup and let them be updated every now and then- spawn another thread for this task and don't use the github one (client encapsulation, easier debugging)
- don't use static types for this, to be less error prone if AoE2net updates something at these endpoints, we don't want to have errors every ten minutes if something breaks
- GET json/yaml file(s) from github (periodically?) [teams, platforms, players]
- Sources:
- https://raw.githubusercontent.com/SiegeEngineers/aoc-reference-data/master/data/players.yaml
- https://raw.githubusercontent.com/SiegeEngineers/aoc-reference-data/master/data/platforms.json
- https://raw.githubusercontent.com/SiegeEngineers/aoc-reference-data/master/data/teams.json
- periodically:
- at the start of the server
- once every 10 minutes
- Sources:
- Merge various data sources into a
MatchInfo
datastructure for giving back to client- await json from polska for new matchinfo DS for merging/exposing to our frontend
- Q: What's the best way in Rust to automatically map Datastructures
- Sort the player vector for each team first for the requested player
on
vec[0]
- then the remaining players either by name or by rating. highest
rating after
vec[0] == requested player
- then the remaining players either by name or by rating. highest
rating after
- Add Daemon
- WIP Implement good error handling
- use crates error types for better
Error handling
e.g.reqwest::Error
- use
thiserror
in library part - use
eyre
consistently for results with reports in binary part - Q use
.map_err
(e.g. return HTTP status codes, other errors)- A We should return more warnings/errors in the
error message
field for frontend error handling
- A We should return more warnings/errors in the
- Handle errors that got bubbled up to the MatchInfoProcessor gracefully
and return a maximum of valuable information on the MatchInfo and the
errors to the client
- Send
log entry
to Client for better error handling on client-side - On
hard error
, no match_info but instead error status code (HTTP)
- Send
- handle
serde_json::Value::Null
errors better when parsing data fromaoe2.net
- use crates error types for better
- implement
todo!()
s - don't overwrite
aoc_ref_data
if not able to parse it in thread, so we have at least one working version - collect all
SoftFail
errors within each request to our API, collect them at the end inMatchInfoProcessor
and write them back toerror_message
inMatchInfoResult
- Add assertions to http requests: https://github.com/beltram/asserhttp
- implement functionality to download a specific match via
/api/match
for usage in test cases- create a command-line parameter for
export-test-data
example to run it with a specificmatchid
/match-uuid
(UUID is probably preferable because of validation withuuid
crate) - then run all other functions to download the resources need to answer with that specific request
- rebuild and export the MatchInfoRequest for a random player from it for test case usage of our normal functionality
- create a command-line parameter for
- implement useful tests/raise test-coverage to a (valuable) maximum
- put unit tests into the same file of the type they refer to
- use
claim
for tests
- Special cases done right? (talk through them together)
- Implement (integration) test cases for these
- Data structure does not match with data from aoe2net
- Q: take a look for a
serde
attribute to mark fields in structs that are not as important for our processing, so we don't throw a parsing error if non-essential fields don't match/exist - A: We only parse
Players
oflast_match
into some losely-typed datastructure for easier handling, the rest isserde_json::Value
and parsing on the run
- Q: take a look for a
- last_match == 404
- New players without ranking (as deranked, but less than 10 games played)
- Deranked players (have an empty
leaderboard
entry)- then we should use
ratinghistory
for the last data andrank=DR
- then we should use
- Coop games
- Game Type except RM (0) and DM (2)
- FFA with teams set to ’-1’
- Write functionality to save a set of JSON responses (also our own) to a file
to use them inside the integration tests and be able to update frequently
- Parse requests and use
wiremock
for HTTP-mocking and test requests made by theapi_handler
- Compare our parsed initial response (manually checked) with the one in memory from the offline data
- Parse requests and use
- Use https://crates.io/crates/walkdir for walking test directory tree
- Use https://crates.io/crates/automod for adding (regression) tests dynamically
-
Fix character escaping in e.g.
"name": "\"[RUS-F]GriN\""
-
Make error message more understandable for frontend:
"GenericResponderError": "Other ApiRequestError: HTTP-Client experienced an error: error decoding response body: EOF while parsing a value at line 1 column 0."
probably from
http: error: ConnectionError: ('Connection aborted.', RemoteDisconnected(' Remote end closed connection without response')) while doing a GET request to URL: http://127.0.0.1:8000/matchinfo?id_type=profile_id&id_number=224786&language=en&game=aoe2de
-
Investigate HTTPie errors for more edge cases
-
in case
team == -1
start setting from Team 1/2 not from the back (7/8)
- Migrate to clap v3 from structopt
- Parse
MatchInfoRequest
forexport-sample-data
andfull-integration
test fromron
file for ease of testing/exporting- create struct that contains a
MatchInfoRequest
and a folder-layout and for other useful/needed information so we can create different test cases easier forintegration
testing
- create struct that contains a
- Refactor both, parsing and mock binding logic in full integration test
- create only new clients for each new api-root not for each request to us
- Q: how can we make creating requests easier and less boilerplate? (trait
objects, etc.)
- Create API client struct that wraps
ApiRequests
andApiResponses
- Also think about the openAPI parsing and request generating logics for the future
-
parse_into::<T>
method forApiRequest
andFileRequest
-
ParsableRequest
trait
- Create API client struct that wraps
- async stuff done right?
- use https://docs.rs/reqwest/0.11.0/reqwest/struct.Url.html#method.join
for
base_path
and joining files for DS:reqwest::Url
- structured logging: use
tracing
crate instead oflog
and refactor accordingly- use tracing-tree for structured summaries of tracing
- Use a concurrent hashmap instead of a HashMap: https://crates.io/crates/dashmap
- (?) Migrate to Axum from warp
- Use RwLock instead of Mutex for non-blocking aoc-ref-data lookup with multiple readers
- Check value of https://crates.io/crates/indexmap for the player alias indexing
- Use
cow
for less cloning to satisfy the borrow checker - check where enums in parameters are more applicable (no stringly typed apis)
- no
self
onwith_
alternative constructors - having a struct for exporting/mocking/maintenance to spare parameters and get get rid of unnecessary boilerplate
- make use of conversion traits:
fn foo<P: Into<PathBuf>>(p: P)
- use case for enum with str representation?
- implement
FromStr
for types? https://doc.rust-lang.org/std/str/trait.FromStr.html - no stringly typed function parameters: https://hermanradtke.com/2015/05/06/creating-a-rust-function-that-accepts-string-or-str.html
- crossbeam-deque use case?
- parking_lot use for Mutex (faster)
-
impl Into<String>
for stringly-typed parameters, because we may not need a String but something that can be turned into one- if a conversion can fail we can do it with
impl TryInto<String>
- if a conversion can fail we can do it with
- Use
bail!
andensure!
macros fromanynhow
where applicable
- Create good base documentation
- Add more documentation
- Q: how is our backend reacting to 100+ concurrent API requests?
- implement benchmark getting all ’MatchInfoResult’s for the To100
- what architectural changes need to be made to support many clients on our api
- smoke test with https://github.com/tarekziade/salvo
- Use bencher for benchmarking features on stable
- Maybe criterion which is a more sophisticated alternative
- Can dig deeper after profiling with counts
- Use flamegraph. A very simple
and portable tool to understand where the time is spent in the application. For
more detailed info, try:
perf record -g --call-graph=dwarf /path/to/your/application
, then load it into Firefox Profiler.
- GET
last_match
foraoc-reference-data
profile ids in anotherthread
and save the content to aHashMap
-> for later subscriptions- if a
profile id
from this list asks for aMatchInfo
we can shorten the path/do less requests - new subscriptions that are not on
aoc-reference-data
can be made persistent within aron
file that gets parsed on startup -
active subscribed
profile ids get copied from thisHashMap
into anActiveSubs
-HashMap
where requests are made more frequently to check for changes and send out a `delta
- if a
- Add automatic translation of user facing strings with https://crates.io/crates/libretranslate
- Client: SUBSCRIBE lastmatch(player_id=197751)
- Server: CREATE Observable
- Server: SEND initial state to CLIENT
- Server: POLL AoE2.net / Caching
- Server: UPDATE Observable
- Server: ON UPDATE of Observable send PATCH with DELTA to CLIENT
- Client: UPDATE internal data structure with PATCH
- User database (PostgreSQL/MariaDB), user log-in and dashboard
- Transparency management in user dashboard