OxL Справочник OxL
РусскийEnglish

src/cart/cart.oxl

oxl
use super.model.*
use super.config { Features }
use super.limits { CART_IDLE }

// Шардированный актор (V.5, §12.5): одна корзина на пользователя во всём кластере. Живёт на узле-владельце шарда userId;
// `var` сохраняются в журнал после каждого сообщения, неактивная корзина выгружается из памяти, но не теряется.
@idle(CART_IDLE)
pub actor Cart sharded by userId: UserId {
  var items: List<Item> = []

  // Сообщения обрабатываются строго по одному — гонок за items нет
  msg add(item: Item) -> () | CartFull {
    let max = Features.get().maxCart.get()
    if items.len() as u32 >= max { fail CartFull{ max } }
    items.push(item)
    ()
  }

  msg remove(sku: Sku) { items = items.filter(i => i.sku != sku) }

  // Копия содержимого: сама корзина остаётся у актора
  msg snapshot() -> CartSnapshot {
    CartSnapshot{ userId: userId, items: items.clone(),
      total: items.fold(Money.ZERO, (a, i) => a + i.price * (i.qty as i64)) }
  }

  msg clear() { items = [] }

  // Убирает из корзины только первые `n` позиций — те, что вошли в снимок заказа; добавленные после снимка остаются.
  // Вызывается из `checkout` с `await` (в Стандарте V.5 — `removeOrdered`): очистка в фоне гонялась бы со следующим запросом.
  msg removeOrdered(n: usize) {
    if n >= items.len() { items = [] }
    else { items = items.iter().skip(n).collect() }
  }
}

// Пользователь может работать только со своей корзиной; userId — ключ актора
policy Cart { allow * if caller.isUser("{userId}") }   // `isUser` takes the id as text (the JWT `sub`), as in `users` (DEVIATIONS.md #3)

Исходник: examples/shop/src/cart/cart.oxl