Skip to content

[DISCO-4151] Merino: add client for wcs#7345

Open
tiftran wants to merge 9 commits intomainfrom
wcs
Open

[DISCO-4151] Merino: add client for wcs#7345
tiftran wants to merge 9 commits intomainfrom
wcs

Conversation

@tiftran
Copy link
Copy Markdown
Contributor

@tiftran tiftran commented Apr 30, 2026

This PR adds a new module to the merino crate that calls the Merino /api/v1/wcs endpoint
Also added a suggest subcommand to merino-cli for local testing.

Pull Request checklist

  • Breaking changes: This PR follows our breaking change policy
    • This PR follows the breaking change policy:
      • This PR has no breaking API changes, or
      • There are corresponding PRs for our consumer applications that resolve the breaking changes and have been approved
  • Quality: This PR builds and tests run cleanly
    • Note:
      • For changes that need extra cross-platform testing, consider adding [ci full] to the PR title.
      • If this pull request includes a breaking change, consider cutting a new release after merging.
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Changelog: This PR includes a changelog entry in CHANGELOG.md or an explanation of why it does not need one
    • Any breaking changes to Swift or Kotlin binding APIs are noted explicitly
  • Dependencies: This PR follows our dependency management guidelines
    • Any new dependencies are accompanied by a summary of the due diligence applied in selecting them.

@tiftran tiftran force-pushed the wcs branch 2 times, most recently from 0c1055a to ccb9dcc Compare April 30, 2026 17:46
Comment thread components/merino/src/worldcup/http.rs Outdated
Comment thread examples/merino-cli/src/main.rs Outdated
/// Fetch World Cup data
WorldCup {
/// OHTTP relay URL
#[arg(long, default_value = "https://ohttp-merino.mozilla.fastly-edge.com")]
Copy link
Copy Markdown

@annasob annasob May 1, 2026

Choose a reason for hiding this comment

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

Nan said no need for OHTTP since no search data is being passed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

right

@tiftran tiftran force-pushed the wcs branch 2 times, most recently from 1c41220 to fa10294 Compare May 1, 2026 18:37
@tiftran tiftran marked this pull request as ready for review May 1, 2026 19:03
@tiftran tiftran requested review from a team and annasob May 1, 2026 19:03
Copy link
Copy Markdown
Member

@gruberb gruberb left a comment

Choose a reason for hiding this comment

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

I would recommend these changes. Nothing functional, but would be cleaner. Knowing that we likely remove all of that again after the event.

Comment thread components/merino/src/worldcup/mod.rs Outdated
.base_host
.unwrap_or_else(|| DEFAULT_BASE_HOST.to_string());

let base_url = Url::parse(&format!("{}/api/v1/wcs/", base_host))?;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could add the base url as a const (in addition to the DEFAULT_BASE_HOST? Or just do DEFAULT_BASE_URL?

And then we can use this in the tests too (import it there) instead of having another hardcoded url.

Comment thread components/merino/src/worldcup/tests.rs Outdated
}"#;

const LIVE_RESPONSE: &str = r#"{
"current": [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Another little thing is to use a const ICON_URL_BASE: &'static str = "https://storage.googleapis.com/merino-images-prod/logos/" maybe for the logos?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

actually i guess if we're storing those responses in json files, we can't do this right?

pub teams: Option<String>,
}

pub trait HttpClientTrait {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

They are all the same. Can we collapse it into one make_request?

pub trait HttpClientTrait {
    fn make_request(&self, url: Url, params: WorldCupQueryParams) -> Result<Option<Response>>;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

makes sense

Comment thread components/merino/src/worldcup/mod.rs Outdated
}
}

pub fn get_teams(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could all just be make_request and then self.http_client.make_request?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I mean, if we want to hardcode the endpoint to prevent typos etc, we have to use a fixed url here for each of the requests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i kinda do want to leave it, so that the endpoint is hardcoded here. Yes this leaves to some duplication, but maybe okay since it won't be sticking around for long?

Comment thread components/merino/src/worldcup/mod.rs Outdated
/// Creates a new `WorldCupClient` from the given configuration.
#[uniffi::constructor]
#[handle_error(Error)]
pub fn new(base_host: Option<String>) -> ApiResult<Self> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should pass a WorldCupConfig here instead of a String. And I don't think it can be optional.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Suggest and CuratedRecommendations both have Option<String> and it defaults to the merino prod if it's not present, should I follow convention?

Comment thread components/merino/src/worldcup/tests.rs Outdated
Comment thread components/merino/src/worldcup/tests.rs Outdated
WorldCupClientBuilder::new().build().unwrap().base_url
}

struct FakeHttpClientSuccess;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FakeHttpClientSuccess, FakeHttpClientNoContent, FakeHttpClientServerError differ only in their return values. With the trait collapsed to just one method (from the comment earlier), they reduce to one parameterized fake:

struct FakeHttpClient(fn() -> Result<Option<Response>>);
impl http::HttpClientTrait for FakeHttpClient { ... }

Comment thread components/merino/src/worldcup/mod.rs Outdated
Copy link
Copy Markdown

@annasob annasob left a comment

Choose a reason for hiding this comment

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

Approving to clear my block

Comment thread components/merino/src/worldcup/mod.rs Outdated
pub use error::{ApiResult, Error, MerinoWorldCupApiError, Result};
pub use schema::{WorldCupConfig, WorldCupOptions};

pub(crate) const DEFAULT_BASE_URL: &str =
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not sure if this is the best way to make it accessible for test.rs?

@tiftran tiftran requested a review from gruberb May 6, 2026 06:47
@tiftran
Copy link
Copy Markdown
Contributor Author

tiftran commented May 6, 2026

Added the accept language header and a "language" param, will remove/edit once there's a decision on how we're passing locale

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants