fix(capital): регистрация долей Благороста при создании проекта по событию (не ждать крон) #151
Reference in New Issue
Block a user
Delete Branch "fix/capital-share-onproject-event"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Проблема
Доли пайщиков Благороста (
regshare) регистрировались в проект двумя путями:ProgramShareRegistrationSchedulerService(крон), иledger2::userwallets[w.cap.blago]— но он реагирует только на изменение баланса.Создание нового проекта баланс не меняет → wallet-листенер молчит, и наполнение нового проекта существующими пайщиками зависело только от крона. Если проект быстро прогнали
… → resultдо тика крона — пайщики в него не попадали. Откатresult → activeконтракт не допускает, поэтому доли в компоненте терялись безвозвратно.Инцидент: voskhod, компонент
011bcd92…(id 53) создан 2026-06-16 06:14 и за ~45 мин уведён вresult; в сегментах оказались только 2 автора, а 5 пайщиков с долями Благороста (ipesgnlxmnwx~17.1M,mrgpikzesygk,spnpcpshemqp,ndrlqjeptxhh,lfyoloxkxwjc) — нет.Что сделано
ProgramShareRegistrationOnProjectDeltaListenerнаdelta::capital::projects: как только проект оказывается в статусеactive— сразу регистрирует доли всех активных пайщиков. Вpendingне заводим — заход только в активные проекты; при переходеpending → activeпридёт новая дельта соstatus=active, на ней и зайдём. Неблокирующий (fire-and-forget, как wallet-листенер), промахи подбирает крон-бэкстоп.ProgramShareRegistrationService.syncProgramSharesForProject(coopname, project_hash)— обход пайщиков по одному проекту;syncContributorпереведён сProjectDomainEntity[]наprojectHashes: string[]. Тот же код-путь, что и обход по расписанию.findActiveProjects(общий путь крона и wallet-листенера) сужен доactive— pending больше не участвует нигде.if (user_shares != g.capital_contributor_shares)вupsert_contributor_segment— контракт это допускает), а также подбирает события, потерянные при downtime. Поэтому сносить его нельзя.Контракт
regshareоставлен пермиссивным (pending|active) — контроллер просто строже и заводит долю только в active.Тесты
tests/unit/capital/program-share-registration-on-project-delta.listener.test.ts— гейтинг: active → регистрирует; pending / result / present=false / чужой scope → нет; ошибка сервиса не пробрасывается. 6/6 зелёные локально (--runInBand).Без codegen
Изменения чисто backend-внутренние (NestJS листенер/сервис), GraphQL-схема не менялась → SDK regen не требуется.