Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
774c7c8
Наблюдатели источника данных: SPI для трассировки и метрик
claude Sep 14, 2026
36552f6
Проверку реализации интерфейса делает только валидатор
claude Sep 14, 2026
66861d7
События транзакций живут стопкой, а не одной переменной
claude Sep 14, 2026
dfdc760
Событие захвата соединения начинается со входа в пул
claude Sep 14, 2026
c0dfe22
Событие освобождения соединения начинается со входа в пул
claude Sep 14, 2026
b1a9864
Задание в тесте запоминает ошибку фиксации, а не глотает ее молча
claude Sep 14, 2026
18bdd25
Нужно ли событие операции, решает одна проверка
claude Sep 14, 2026
95546d7
Тест ждет входа в закрытие соединения, а не события транзакции
claude Sep 14, 2026
492bb35
Событие операции завершается и тогда, когда освобождение упало
claude Sep 14, 2026
ccd58f2
Захват и возврат соединения под операцию - в своем модуле
claude Sep 14, 2026
25c4316
Тесты закрывают все созданные источники, а не последний
claude Sep 14, 2026
cbbb7d5
Наблюдателей не зовут из-под блокировки пула
claude Sep 15, 2026
0d55d9b
Возврат соединения умершего потока - тоже событие освобождения
claude Sep 15, 2026
e8e3bce
Поля захвата в документации отнесены к захвату
claude Sep 15, 2026
ab84124
Пул сущностей обновляется до возврата соединения
claude Sep 15, 2026
f183643
Неудачный возврат соединения не отменяет событие освобождения
claude Sep 15, 2026
01779dd
Отложенная рассылка описана со стороны наблюдателя
claude Sep 15, 2026
18cb438
Валидатор коннектора отрабатывает, пока не пройдет
claude Sep 15, 2026
20b9af9
Реестр наблюдателей снимает блокировку тем же способом, что и все
claude Sep 15, 2026
54f7733
Косвенные падежи валидатора - в словарь BSL LS
claude Sep 15, 2026
7721507
Наблюдателю сказано не трогать пул
claude Sep 15, 2026
073b38c
Ожидающих считаем по живым заявкам, а не по длине очереди
claude Sep 15, 2026
dfaab8d
Убрана строка про менеджер из параметров соединения
claude Sep 15, 2026
8ac8907
Комментарии интерфейсов приведены в соответствие с кодом
claude Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bsl-language-server.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"listOfIncorrectFirstSymbol": ";|,\\s*\\S+"
},
"Typo": {
"userWordsToIgnore": "переиспользование,Переиспользование,переиспользования,Переиспользования,переиспользованию,Переиспользованию,переиспользованием,Переиспользованием,переиспользовано,Переиспользовано,переиспользовать,Переиспользовать,переиспользует,Переиспользует,переиспользуется,Переиспользуется,переиспользуются,Переиспользуются"
"userWordsToIgnore": "Фикстуры,фикстуры,Валидатор,валидатор,валидатора,Валидатора,валидатором,Валидатором,переиспользование,Переиспользование,переиспользования,Переиспользования,переиспользованию,Переиспользованию,переиспользованием,Переиспользованием,переиспользовано,Переиспользовано,переиспользовать,Переиспользовать,переиспользует,Переиспользует,переиспользуется,Переиспользуется,переиспользуются,Переиспользуются,Переподписывающийся,переподписывающийся"
}
}
}
Expand Down
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* <a href="#entity-active-record">Активная запись</a>
* <a href="#entity-repository">Работа через ХранилищеСущностей</a>
* <a href="#transactions">Работа с транзакциями</a>
* <a href="#observers">Наблюдатели источника данных</a>
* <a href="#annotations">Система аннотаций для сущностей</a>
* <a href="#annotation-entity">Сущность</a>
* <a href="#annotation-id">Идентификатор</a>
Expand Down Expand Up @@ -394,6 +395,49 @@
МенеджерСущностей.ЗафиксироватьТранзакцию();
```

<a id="observers" />

## Наблюдатели источника данных

Источник данных, с которым работает менеджер сущностей, сообщает зарегистрированным наблюдателям
обо всем, что с ним происходит: об операциях (Сохранить, Получить, Удалить и других), запросах к
СУБД, захвате и освобождении соединений и транзакциях. Каждое событие приходит наблюдателю дважды -
до выполнения и после - одним объектом `СобытиеИсточникаДанных`, в котором после выполнения есть
длительность, ошибка и результат. На этом строятся телеметрия, журнал медленных запросов, подсчет
обращений к БД в тестах.

Наблюдатель объявляет интерфейс `НаблюдательИсточникаДанных` аннотацией на конструкторе и
реализует два метода:

```bsl
&Реализует("НаблюдательИсточникаДанных")
Процедура ПриСозданииОбъекта()
КонецПроцедуры

Процедура ПередСобытием(Событие) Экспорт
КонецПроцедуры

Процедура ПослеСобытия(Событие) Экспорт
Если Событие.Вид() = ВидыСобытийИсточникаДанных.Запрос() И Событие.Длительность() > 100 Тогда
Сообщить(СтрШаблон("Медленный запрос к %1: %2 мс", Событие.ИмяТаблицы(), Событие.Длительность()));
КонецЕсли;
КонецПроцедуры
```

Регистрируется наблюдатель на источнике данных, а менеджер создается из источника и отдает
наблюдателю все, что с источником происходит: операции самого менеджера, его хранилищ сущностей
и активной записи, запросы, соединения и транзакции.

```bsl
Источник = Новый ИсточникДанных("Основной", Тип("КоннекторSQLite"), СтрокаСоединения);
Источник.ДобавитьНаблюдателя(Новый МедленныеЗапросы);
МенеджерСущностей = Новый МенеджерСущностей(Источник);
```

Виды событий, их поля, поведение при ошибках и в нескольких потоках, а также поддержка
наблюдателей в собственном коннекторе описаны в разделе
[Наблюдатели источника данных](docs/Наблюдатели.md).

<a id="annotations" />

## Система аннотаций для сущностей
Expand Down Expand Up @@ -528,6 +572,8 @@

Например, `КоннекторJSON` не умеет работать с транзакциями, однако, он имеет соответствующие методы, выводящие диагностические сообщения при их вызове.

Коннектор **может** дополнительно реализовать интерфейс [`НаблюдаемыйКоннектор`](docs/НаблюдаемыйКоннектор.md): тогда наблюдатели источника данных получают события его запросов к СУБД и описание соединения. Встроенные коннекторы реализуют оба интерфейса. Коннектор без второго интерфейса работает как раньше.

> Важно!

Менеджеры и хранилища сущностей одного источника данных собственных коннекторов не держат: они берут соединения из общего пула этого источника. Тип, строка соединения и параметры коннектора задаются при создании ИсточникаДанных.
Expand Down Expand Up @@ -646,14 +692,18 @@
* [`ОбъектМодели`](src/Классы/ОбъектМодели.os),
* [`ЭлементОтбора`](src/Классы/ЭлементОтбора.os);
* [`ЭлементПорядка`](src/Классы/ЭлементПорядка.os);
* [`НаблюдательИсточникаДанных`](src/Классы/НаблюдательИсточникаДанных.os);
* [`СобытиеИсточникаДанных`](src/Классы/СобытиеИсточникаДанных.os);
* значения модулей-перечислений:
* [`ТипыКолонок`](src/Модули/ТипыКолонок.os),
* [`ТипыПодчиненныхТаблиц`](src/Модули/ТипыПодчиненныхТаблиц.os),
* [`ВидСравнения`](src/Модули/ВидСравнения.os);
* [`ВидСравнения`](src/Модули/ВидСравнения.os),
* [`ВидыСобытийИсточникаДанных`](src/Модули/ВидыСобытийИсточникаДанных.os);
* состав и параметры аннотаций сущностей;
* методы ["активной записи"](docs/АктивнаяЗапись.md) сущности;
* для Major.Connector:
* все публичные методы класса [`АбстрактныйКоннектор`](src/Классы/АбстрактныйКоннектор.os) и их сигнатуры;
* все публичные методы необязательного интерфейса [`НаблюдаемыйКоннектор`](src/Классы/НаблюдаемыйКоннектор.os) и их сигнатуры, а также методы `НачатьЗапрос` и `ЗавершитьЗапрос` реестра наблюдателей, который коннектор получает в `УстановитьНаблюдателей`;
* все публичные непомеченные как "нестабильные" (`@unstable`) методы классов:
* [`МодельДанных`](src/Классы/МодельДанных.os),
* [`ОбъектМодели`](src/Классы/ОбъектМодели.os),
Expand All @@ -663,6 +713,7 @@
* значения модулей-перечислений:
* [`ТипыКолонок`](src/Модули/ТипыКолонок.os),
* [`ТипыПодчиненныхТаблиц`](src/Модули/ТипыПодчиненныхТаблиц.os),
* [`ВидСравнения`](src/Модули/ВидСравнения.os).
* [`ВидСравнения`](src/Модули/ВидСравнения.os),
* [`ВидыСобытийИсточникаДанных`](src/Модули/ВидыСобытийИсточникаДанных.os).

> To be continued...
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
* [ОбъектМодели](ОбъектМодели.md)
* [ЭлементОтбора](ЭлементОтбора.md)
* [ЭлементПорядка](ЭлементПорядка.md)
* [НаблюдательИсточникаДанных](НаблюдательИсточникаДанных.md)
* [НаблюдаемыйКоннектор](НаблюдаемыйКоннектор.md)
* [СобытиеИсточникаДанных](СобытиеИсточникаДанных.md)

### Перечисления

* [ВидСравнения](ВидСравнения.md)
* [ВидыСобытийИсточникаДанных](ВидыСобытийИсточникаДанных.md)
* [ТипыКолонок](ТипыКолонок.md)
* [ТипыПодчиненныхТаблиц](ТипыПодчиненныхТаблиц.md)

### Прочее

* [Потокобезопасная работа с БД](ПотокобезопаснаяРаботаСБД.md)
* [Наблюдатели источника данных](Наблюдатели.md)
65 changes: 65 additions & 0 deletions docs/ВидыСобытийИсточникаДанных.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## ВидыСобытийИсточникаДанных

Виды событий, которые источник данных отдает наблюдателям, см. `Вид()` у
[СобытиеИсточникаДанных](СобытиеИсточникаДанных.md). Значения отдаются функциями, а не экспортными
переменными, чтобы их нельзя было изменить извне. Наблюдатель сравнивает вид события с ними,
а не со строковыми литералами:

```bsl
Если Событие.Вид() = ВидыСобытийИсточникаДанных.Запрос() Тогда
```

### Операция

```bsl
// Операция менеджера или хранилища: Сохранить, Получить, Удалить и другие.
//
// Возвращаемое значение:
// Строка - Вид события операции.
//
Функция Операция() Экспорт
```

### Запрос

```bsl
// Запрос коннектора к СУБД: SELECT, INSERT, DELETE, CREATE TABLE, BEGIN, COMMIT, ROLLBACK.
//
// Возвращаемое значение:
// Строка - Вид события запроса.
//
Функция Запрос() Экспорт
```

### Соединение

```bsl
// Захват и освобождение соединения пула: Занять, Освободить.
//
// Возвращаемое значение:
// Строка - Вид события соединения.
//
Функция Соединение() Экспорт
```

### Транзакция

```bsl
// Транзакция потока исполнения от начала до исхода.
//
// Возвращаемое значение:
// Строка - Вид события транзакции.
//
Функция Транзакция() Экспорт
```

### Виды

```bsl
// Все виды событий в порядке объявления.
//
// Возвращаемое значение:
// ФиксированныйМассив из Строка - Операция, Запрос, Соединение, Транзакция.
//
Функция Виды() Экспорт
```
50 changes: 50 additions & 0 deletions docs/ИсточникДанных.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@

```bsl
Источник = Новый ИсточникДанных("Основной", Тип("КоннекторPostgreSQL"), СтрокаСоединения, , 20);
Источник.ДобавитьНаблюдателя(Новый МойНаблюдатель);

МенеджерСущностей = Новый МенеджерСущностей(Источник);
```

Реестр наблюдателей общий у источника, его пула и всех менеджеров, созданных из него, см.
[Наблюдатели источника данных](Наблюдатели.md).

### ПриСозданииОбъекта

```bsl
Expand Down Expand Up @@ -150,3 +156,47 @@
//
Функция ПулСоединений() Экспорт
```

### ДобавитьНаблюдателя

```bsl
// Регистрирует наблюдателя источника данных.
//
// Наблюдатель получает события всех операций, запросов, соединений и транзакций каждого
// менеджера, созданного из этого источника: самого менеджера, его хранилищ сущностей и
// Active Record. Реестр общий у источника и его менеджеров, поэтому регистрировать можно
// и после создания менеджера. См. интерфейс НаблюдательИсточникаДанных и класс
// СобытиеИсточникаДанных.
//
// Параметры:
// Наблюдатель - Произвольный - Объект с аннотацией &Реализует("НаблюдательИсточникаДанных") на конструкторе,
// реализующий этот интерфейс. Неполная реализация отвергается при регистрации.
//
// Пример:
// Источник.ДобавитьНаблюдателя(Новый МойНаблюдатель);
//
Процедура ДобавитьНаблюдателя(Наблюдатель) Экспорт
```

### УдалитьНаблюдателя

```bsl
// Снимает наблюдателя источника данных с регистрации.
//
// Параметры:
// Наблюдатель - Произвольный - Ранее зарегистрированный наблюдатель. Незарегистрированный пропускается.
//
Процедура УдалитьНаблюдателя(Наблюдатель) Экспорт
```

### Наблюдатели

```bsl
// @internal
// Реестр наблюдателей источника: источник передает его своему пулу соединений.
//
// Возвращаемое значение:
// НаблюдателиИсточникаДанных - Реестр наблюдателей.
//
Функция Наблюдатели() Экспорт
```
5 changes: 3 additions & 2 deletions docs/МенеджерСущностей.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
// Конструктор объекта МенеджерСущностей.
//
// Менеджер создается из источника данных и берет соединения из его пула: все менеджеры одного
// источника делят соединения и транзакции потоков. Параметры соединения задает источник, а его
// временем жизни управляет тот, кто источник создал.
// источника делят соединения, транзакции потоков и наблюдателей. Параметры соединения задает
// источник, а его временем жизни управляет тот, кто источник создал.
//
// Параметры:
// ИсточникДанных - ИсточникДанных - Источник данных, из которого создается менеджер.
//
// Пример:
// Источник = Новый ИсточникДанных("Основной", Тип("КоннекторSQLite"), СтрокаСоединения);
// Источник.ДобавитьНаблюдателя(Новый МойНаблюдатель);
// МенеджерСущностей = Новый МенеджерСущностей(Источник);
//
Процедура ПриСозданииОбъекта(Знач ИсточникДанных)
Expand Down
Loading
Loading