feat(generator): добавлено опоздание заказов в слепках
- Зачем: - менти должен увидеть, как запоздавшая выгрузка меняет открытое окно, не подделывая аудит источника. - Что: - заказам назначена задержка D, D+1 или D+2 последним броском подпотока ORDERS. - назначенный планом заказ приезжает сразу, а Woven передаёт эту гарантию именованным полем. - обновлены документы, проверки границ механики и эталонные хеши слепков. - Проверка: - make lint, make typecheck и make test в generator: 436 тестов прошли. - make config-test: конфигурация прошла проверку. - world_live_day и следующий etl_pipeline перевели заказ 20260608-0001 из awaiting_order в match.
This commit is contained in:
1 parent
58e944aa87
commit
8db1c58c12
11 files changed
+186
-54
No files matched your search
@@ -68,6 +68,7 @@ def orders(events: day.Day) -> list[list[Any]]:
|
||||
int(theirs.outcome[number]),
|
||||
int(theirs.paid_after[number]),
|
||||
int(theirs.cancelled_after[number]),
|
||||
int(theirs.snapshot_delay[number]),
|
||||
]
|
||||
for number in range(len(theirs))
|
||||
]
|
||||
|
||||
@@ -87,6 +87,25 @@ def test_every_order_of_the_day_is_a_purchase_of_the_day(weekday: day.Day):
|
||||
)
|
||||
|
||||
|
||||
def test_an_assigned_order_never_waits_for_a_later_snapshot(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
):
|
||||
"""Гарантия плана сильнее опоздания: мост склейки приезжает сразу."""
|
||||
# Все неназначенные заказы опаздывают на два дня. Нулевую задержку после
|
||||
# такого броска могут получить только заказы, защищённые планом.
|
||||
monkeypatch.setattr(
|
||||
orders, "_SNAPSHOT_DELAY_CUMULATIVE", np.array([0, 0, 1], dtype=np.int64)
|
||||
)
|
||||
events = day.stream(CANONICAL_SEED, WEEKDAY)
|
||||
audience = plan.audience(CANONICAL_SEED, WEEKDAY)
|
||||
|
||||
promised = set(audience.person_id[audience.assigned_order].tolist())
|
||||
immediate = set(events.orders.user_id[events.orders.snapshot_delay == 0].tolist())
|
||||
assert promised
|
||||
assert immediate == promised
|
||||
assert (events.orders.snapshot_delay == 2).any()
|
||||
|
||||
|
||||
def dropped_line(client: list[tuple[Any, int]], order: list[tuple[Any, int]]):
|
||||
"""Единственный индекс, удалением которого корзина клиента даёт заказ."""
|
||||
for gone in range(len(client)):
|
||||
|
||||
@@ -176,6 +176,63 @@ def test_the_rows_go_in_the_order_of_birth(days: list[day_module.Day]):
|
||||
assert len(set(numbers)) == len(numbers)
|
||||
|
||||
|
||||
def test_lateness_changes_only_the_rows_present_in_a_snapshot(
|
||||
days: list[day_module.Day],
|
||||
):
|
||||
"""Неопоздавшие строки остаются прежними байтами и в прежнем порядке."""
|
||||
number = SHORT_WINDOW_DAY
|
||||
window = [today.orders for today in days[: number + 1]]
|
||||
eager = serialize.orders(
|
||||
[
|
||||
replace(rows, snapshot_delay=np.zeros_like(rows.snapshot_delay))
|
||||
for rows in window
|
||||
],
|
||||
number,
|
||||
)
|
||||
actual = serialize.orders(window, number)
|
||||
actual_ids = {json.loads(payload)["order_id"] for payload in actual}
|
||||
expected = [
|
||||
payload for payload in eager if json.loads(payload)["order_id"] in actual_ids
|
||||
]
|
||||
|
||||
assert len(actual) < len(eager)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_a_two_day_late_order_first_arrives_in_its_lived_state(
|
||||
days: list[day_module.Day],
|
||||
):
|
||||
"""Заказ δ = 2 пропускает D и D+1 и догоняет жизнь, не меняя `created_at`."""
|
||||
honest = days[0].orders
|
||||
target = 0
|
||||
delay = np.zeros_like(honest.snapshot_delay)
|
||||
delay[target] = 2
|
||||
cancelled_after = honest.cancelled_after.copy()
|
||||
cancelled_after[target] = 30 * 3600
|
||||
late = replace(
|
||||
honest,
|
||||
snapshot_delay=delay,
|
||||
cancelled_after=cancelled_after,
|
||||
)
|
||||
order_id = late.order_id[target]
|
||||
|
||||
for number in (0, 1):
|
||||
assert order_id not in {
|
||||
json.loads(payload)["order_id"]
|
||||
for payload in serialize.orders([late], number)
|
||||
}
|
||||
|
||||
arrived = {
|
||||
record["order_id"]: record
|
||||
for record in map(json.loads, serialize.orders([late], 2))
|
||||
}[order_id]
|
||||
created_at = np.datetime_as_string(
|
||||
late.created_at[target], unit="ms", timezone="UTC"
|
||||
)
|
||||
assert arrived["status"] == "cancelled"
|
||||
assert arrived["created_at"] == created_at
|
||||
|
||||
|
||||
def test_the_state_is_read_at_the_boundary_of_the_day(days: list[day_module.Day]):
|
||||
"""Дыхание окна: оплаченный назавтра заказ в сегодняшнем слепке `created`.
|
||||
|
||||
|
||||
Reference in new issue
Block a user