Usage Recording и Quota Management
Usage системата проследява колко време потребителите диктуват и управлява quota-та за free потребители. Работи както с автентикирани, така и с анонимни (само device ID) потребители.
Поток на записване
Endpoints
POST /usage/record (OptionalAuth)
Записва нова диктовка и връща актуалния quota статус.
Request:
{
"device_id": "DEVICE_HASH",
"duration_seconds": 15.5
}
Response: QuotaStatusResponse (виж по-долу)
Логика:
- Валидация:
duration_seconds > 0 - Ако потребителят е автентикиран:
MigrateDeviceToUser-- прехвърля всички анонимни usage_records от това устройство към потребителя - INSERT в
usage_records(сuser_idако е логнат, NULL ако не е) - UPDATE на кумулативните статистики в
usersтаблицата - UPSERT на
stats_aggregate(singleton с id=1) - Изчисляване и връщане на
QuotaStatusResponse
Всичко се изпълнява в единична транзакция за consistency.
GET /usage/quota-status (OptionalAuth)
Проверява текущия quota статус без да записва нова диктовка.
Query params: ?device_id=DEVICE_HASH
Response: QuotaStatusResponse
GET /stats/public (без автентикация)
Публична статистика за уеб сайта.
Response:
{
"total_users": 1234,
"total_dictation_hours": 567.89,
"total_typing_saved_hours": 2271.56,
"total_dictation_count": 45678
}
QuotaStatusResponse
{
"status": "active",
"used_seconds": 300.0,
"quota_seconds": 600.0,
"remaining_seconds": 300.0,
"cooldown_until": null,
"trial_ends_at": null,
"total_dictation_seconds": 1500.0,
"total_typing_saved_seconds": 6000.0
}
| Поле | Тип | Описание |
|---|---|---|
status | string | Един от: unlimited, trial, active, cooldown |
used_seconds | float | Използвани секунди в текущия цикъл |
quota_seconds | float | Общо позволени секунди за цикъла |
remaining_seconds | float | Оставащи секунди |
cooldown_until | string? | ISO 8601 datetime кога cooldown-ът приключва |
trial_ends_at | string? | ISO 8601 datetime кога trial-ът изтича |
total_dictation_seconds | float | Общо секунди диктовка (lifetime) |
total_typing_saved_seconds | float | Спестено време от типене (lifetime, x TypingRatio) |
Quota логика
Статуси
| Статус | Описание | Кога се случва |
|---|---|---|
unlimited | Без ограничения | Pro план |
trial | Trial период, без лимит | Нов потребител в рамките на TRIAL_DAYS дни |
active | Нормална работа с quota | Free потребител след trial |
cooldown | Временно блокиран | Free потребител, изчерпал quota-та |
Rolling Quota Algorithm (walkCycles)
Алгоритъмът обхожда всички usage records хронологично и поддържа текущ "цикъл":
Ключови характеристики:
- Quota-та е rolling, не calendar-based
- Cooldown се закръглява нагоре до най-близкия цял час (
roundUpToHour) - При изтекъл cooldown, записите след cooldown-а се преизчисляват за нов цикъл
Typing Ratio Multiplier
total_typing_saved_seconds = total_dictation_seconds * TYPING_RATIO
По подразбиране TYPING_RATIO = 4.0, което означава, че 1 секунда диктовка спестява приблизително 4 секунди типене. Използва се за маркетингови цели в публичната статистика и в клиента.
Device-to-User Migration
Когато анонимен потребител (само с device_id) се логне за първи път, MigrateDeviceToUser:
- Обновява всички
usage_recordsсdevice_id = Xиuser_id IS NULL->user_id = потребителя - Преизчислява
total_dictation_secondsиtotal_dictation_countза потребителя чрезSUMиCOUNTзаявки
Това гарантира, че анонимната usage история се запазва след логване.
Конфигурация
| Променлива | Default | Описание |
|---|---|---|
QUOTA_MINUTES | 10 | Quota в минути за free потребители per цикъл |
COOLDOWN_HOURS | 5 | Cooldown период в часове след изчерпване |
TRIAL_DAYS | 7 | Trial период в дни за нови потребители |
TYPING_RATIO | 4.0 | Множител за изчисляване на спестено време |
Prometheus Metrics
Usage handler-ът записва следните metrics:
usage_records_total-- counter за общ брой записани usage eventsusage_duration_seconds_total-- counter за общо записани секунди