OxL Reference

src/search/search.oxl

oxl
// Поиск по каталогу и A/B-эксперимент «search v2» (ERRATUM V.5, DEVIATIONS.md #13, Стандарт §18.5, D-6866).
// Какой вариант получает запрос, решает `ab.variant(..)`: в `oxl test --kind ab` — по хешу пользователя на записанном трафике,
// в кластере — динамический Flag `oxl.ab.search v2`, который создаёт `oxl ab start "search v2"`.
use std.ab { ab }
use std.obs { metric }

// Позиция каталога: артикул, название и теги
data Entry {
  sku: str
  title: str
  tags: List<str>
}

fn catalog() -> List<Entry> => [
  Entry{ sku: "HAT-1", title: "wool hat", tags: ["winter", "head"] },
  Entry{ sku: "SHOE-7", title: "running shoes", tags: ["sport", "summer"] },
  Entry{ sku: "BAG-3", title: "laptop bag", tags: ["office", "travel"] },
  Entry{ sku: "SCARF-2", title: "silk scarf", tags: ["winter", "gift"] },
  Entry{ sku: "MUG-9", title: "travel mug", tags: ["travel", "kitchen"] },
]

// Вариант a (контроль): только по названию
pub fn searchByName(q: str) -> List<str> {
  let needle = q.lower()
  catalog().filter(e => e.title.contains(needle)).map(e => e.sku)
}

// Вариант b (кандидат): по названию и по тегам
pub fn searchByTag(q: str) -> List<str> {
  let needle = q.lower()
  catalog().filter(e => e.title.contains(needle) || e.tags.contains(needle)).map(e => e.sku)
}

// Тело rpc `Shop.search`: вариант выбирает эксперимент; поиск с результатом увеличивает метрику `search_found` (её сравнивает тест)
pub fn searchCatalog(q: str) -> List<str> {
  let found = match ab.variant("search v2") {
    "b" => searchByTag(q)
    _ => searchByName(q)
  }
  if !found.isEmpty() {
    metric.counter("search_found", help: "searches with at least one result").inc()
  }
  found
}

Source: examples/shop/src/search/search.oxl