Skip to content

fix(entities): пул сущностей на поток исполнения - #156

Open
sfaqer wants to merge 1 commit into
nixel2007:masterfrom
sfaqer:claude/thread-safety-v-entity-pool
Open

sfaqer wants to merge 1 commit into
nixel2007:masterfrom
sfaqer:claude/thread-safety-v-entity-pool

Conversation

@sfaqer

@sfaqer sfaqer commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Что чинит

Экземпляры прочитанных сущностей. Пул сущностей хранилища был один на все потоки: потоки получали один и тот же экземпляр строки и без согласования заполняли его поля. Для каждого дефекта сначала написан тест, красный на master, потом исправление.

Дефект Как проявлялся на master Исправление
Чтение в одном потоке перезаписывало поля экземпляра, с которым работает другой Поток правил прочитанный экземпляр и ещё не сохранил его, другой поток читал ту же строку — правка пропадала Пул сущностей у каждого потока свой
Разные потоки получали один экземпляр строки Экземпляр, прочитанный в фоновом задании, был тем же объектом, что и в основном потоке Тот же пул на поток: внутри потока экземпляр один, у другого потока свой
Экземпляр попадал в пул до заполнения, и другой поток дозаполнял его своим снимком строки Задание, остановленное на чтении ссылки посреди сборки автора, получало имя из снимка, который другой поток прочитал позже Чужой поток больше не видит экземпляр, который собирается

Как теперь

  • Пул — Соответствие в ТекущийПоток().Данные под ключом хранилища. Пишет и читает его только свой поток, поэтому блокировки нет.
  • Внутри потока на идентификатор один экземпляр и между вызовами, как раньше. Повторное чтение того же идентификатора заполняет поля этого экземпляра заново.
  • ХранилищеСущностей.Закрыть() и МенеджерСущностей.Закрыть() отбрасывают экземпляры всех потоков. Пул своего потока освобождается сразу, пулы других — при их следующем обращении к хранилищу (по номеру очистки, АтомарноеЧисло) или по завершении потока.

Что меняется снаружи

  • Разные потоки исполнения (фоновые задания, запросы веб-сервера) получают разные экземпляры одной строки.
  • Служебный ПолучитьПулСущностей() отдаёт Соответствие текущего потока вместо общей СинхронизированнаяКарта.
  • Пул долгоживущего потока растёт до закрытия менеджера.
  • Потерянное обновление это не лечит: из двух сохранений одной строки остаётся последнее. Оптимистическая блокировка (колонка версии) — отдельная задача. Описано в новом разделе «Экземпляры сущностей» в docs/ПотокобезопаснаяРаботаСБД.md.

Тесты

Новый набор ЭкземплярыСущностейВПотоках (InMemory):

  • ЧтениеВДругомПотокеНеЗатираетПравкуЭкземпляра;
  • ПотокиПолучаютРазныеЭкземплярыОднойСтроки;
  • ЧтениеПосредиСборкиВДругомПотокеНеСмешиваетСнимки — новая фикстура НаблюдательЗадержкиЧтения держит задание на вложенном чтении ссылки;
  • страховочный ОчисткаХранилищаОтбрасываетЭкземплярыДругихПотоков: зелёный и на master, мутант «без номера очистки» тест поймал.

Первые три на master красные.

Полный прогон:

  • OneScript 2.2.0, SQLite + PostgreSQL: 319 из 319;
  • 2.3.0-next+a02323a1, SQLite + PostgreSQL: 319 из 319;
  • 2.2.0, только PostgreSQL: 302 из 302.

🤖 Generated with Claude Code

Прочитанные сущности хранилище запоминает в пуле своего потока исполнения
(в данных потока), а не в одном пуле на все потоки. Внутри потока на
идентификатор по-прежнему один экземпляр, а разные потоки получают разные
экземпляры одной строки: чтение в одном потоке больше не стирает несохраненные
правки другого и не смешивает снимки строки, прочитанные в разное время.

ХранилищеСущностей.Закрыть() отбрасывает экземпляры всех потоков: пул своего
потока освобождается сразу, пулы других - при их следующем обращении к
хранилищу (по номеру очистки).

Потерянное обновление при двух сохранениях одной строки это не лечит:
остается сохраненное последним, это описано в документации.

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

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 1a441010-9404-40af-a09e-4ec7f56f8020

📥 Commits

Reviewing files that changed from the base of the PR and between 58e761e and 2c5863f.

📒 Files selected for processing (8)
  • docs/МенеджерСущностей.md
  • docs/ПотокобезопаснаяРаботаСБД.md
  • docs/ХранилищеСущностей.md
  • src/internal/Модули/РаботаСКоннекторами.os
  • src/Классы/МенеджерСущностей.os
  • src/Классы/ХранилищеСущностей.os
  • tests/fixtures/НаблюдательЗадержкиЧтения.os
  • tests/ЭкземплярыСущностейВПотоках.os
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant