Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(buck2_common): don't overload the user with HTTP retry backoff warnings #342

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

thoughtpolice
Copy link
Contributor

@thoughtpolice thoughtpolice commented Jul 13, 2023

Summary: Another attempt at GH-316 after feedback given on GH-321 by @krallin. This introduces a new trait to dispatch these warnings, and two trait impls: one used in the materializer codepath that now writes buck events to the log, and another one used in the manifold client path to just warn to the console, like we do now.

Test Plan: Build a project that uses reindeer with buck2, as that causes a lot of warnings. Observe lots of warnings. Apply patches. Rebuild with new buck2. Observe no warnings. Run buck2 log show | grep HttpRequestRetried and see that all the new log events actually did get emitted and go where intended.

Fixes GH-316.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 13, 2023
@thoughtpolice thoughtpolice changed the title refactor(buck2_common): don't overload the user with possible HTTP refactor(buck2_common): don't overload the user with HTTP retry backoff warnings Jul 13, 2023
Summary: Used in an upcoming diff to replace noisy warnings on stdout.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Ia17005d526a72e0a444b713ebc93f200
@thoughtpolice
Copy link
Contributor Author

Actually, I have no idea why this isn't just a higher order function that's passed to http_retry? We don't need a trait at all?

Summary: NFC. This just sets up everything so that the normal HTTP materializer
and the Manifold client can have different retry warnings enabled in an upcoming
change.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: Iaac8ffce8ec20563216eaf4de1b98206
Summary: NFC. Wired up, but won't take effect yet.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: I9ccb6647aed663b6823ad9f42119f8e1
…Warning

Summary: NFC. Wired up, but won't take effect yet.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: I6d061db6956e2133e33a74d79bb2f583
Summary: This switches both the materializer and the manifold client to use the
new interface, all at once.

Signed-off-by: Austin Seipp <aseipp@pobox.com>
Change-Id: I6d061db6956e2133e33a74d79bb2f583
@thoughtpolice
Copy link
Contributor Author

Actually, I guess the trait isn't too bad, I just kind of hate the boilerplate-ness of this in particular, which we do three times here:

struct F {}

impl F {
    fn new() -> Self {
        Self {}
    }
}

But surely there's a shorter way to just make this impl one-shot on the struct declaration with a derive thingy? Rust programmers love those, I think.

I could also remove the Noop variant for the dispatch warning trait, though I'd have to rebase the history a bit, which is fine. I just wanted something to use when introducing the API patch-by-patch.

@stepancheg stepancheg requested a review from krallin July 14, 2023 19:50
@thoughtpolice
Copy link
Contributor Author

But surely there's a shorter way to just make this impl one-shot on the struct declaration with a derive thingy? Rust programmers love those, I think.

This is apparently the Default trait, so I can replace all these with that, I think.

Comment on lines +432 to +439
struct ManifoldDispatchableHttpRetryWarning {}

impl ManifoldDispatchableHttpRetryWarning {
pub fn new() -> Self {
Self {}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct ManifoldDispatchableHttpRetryWarning {}
impl ManifoldDispatchableHttpRetryWarning {
pub fn new() -> Self {
Self {}
}
}
struct ManifoldDispatchableHttpRetryWarning;

And then just do ManifoldDispatchableHttpRetryWarning instead of ManifoldDispatchableHttpRetryWarning::new ?

Comment on lines +58 to +66
/// No-op implementation of DispatchableHttpRetryWarning. This does nothing at
/// all when a retry occurs; useful for mock tests.
pub struct NoopDispatchableHttpRetryWarning {}

impl NoopDispatchableHttpRetryWarning {
pub fn new() -> Self {
Self {}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same as above)


pub async fn http_retry<Exec, F, T, E, R>(
url: &str,
dispatch_retry_warning: R,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) passing &R might make a bit more sense considering that' all the API requires

Comment on lines +53 to +55
/// Fire off a warning. This might go to the console, event log, or
/// some other place.
fn dispatch(&self, dur: &Duration, retries: usize, url: &str);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename retries -> attempts? The first time this function is called the value will be 1 so it's more accurately attempts than retries

impl DispatchableHttpRetryWarning for ManifoldDispatchableHttpRetryWarning {
fn dispatch(&self, backoff: &Duration, retries: usize, url: &str) {
tracing::warn!(
"HTTP request to {} failed; {} retries. Retrying in {} seconds",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see my comment below, it's not actually retries, it's attempts)

dispatcher.instant_event(event);
}
None => {
tracing::warn!("Failed to dispatch HttpRequestRetried event: {:?}", event)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here what we actually would like to call is this function:

pub fn broadcast_instant_event<E: Into<buck2_data::instant_event::Data> + Clone>(
    event: &E,
) -> bool {
    let mut has_subscribers = false;

    for cmd in ACTIVE_COMMANDS.lock().values() {
        cmd.dispatcher.instant_event(event.clone());
        has_subscribers = true;
    }

    has_subscribers
}

(as-is unfortunately the logging wouldn't work when using the deferred materializer)

This function lives in buck2_server, so what we need to do is allow this to be injected into the callsites.

Maybe the easiest way to do this is to simply have the HttpClient provide its logging method (because this is already threaded through to all the places you need it), via a method like:

trait HttpClient {
  ..

  fn retry_logger(&self) -> &dyn DispatchableHttpRetryWarning;
}

You probably should actually keep the "log to stderr" implementation as just the default implementation for this method on HttpClient. This way all you need to do is just wrap the client being constructed for the server with the event-logging code.

So, putting it all together, what we need to do is:

  • Move this code to buck2_server
  • Have it implement the broadcast
  • When we create the server's http client (in DaemonState::init_data), we wrap it with some new struct implementing HttpClient that uses the event-logging implementation
  • When we create ManifoldClient's http client, you inject the other one in
  • When calling http_retry you get the retry logging from HttpClient

I can also make some of those changes if you'd like, just let me know

@ndmitchell
Copy link
Contributor

@thoughtpolice - are you planning to follow up on this or should we close it?

@thoughtpolice
Copy link
Contributor Author

Yes, I haven't gotten back to this, but it still is on my radar and I'd like to finish it up at some point. But if someone else gets to it or whatnot, we can close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Warnings that occur when HTTP2 downloads are throttled are a little bit aggressive
4 participants