Skip to content

Потокобезопасный индекс параметров, версия 0.12.1 - #50

Merged
nixel2007 merged 3 commits into
masterfrom
fix/thread-safe-index
Sep 29, 2026
Merged

nixel2007 merged 3 commits into
masterfrom
fix/thread-safe-index

Conversation

@sfaqer

@sfaqer sfaqer commented Sep 29, 2026

Copy link
Copy Markdown
Member

Проблема

ИндексЗначений.ИндексСформирован нигде не становился Истина, поэтому каждый вызов МенеджерПараметров.Параметр() заново строил весь плоский индекс в общее поле экземпляра. При параллельных вызовах из фоновых заданий потоки подменяли друг другу ИндексКоллекция и одновременно писали в один Соответствие (.NET Dictionary). Результат: InvalidOperationException, ArgumentException, NullReferenceException, пустые или чужие значения. Заодно это была проблема производительности: на каждое чтение перестраивался весь индекс, включая все переменные окружения у ENV-провайдера без префикса.

Решение

  • ИндексЗначений.Коллекция() строит индекс в локальную карту и публикует его одним присваиванием поля. После публикации карта не меняется, поэтому Значение() и ПолучитьИндекс() читают её без блокировок. Отдельного флага нет: всё состояние хранится в одной ссылке (Неопределено значит «коллекция не установлена»), так что ни флаг, ни порядок его записи не нужны.
  • МенеджерПараметров.Прочитать() больше не вызывает ИндексПараметров.Очистить(). Новый индекс строится полностью и только потом подменяет прежний, поэтому Параметр() можно вызывать параллельно с Прочитать(). Параллельные вызовы Прочитать() между собой не поддерживаются, это задокументировано.
  • Исключение «Коллекция индекса не установлена» раньше не доходило до вызывающего: Новый ИнформацияОбОшибке(...) в 2.x падает с «Конструктор не найден». Исправлено.
  • Документация: изменения соответствия из ПрочитанныеПараметры() не попадают в Параметр() до повторного Прочитать(). До 4103624 индекс тоже строился один раз при чтении, а видимость изменений появилась случайно вместе с пересборкой на каждый вызов.

Индекс строится один раз в Прочитать(), даже если Параметр() потом не вызывается.

Тесты

Новый файл tests/ИндексЗначений_test.os:

  • индекс строится один раз: ПолучитьИндекс() возвращает тот же объект, а после Коллекция()/Прочитать() — новый;
  • после Очистить() выдаётся корректное исключение;
  • 32 фоновых задания × 200 вызовов Параметр(): ни одного исключения, все значения верные;
  • то же параллельно с 50 вызовами Прочитать().

Без исправления падают все 5 тестов: в параллельных ошибки в 32 из 32 заданий. С исправлением на 2.3.0-dev и 2.2.0 все unit-тесты и BDD (14/14) проходят. Исключение — 2 теста Vault, которые так же падают на master локально: тестовый сервер на winow не стартует.

Вне рамок PR

  • Прочитать() по-прежнему очищает и заполняет ПрочитанныеПараметры на месте.
  • Коллекции, которые возвращает Параметр(), общие с исходными данными, и ОбъединитьПрочитанныеПараметры при нескольких провайдерах дописывает данные прямо в них.

🤖 Generated with Claude Code

sfaqer and others added 2 commits September 29, 2026 20:07
Индекс строился заново на каждый вызов Параметр() в общее поле экземпляра,
из-за чего параллельные вызовы из фоновых заданий падали с исключениями
Dictionary и возвращали пустые или чужие значения.

- ИндексЗначений строит индекс в локальную карту в Коллекция() и публикует
  его одним присваиванием поля; чтение идет без блокировок
- Прочитать() больше не очищает индекс заранее: новый индекс подменяет
  прежний только после полного построения
- исправлено исключение "Коллекция индекса не установлена"
  (Новый ИнформацияОбОшибке в 2.x не создается)
- документирован контракт многопоточности и ПрочитанныеПараметры()
- тесты на однократное построение и параллельное чтение

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coveralls

coveralls commented Sep 29, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 81.484% (+0.3%) from 81.167% — fix/thread-safe-index into master

- описание возвращаемого значения ОпубликованныйИндекс()
- объединены одинаковые ветки для Соответствие и Структура

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonar-openbsl-ru-qa-bot

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants