хранилище переехало с PocketBase на SQLite со своим каталогом файлов
- база своя: два пула, захват одним UPDATE ... RETURNING, шаги схемы на goose под файловым замком, одна миграция начальной схемы вместо семи прежних - транспорт переписан на net/http: свои слои, свой ограничитель частоты, отдача файла с проверкой владельца; панель /_/ и пространство /api/ исчезли - по находкам ревью: журнал не пишет путь под корнем приложения, ключ бюджета читается справа налево, узнавание известного идёт читающим пулом
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
перехода, неделимость захвата и срок его протухания, условие записи результата
|
||||
держателем захвата, нарастающая пауза перед повтором, число воркеров настройкой,
|
||||
журнал событий записи и молчание конвейера наружу: обращений к отправителю он не
|
||||
делает вовсе, и свой исход тот узнаёт опросом готовности.
|
||||
делает вовсе, и свой исход тот узнаёт карточкой записи.
|
||||
|
||||
Сознательно не описаны: освобождение ресурсов внешних клиентов и **какие отказы
|
||||
считаются приговором записи, а какие поводом к повтору**. Второе — не пробел
|
||||
@@ -20,6 +20,7 @@
|
||||
потому что требование без проверки — предположение, а не норма. Первая задача,
|
||||
которая трогает любое из перечисленного, дописывает его сюда.
|
||||
## Requirements
|
||||
|
||||
### Requirement: Пустой прогон воркера — не отказ
|
||||
|
||||
Воркер SHALL отличать «пригодной к работе записи сейчас нет» от отказа шага. На
|
||||
@@ -87,8 +88,9 @@
|
||||
|
||||
### Requirement: Захват задачи неделим
|
||||
|
||||
Захват записи воркером SHALL быть одним неделимым шагом хранилища: выбор
|
||||
подходящей записи и пометка её захваченной MUST происходить вместе.
|
||||
Захват записи воркером SHALL быть одним неделимым запросом к базе: выбор
|
||||
подходящей записи и пометка её захваченной MUST происходить вместе, одним
|
||||
оператором с возвратом.
|
||||
|
||||
Захват MUST возвращать **идентификатор записи и признак этого захвата**, а не
|
||||
перечень её колонок. Колонки записи шаг читает сам, обычным чтением. Иначе
|
||||
@@ -99,7 +101,8 @@
|
||||
**Признак захвата MUST быть значением, уникальным для каждого захвата**, а не
|
||||
признаком занятости. Условие записи результата сверяет именно это значение:
|
||||
захват, перевыданный другому — по протуханию срока или после того, как человек
|
||||
снял признак остановки в панели, — обязан обращать запись первого в отказ.
|
||||
снял признак остановки подкомандой оснастки, — обязан обращать запись первого в
|
||||
отказ.
|
||||
Условие, проверяющее лишь непустоту признака или срок, пропустило бы обоих, и
|
||||
два шага записали бы в одну запись по очереди, испортив её результат.
|
||||
|
||||
@@ -170,15 +173,19 @@
|
||||
|
||||
Шаг MUST записывать только те поля, которыми распоряжается сам. Запись он держит
|
||||
снимком с момента захвата и до записи — это часы, — и безусловная запись снимка
|
||||
стёрла бы всё, что владелец правил в панели за это время: молча, без строки в
|
||||
журнале и без отказа в панели. Владелец увидел бы успешное сохранение и был бы
|
||||
уверен, что правка на месте. Владелец записи, заголовок, краткое описание и темы
|
||||
стёрла бы всё, что владелец правил за это время: молча, без строки в журнале и
|
||||
без отказа тому, кто правил. Владелец записи, заголовок, краткое описание и темы
|
||||
конвейер MUST не трогать.
|
||||
|
||||
Возвращает остановленную запись в работу сегодня владелец сервиса подкомандой
|
||||
оснастки — своего экрана для этого у сервиса нет. Норму это не меняет: она
|
||||
написана про поля, а не про того, чьей рукой правка сделана, и переживёт
|
||||
появление экранов.
|
||||
|
||||
#### Scenario: Правка владельца пережила сохранение шага
|
||||
|
||||
- **GIVEN** шаг держит захваченную запись
|
||||
- **AND** владелец за это время изменил в панели поле, которого шаг не касается
|
||||
- **AND** владелец за это время изменил поле, которого шаг не касается
|
||||
- **WHEN** шаг записывает свой результат
|
||||
- **THEN** результат шага записан
|
||||
- **AND** правка владельца на месте
|
||||
@@ -346,10 +353,36 @@ MUST расти с числом её отказов до объявленног
|
||||
и машинный текст отказа.
|
||||
|
||||
Снятие признака SHALL возвращать запись в работу **с того рубежа, где она
|
||||
стояла**, и MUST сбрасывать число отказов, паузу **и время входа в рубеж**.
|
||||
Время входа сбрасывается по той же причине, что и остальные сторожа: запись,
|
||||
простоявшая остановленной дольше предела, иначе останавливалась бы снова первым
|
||||
же захватом, и перезапуск не работал бы вовсе.
|
||||
стояла**, и MUST сбрасывать **всё, чем прошлый прогон её удерживал**:
|
||||
|
||||
- признак остановки — время остановки, причину и машинный текст отказа;
|
||||
- признак захвата и срок его протухания;
|
||||
- число отказов;
|
||||
- паузу перед повтором;
|
||||
- время входа в рубеж.
|
||||
|
||||
Перечень назван целиком и в одном месте, потому что забытое поле не даёт ни
|
||||
отказа, ни строки в журнале. Оставленный признак захвата держит запись занятой до
|
||||
протухания срока и отдаёт её потом чужому шагу — тому, чей результат условен по
|
||||
прежнему значению. Оставленное время входа в рубеж останавливает запись снова
|
||||
первым же захватом, если остановленной она простояла дольше предела, и перезапуск
|
||||
не работает вовсе. Оставленные отказы и пауза откладывают первый же прогон на
|
||||
накопленный срок.
|
||||
|
||||
Возврат в работу MUST идти **через домен**: тот, кто его делает, называет запись,
|
||||
а поля выше сбрасывает домен одним действием. Правка колонок мимо домена
|
||||
повторяет перечень вторым местом, и второе место расходится с первым молча.
|
||||
|
||||
Возврат в работу MUST писать событие журнала записи с происхождением «человек».
|
||||
Иначе запись, побывавшая остановленной и вернувшаяся в работу, неотличима в
|
||||
журнале от записи, которую конвейер вёл без остановок, а происхождение события
|
||||
перестаёт различать что-либо: другого писателя, кроме конвейера, у журнала не
|
||||
остаётся.
|
||||
|
||||
Инструментом возврата сегодня служит подкоманда набора инструментов
|
||||
разработчика: панели у сервиса нет, а экраны владельца приносят отдельные задачи.
|
||||
Норма написана про поля и про домен, а не про инструмент, и появление экрана её
|
||||
не трогает.
|
||||
|
||||
Прежние состояния отказа и смерти MUST не заводиться заново: обе причины
|
||||
восстанавливаются одинаково — снятием признака, — и различие между ними
|
||||
@@ -389,6 +422,19 @@ MUST расти с числом её отказов до объявленног
|
||||
- **THEN** число отказов, пауза и время входа в рубеж сброшены
|
||||
- **AND** ближайший захват выдаёт запись, а не останавливает её снова
|
||||
|
||||
#### Scenario: Возврат в работу освобождает захват
|
||||
|
||||
- **GIVEN** запись остановлена, и признак прошлого захвата на ней стоит
|
||||
- **WHEN** признак остановки снимают
|
||||
- **THEN** признака захвата и срока его протухания на записи нет
|
||||
- **AND** ближайший захват выдаёт запись, не дожидаясь протухания прежнего срока
|
||||
|
||||
#### Scenario: Возврат в работу виден в журнале записи
|
||||
|
||||
- **GIVEN** запись остановлена
|
||||
- **WHEN** её возвращают в работу
|
||||
- **THEN** в журнале событий записи есть событие с происхождением «человек»
|
||||
|
||||
### Requirement: Время в рубеже ограничено
|
||||
|
||||
У аудиозаписи SHALL быть время входа в рубеж, и оно MUST ставиться только при
|
||||
@@ -608,8 +654,13 @@ MUST не быть привязаны к отдельному шагу: кажд
|
||||
|
||||
Шаг конвейера SHALL доводить запись до достигнутого рубежа и MUST не обращаться
|
||||
к отправителю вовсе — ни с готовым текстом, ни с сообщением о неудаче. Исход
|
||||
своей записи владелец узнаёт **карточкой записи** и в панели владельца сервиса;
|
||||
адрес карточки и содержимое ответа нормирует capability `archive`.
|
||||
своей записи владелец узнаёт **карточкой записи**; адрес карточки и содержимое
|
||||
ответа нормирует capability `archive`.
|
||||
|
||||
Владелец сервиса узнаёт исход журналом и журналом событий записи. Панели, где он
|
||||
видел бы то же строкой таблицы, у сервиса нет — она ушла вместе со встроенным
|
||||
хранилищем, и второго канала наблюдения это не отняло: журнал событий пишется
|
||||
по-прежнему, а читается запросом к базе, пока экрана нет.
|
||||
|
||||
Держатель нормы сменился вместе с убранным опросом готовности: прежде исход
|
||||
отдавал адрес опроса, нормированный capability `intake`, и адреса этого больше
|
||||
@@ -628,8 +679,8 @@ MUST не быть привязаны к отдельному шагу: кажд
|
||||
спрашивает, об остановке не узнаёт.
|
||||
|
||||
Записи, которой этот канал недоступен, не бывает: у каждой записи есть владелец,
|
||||
и карточка отдаёт ему её исход. Держится это обязательностью владельца в схеме
|
||||
хранилища — норму держит capability `storage`.
|
||||
и карточка отдаёт ему её исход. Держится это обязательностью владельца в схеме —
|
||||
норму держит capability `storage`.
|
||||
|
||||
#### Scenario: Готовый текст отправителю не уходит
|
||||
|
||||
@@ -644,4 +695,3 @@ MUST не быть привязаны к отдельному шагу: кажд
|
||||
- **WHEN** владелец записи спрашивает её карточку
|
||||
- **THEN** ответ несёт достигнутый рубеж, признак остановки и её причину
|
||||
- **AND** в журнале владельца сервиса есть запись об остановке с причиной
|
||||
|
||||
|
||||
Reference in New Issue
Block a user