[Easy] record quote events for streamed quotes - #4957
Conversation
|
Claude finished @fleupold's task in 2m 44s —— View job Review: record quote events for streamed quotes
Verdict: looks correct and well-tested — no changes requested. I traced the streaming path against the one-shot
One minor, non-blocking observation (no change needed): the two paths break exact ties differently — the one-shot sort keeps the first stage-order quote among equals, while the stream keeps the first-arrived. Since tied quotes rank equally this doesn't affect ranking correctness, only which estimator gets credited on an exact tie. |
| match best { | ||
| // The last improvement forwarded is the winner of the competition. | ||
| Some((name, estimate)) => { | ||
| let winner: PriceEstimateResult = Ok(estimate); | ||
| report_winner_by_name(&query, query.kind, name, &winner); | ||
| emit_winning_price_estimate_event(name, &query); | ||
| } | ||
| None => { | ||
| let terminal = results | ||
| .into_iter() | ||
| .max_by(|(_, a), (_, b)| { | ||
| compare_quote_result(&query, a, b, &context, self.verification_mode) | ||
| }); | ||
| match terminal { | ||
| Some((name, result)) => { | ||
| report_winner_by_name(&query, query.kind, name, &result); | ||
| yield result; | ||
| } | ||
| None => yield Err(unreasonable_estimates_error()), | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
nit: nested matches lean very far to the right which IMO makes reading the code harder. Feel free to ignore if you prefer the matches.
| match best { | |
| // The last improvement forwarded is the winner of the competition. | |
| Some((name, estimate)) => { | |
| let winner: PriceEstimateResult = Ok(estimate); | |
| report_winner_by_name(&query, query.kind, name, &winner); | |
| emit_winning_price_estimate_event(name, &query); | |
| } | |
| None => { | |
| let terminal = results | |
| .into_iter() | |
| .max_by(|(_, a), (_, b)| { | |
| compare_quote_result(&query, a, b, &context, self.verification_mode) | |
| }); | |
| match terminal { | |
| Some((name, result)) => { | |
| report_winner_by_name(&query, query.kind, name, &result); | |
| yield result; | |
| } | |
| None => yield Err(unreasonable_estimates_error()), | |
| } | |
| } | |
| } | |
| if let Some((name, estimate)) = best { | |
| // The last improvement forwarded is the winner of the competition. | |
| let winner: PriceEstimateResult = Ok(estimate); | |
| report_winner_by_name(&query, query.kind, name, &winner); | |
| emit_winning_price_estimate_event(name, &query); | |
| } else { | |
| let worst_error = results | |
| .into_iter() | |
| .max_by(|(_, a), (_, b)| { | |
| compare_quote_result(&query, a, b, &context, self.verification_mode) | |
| }); | |
| if let Some((name, result)) = worst_error { | |
| report_winner_by_name(&query, query.kind, name, &result); | |
| yield result; | |
| } else { | |
| yield Err(unreasonable_estimates_error()) | |
| } | |
| } |
| // Both quotes were forwarded, the slow one improved on the fast one. | ||
| assert_eq!(results.len(), 2); | ||
| assert_eq!(wins("stream-slow") - slow_before, 1); | ||
| assert_eq!(wins("stream-fast") - fast_before, 0); |
There was a problem hiding this comment.
| assert_eq!(wins("stream-fast") - fast_before, 0); | |
| assert_eq!(wins("stream-fast"), fast_before); |
8fcd90a to
5dc987a
Compare
Description
CompetitionEstimator::estimate_streamdoesn't report participating price estimates to our event bus and also doesn't populate any prometheus metrics.Streamed quotes therefore show up in the event bus only as a
quoteRequested/quoteComputedpair, with no competition behind them, which breaks anything that consumes the competition data (quote analytics, and the upcoming quote-rewards accounting that pays losing quotes).This makes the streaming path report the competition the same way the one-shot path does.
Changes
estimate_streamkeeps each estimator's name next to its future, publishes apriceEstimateevent for every successful answer as it arrives (sameemit_quote_eventhelper and same "only successful estimates" rule asestimates), and once every estimator has answered reports the final best as the winner:winningPriceEstimateevent plus thequeries_wonmetric.report_winneris split into the index lookup and a name-basedreport_winner_by_name, shared by both paths.How to test
New test
estimate_stream_counts_the_final_best_as_the_winnerchecks that only the estimator behind the last forwarded improvement gets the win.Manually: run the orderbook with an event bus configured, call
POST /api/v1/quote/stream, and observe onepriceEstimateper solver and onewinningPriceEstimateon the bus;competition_price_estimator_queries_wonincreases for the winning estimator.