feat: changed get time logic to approvers
This commit is contained in:
+105
@@ -0,0 +1,105 @@
|
||||
# План: обсуждение задачи
|
||||
|
||||
_Создано: 2026-08-12_
|
||||
|
||||
## Контекст
|
||||
Пишем сюда идею, договорённости и шаги, чтобы ничего не забыть.
|
||||
|
||||
## Идея (со слов пользователя)
|
||||
> Данные заявок лежат в списках SP Online. Т.к. рекомендуемый предел ~5000, а заявки
|
||||
> копятся бесконечно, придумать механизм «архивации»/шардинга: при достижении 5000
|
||||
> элементов заводить новый список с тем же именем + числовой постфикс (`— данные_2`),
|
||||
> и фронт начинает писать новые заявки туда.
|
||||
|
||||
## Важный факт (уточнение)
|
||||
- **5000 = List View Threshold** — лимит на строки, сканируемые ОДНИМ запросом, а НЕ на хранение.
|
||||
- Список SPO хранит **до 30 млн** элементов. «Переполнения» по хранению не будет.
|
||||
- Реальная проблема = запросы без индекса, сканирующие >5000 строк → throttling.
|
||||
Лечится индексами + фильтрацией, а не разбиением списка.
|
||||
|
||||
## Цена шардинга по счётчику (что ломается в нашем коде)
|
||||
- `myRequests.service` → чтение становится UNION по N шардам на каждый тип.
|
||||
- `requestCode.ts` → код `type-YYMM-itemId`, itemId в новом списке снова с 1 → дубли кодов.
|
||||
- Списки согласования растут ещё быстрее (строки маршрута) — их тоже шардить?
|
||||
- Провижининг схемы/индексов/прав (Sites.Selected) для каждого нового списка на лету.
|
||||
- Отчётность/поиск «за период» становятся кросс-списочными.
|
||||
|
||||
## Варианты (развилка)
|
||||
- **A. Индексы + пагинация (рекомендую как базу)** — индексируем RequestStatus/Created/Author,
|
||||
читаем через `.top()`+paging. Закрывает throughput-проблему полностью. Кода минимум.
|
||||
- **B. Архивация по статусу/дате** — закрытые заявки переносим в `...— архив`, активный список
|
||||
остаётся маленьким. Это «правильная» версия интуиции пользователя. Разгрузка без ломки кодов.
|
||||
- **C. Шардинг по 5000 (исходная идея)** — крайний вариант, только если реально упрёмся в десятки млн.
|
||||
|
||||
## ВЫБРАННОЕ НАПРАВЛЕНИЕ (после обсуждения)
|
||||
Причина тормозов подтверждена пользователем: слабый интернет (Казахстан) + список зависает.
|
||||
Есть мандат «держать ≤5000 элементов в списке, плодить новые списки».
|
||||
Решение = **C (шардинг) + обязательная пагинация**. Обе части нужны:
|
||||
- **Шардинг** ≤5000 на список — выполняет мандат / снимает threshold-throttling (ops).
|
||||
- **Пагинация + фильтр по индексу** — фронт НИКОГДА не качает весь список, только маленькую
|
||||
страницу (`.top(50)`, фильтр по Author/RequestStatus). Именно это убирает зависания на
|
||||
слабом канале. Без этой части шардинг сам по себе скорость НЕ спасёт (4999 строк грузятся
|
||||
так же долго, как 5000).
|
||||
|
||||
## Кто что создаёт (решено)
|
||||
- Создание шардов — **бэкенд-скрипт по расписанию** (НЕ фронт). Варианты хостинга:
|
||||
Azure Function (timer) / Azure Automation runbook (PnP.PowerShell) / Power Automate /
|
||||
cron на своём сервере (есть git.tnsu.kz → своя инфра). Auth: app-only (сертификат), Sites.Selected.
|
||||
- Плюсы: права на создание списков не на фронте; тяжёлый провижининг мимо слабого канала юзера;
|
||||
нет гонок (шард готовится заранее); переиспользуем существующий PnP-провижининг.
|
||||
|
||||
## Контракт бэк ↔ фронт: РЕЕСТР ШАРДОВ
|
||||
Маленький SP-список / config-элемент. На каждый тип заявки:
|
||||
`базовое имя`, `номер активного шарда`, `счётчик`, (для approval — свой активный/счётчик).
|
||||
- Бэкенд-джоб ОБНОВЛЯЕТ (создал шард → новый активный номер).
|
||||
- Фронт ЧИТАЕТ (активный список для записи + полный набор для чтения).
|
||||
|
||||
## Роли в коде фронта (обёртки, детали позже)
|
||||
- `resolveActiveList(type)` → активный список для записи; все `submit.ts` зовут её вместо
|
||||
хардкода `DATA_LIST_TITLE`.
|
||||
- `resolveAllShards(type)` → все шарды для чтения; запрос по каждому с фильтром + `.top()`,
|
||||
склейка маленьких кусков (быстро на слабом канале).
|
||||
- Порог переключения — 4900 (запас до 5000).
|
||||
- Коды: внести номер шарда (`type-YYMM-s2-itemId`), иначе itemId в новом списке снова с 1 → дубли.
|
||||
- Списки согласования шардить по СВОЕМУ счётчику (растут в 3-5 раз быстрее) — проектируем после данных.
|
||||
|
||||
## Открытые вопросы (для следующего обсуждения)
|
||||
1. Хостинг бэкенд-джоба: Azure Function / Automation / Power Automate / свой cron (git.tnsu.kz)? Что доступно и кто админит?
|
||||
2. Реестр шардов — отдельный SP-список или один JSON config-элемент? (склоняюсь к маленькому списку — виден в админке)
|
||||
3. ~~Формат кода с шардом?~~ РЕШЕНО: offset-схема (см. ниже).
|
||||
4. Согласование: шардим сразу вместе с данными или сначала только данные, approval потом?
|
||||
5. ~~Старые данные >5000 сейчас?~~ РЕШЕНО: таких списков нет, гринфилд. Разовая миграция НЕ нужна.
|
||||
Текущие списки = «шард №1». Настоящая архивация (прятать старые из выдачи) — опционально, потом.
|
||||
6. Прогноз объёма: заявок/месяц по каждому типу — чтобы понять реальную частоту переключений.
|
||||
|
||||
## Решения (зафиксировано)
|
||||
- Направление: шардинг + обязательная пагинация (обе части).
|
||||
- Создание шардов: бэкенд-скрипт по расписанию (app-only), НЕ фронт.
|
||||
- Стык бэк↔фронт: реестр шардов.
|
||||
- РЕЖИМ РАБОТЫ: сейчас ТОЛЬКО план и обсуждение. Код НЕ пишем без явного подтверждения пользователя.
|
||||
|
||||
### Код заявки: offset-схема (сквозная нумерация)
|
||||
- ВАЖНО: SP-шный `ID` мы НЕ контролируем — в каждом новом списке он всегда с 1. Нельзя заставить
|
||||
SP стартовать с 5001. Поэтому сквозную нумерацию делаем в НАШЕМ коде, не в SP ID.
|
||||
- Код = `type-YYMM-{offset + itemId}`, offset = сумма финальных счётчиков всех предыдущих шардов.
|
||||
- Шард 1: offset 0 → `hr-2608-1` … (совпадает с текущим форматом → обратная совместимость!)
|
||||
- Шард 2: offset 5000 → `hr-2608-5001` …
|
||||
- Уникальность гарантирована. Непрерывность не идеальна (удаления → дырки в SP ID), но это ок —
|
||||
важна уникальность, а не отсутствие пропусков.
|
||||
- Финальный счётчик закрытого шарда пишет бэкенд-джоб в реестр при переключении.
|
||||
|
||||
### «Мои заявки» — из ВСЕХ шардов
|
||||
- `resolveAllShards(type)`: опрос всех шардов, каждый с фильтром по Author + `.top()`, склейка+сортировка.
|
||||
- Трафик мал (с каждого шарда пара строк) → быстро на слабом канале.
|
||||
- Оптимизация на потом: при большом числе шардов читать по умолчанию только свежие, старые — по кнопке «Показать ещё».
|
||||
|
||||
## Шаги (черновик, не выполняем)
|
||||
- [ ] Закрыть открытые вопросы 1-6 (обсуждение)
|
||||
- [ ] Спроектировать схему реестра шардов
|
||||
- [ ] Спроектировать интерфейс `resolveActiveList` / `resolveAllShards` (без реализации)
|
||||
- [ ] Спроектировать бэкенд-джоб (псевдокод/алгоритм)
|
||||
- [ ] Только после «го» — реализация
|
||||
|
||||
## Заметки
|
||||
- Паттерн доступа сегодня: у каждой формы свой `DATA_LIST_TITLE`, доступ через
|
||||
`getSP().web.lists.getByTitle(...)` (см. `forms/*/submit.ts`, `load.ts`, `myRequests.service`).
|
||||
Reference in New Issue
Block a user