Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ server:
# TestDetailedSearchFieldsMask for why name and user_ratings_total are
# deliberately absent (nothing reads them from a Details response; both
# arrive free with every Nearby/Text Search result).
# editorial_summary and photos were dropped 2026-08-13: nothing on the
# OfferBee wire (nearby-places, nearby-places-by-category, place-search,
# confirm) reads Summary or Photo, and editorial_summary is the lone
# Atmosphere-tier field — removing it drops every Details call one SKU tier.
detailed_search_fields:
- opening_hours
- formatted_address
- adr_address
- url
- editorial_summary
- photos
plan_solver:
same_place_dedupe_count_limit: 2
nearby_cities_count_limit: 3
Expand Down
11 changes: 7 additions & 4 deletions config_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import (
// path (both already arrive free with every Nearby/Text Search result), and
// user_ratings_total alone pulls the call into the Atmosphere tier. The AddUserRatingsTotal
// admin migration passes its own single-field list and is unaffected.
// - editorial_summary and photos must stay OUT (dropped 2026-08-13): nothing on the OfferBee
// wire reads Summary or Photo, and editorial_summary is the lone Atmosphere-tier field, so
// its absence drops every Details call one SKU tier. Photo backfill on place-search confirm
// becomes a no-op, which nothing consumes.
// - the remaining fields are load-bearing: opening_hours (open-now filtering),
// formatted_address/adr_address (display + address parsing), url (also the Details-freshness
// signal — see iowrappers/data_migrations.go detailsSourcedFields), editorial_summary (trip
// planner), photos (place photos + confirm gap-fill).
// signal — see iowrappers/data_migrations.go detailsSourcedFields).
func TestDetailedSearchFieldsMask(t *testing.T) {
raw, err := os.ReadFile("config/config.yml")
if err != nil {
Expand All @@ -33,12 +36,12 @@ func TestDetailedSearchFieldsMask(t *testing.T) {
fields[f] = true
}

for _, banned := range []string{"name", "user_ratings_total"} {
for _, banned := range []string{"name", "user_ratings_total", "editorial_summary", "photos"} {
if fields[banned] {
t.Errorf("detailed_search_fields contains %q, which no Details consumer reads — it only adds billing tier", banned)
}
}
for _, required := range []string{"opening_hours", "formatted_address", "adr_address", "url", "editorial_summary", "photos"} {
for _, required := range []string{"opening_hours", "formatted_address", "adr_address", "url"} {
if !fields[required] {
t.Errorf("detailed_search_fields is missing load-bearing field %q", required)
}
Expand Down
7 changes: 6 additions & 1 deletion planner/planner.go
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,12 @@ func (p *MyPlanner) getNearbyPlaces(ctx *gin.Context) {
Location: location,
Radius: radius,
MinNumResults: uint(limit),
DetailsLimit: limit,
// The notification path shows a handful of stores per brand, so
// Details (the dominant cost, one call per new place) is capped
// below the candidate pool. Without this, a widened limit (40)
// across a 25-brand request could buy up to 1000 Details calls
// on a cold cell.
DetailsLimit: min(limit, 10),
}
result := nearbyPlacesBrandResult{Brand: keyword, Places: []POI.Place{}}
places, searchErr := p.Solver.Searcher.NearbySearch(searchContext, searchReq)
Expand Down