Skip to content

fix(types): контракты обработчиков сервиса живут на типе самого сервиса - #4437

Merged
nixel2007 merged 2 commits into
developfrom
fix/service-module-types
Aug 10, 2026
Merged

fix(types): контракты обработчиков сервиса живут на типе самого сервиса#4437
nixel2007 merged 2 commits into
developfrom
fix/service-module-types

Conversation

@nixel2007

@nixel2007 nixel2007 commented Aug 10, 2026

Copy link
Copy Markdown
Member

Проблема

У модуля сервиса есть владелец — сам сервис, и обработчики объявлены только в нём. Синтакс-помощник этого не выражает. Сырые данные из HBK (8.3.26.1521, через bsl-context):

СправочникМенеджер.<Имя справочника>   | параметры типа: [Имя справочника]
Модуль Web-сервиса                     | параметры типа: []   член: EVENT <Имя обработчика>
Модуль HTTP-сервиса                    | параметры типа: []   член: EVENT <Имя обработчика>
Модуль сервиса интеграции              | параметры типа: []   член: EVENT <Имя обработчика полученного сообщения>

У справочников платформа параметризует имя типа и прямо пишет об этом в описании. У модулей сервисов параметризовано только имя члена, а тип один на вид сервиса. Это не потеря в bsl-context: BslContextPlatformTypesProvider берёт context.typeParameters() как есть, и у справочника параметр приходит.

Типа «сам сервис» в HBK тоже нет: есть СервисИнтеграцииМенеджер.<Имя сервиса интеграции>, КаналСервисаИнтеграцииМенеджер.<…>, WSСсылкаМенеджер.<Имя WS-Ссылки> — но ни WebСервисМенеджер.<…>, ни HTTPСервисМенеджер.<…>. К веб-сервису конфигурации из кода не обратиться, поэтому типа-значения у него нет; ОбъектМетаданных: WebСервис — это описание метаданных, а не сервис.

ServiceModuleEventRegistrar следовал HBK буквально: собирал обработчики всех сервисов конфигурации и материализовал их на одном типе, разрешая столкновения имён так:

Collectors.toMap(HandlerSpec::name, HandlerSpec::signature, (a, b) -> a)

Насколько это массово (ssl_3_1)

пар «сервис — операция» в веб-сервисах 143
различных имён обработчиков 47
имён, объявленных больше чем одним сервисом 41
имён, у которых наборы параметров различаются 16

Пример: СоздатьУзелОбмена в Exchange_3_0_1_1 принимает Parameters, в Exchange_3_0_2_1Parameters, Zone. Контракт доставался тому, чей объект метаданных попался раньше, а обработчики остальных сервисов объявлялись несоответствующими. Порядок обхода метаданных между запусками не гарантирован, поэтому и набор замечаний плавал: в замерах по ишью #4429 ровно эти строки расходились между прогонами.

Что сделано

На каждый сервис регистрируется свой тип модуля — Модуль Web-сервиса.Обмен — специализацией от HBK-шаблона, с операциями только этого сервиса и их настоящими параметрами. EventHandlerResolver.resolveOwnerType спрашивает сперва тип конкретного сервиса и лишь потом общий тип вида (запасной путь на случай, когда метаданные сервиса не прочитались).

Одинаково для всех трёх видов: Web-сервисы, HTTP-сервисы, сервисы интеграции.

Замеры на ssl_3_1

EventHandlerInvalidSignature
develop 557
ветка 519

Убрано 38, добавлено 0 — все убранные приходятся на обработчики, проверявшиеся по контракту чужого сервиса (WebServices/Exchange, EnterpriseDataUpload_1_0_1_1 и т. д.).

Тесты

Новые: ServiceModuleEventRegistrarTest — два сервиса с одноимённой операцией и разными параметрами сохраняют каждый свой контракт, на общий тип обработчики не попадают; в EventHandlerResolverTest — контракт берётся у своего сервиса, а не у чужого, и запасной путь на общий тип.

Правлены: три проверки в ConfigurationTypesProviderHelpersTest спрашивали члены у общего типа вида — теперь спрашивают у типа сервиса. Контракт переехал туда намеренно, это и есть суть правки.

Замечание на будущее: Модуль команды и Модуль бота тоже сидят на фиксированном типе, но у них имена событий не параметризованы (ОбработкаКоманды и пять событий бота), поэтому сталкиваться нечему — их не трогал.

Summary by CodeRabbit

  • Bug Fixes

    • Improved event handling for service modules by resolving handlers against the correct service-specific type.
    • Preserved distinct parameter contracts for same-named operations across different services.
    • Added fallback behavior to shared service types when a specialized type is unavailable.
    • Prevented handlers from being incorrectly shared between independent services.
  • Tests

    • Expanded coverage for web-service event resolution and independent service handler registration.

У модуля сервиса есть владелец — сам сервис, и обработчики объявлены только в нём.
Синтакс-помощник этого не выражает: у него один тип на вид сервиса
(«Модуль Web-сервиса») с единственным членом-шаблоном «<Имя обработчика>» и без
параметра в имени типа — в отличие от справочников, где параметризовано само имя
(«СправочникМенеджер.<Имя справочника>»). Регистратор следовал этому буквально и
складывал обработчики всех сервисов конфигурации на один тип.

На ssl_3_1 это 143 операции тринадцати веб-сервисов, схлопнутые в 47 членов: 41 имя
объявлено больше чем одним сервисом, а у 16 имён наборы параметров различаются —
у версий одного сервиса операции называются одинаково, но принимают разное. Побеждал
контракт того сервиса, что попался раньше, а обработчики остальных объявлялись
несоответствующими. Кто попадётся раньше, решал порядок обхода метаданных.

Теперь на каждый сервис регистрируется свой тип модуля («Модуль Web-сервиса.Обмен»)
специализацией от HBK-шаблона, с операциями только этого сервиса, а EventHandlerResolver
спрашивает сперва тип конкретного сервиса и лишь потом общий.

На ssl_3_1: EventHandlerInvalidSignature 557 → 519, ни одного нового; убранные 38 —
это обработчики, которые проверялись по чужому контракту.

Три проверки в ConfigurationTypesProviderHelpersTest спрашивали члены у общего типа
вида — они спрашивают их у типа сервиса: контракт переехал туда намеренно.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 67b52ddf-1dcb-4a05-a057-2fc66a782b6c

📥 Commits

Reviewing files that changed from the base of the PR and between cee0284 and 7427689.

📒 Files selected for processing (1)
  • src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ServiceModuleEventRegistrarTest.java

📝 Walkthrough

Walkthrough

Service event registration now creates metadata-qualified module types for each service. Event resolution checks these types before generic service types. Tests cover distinct operation contracts, generic fallback, and HTTP, Web, and integration service names.

Changes

Service-specific event contracts

Layer / File(s) Summary
Service-specific event type resolution
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/EventHandlerResolver.java, src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/EventHandlerResolverTest.java
EventHandlerResolver checks <fixed owner type>.<MDO name> before the generic fixed type. Web service tests cover specialized resolution and generic fallback.
Per-service handler registration
src/main/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ServiceModuleEventRegistrar.java, src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ServiceModuleEventRegistrarTest.java, src/test/java/com/github/_1c_syntax/bsl/languageserver/types/registry/ConfigurationTypesProviderHelpersTest.java
ServiceModuleEventRegistrar collects and deduplicates handlers per service, then registers them on specialized module types. Tests cover distinct operation parameters and HTTP, Web, and integration service type names.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant ServiceModuleEventRegistrar
  participant MetadataService
  participant TypeRegistry
  participant SpecializedServiceType
  ServiceModuleEventRegistrar->>MetadataService: collect handlers for one service
  ServiceModuleEventRegistrar->>TypeRegistry: resolve generic module type
  TypeRegistry->>SpecializedServiceType: create specialized type
  ServiceModuleEventRegistrar->>SpecializedServiceType: register handlers
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: service handler contracts are registered on each service's own type.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/service-module-types

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.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

 4 056 files   4 056 suites   50m 40s ⏱️
 4 210 tests  4 139 ✅  71 💤 0 ❌
25 260 runs  24 830 ✅ 430 💤 0 ❌

Results for commit cee0284.

*/
class ServiceModuleEventRegistrarTest {

private static final String WEB_SERVICE_MODULE = "Модуль Web-сервиса";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужны тесты так же на ХТТП сервисы и сервисы интеграций

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

Заодно замечания Sonar по этому файлу: лишний импорт, статический импорт verify вместо
полного имени, ссылка на метод вместо лямбды, слитые проверки одного предмета.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nixel2007

Copy link
Copy Markdown
Member Author

Спасибо, поправил.

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

По Sonar — все четыре замечания были в этом же тесте и устранены: лишний импорт TypeSet, полное имя org.mockito.Mockito.verify вместо статического импорта, лямбда вместо ссылки на метод ParameterDescriptor::name, две проверки одного предмета слиты в цепочку.

@sonarqubecloud

Copy link
Copy Markdown

@sfaqer sfaqer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nixel2007
nixel2007 merged commit 4681f74 into develop Aug 10, 2026
36 checks passed
@nixel2007
nixel2007 deleted the fix/service-module-types branch August 10, 2026 14:43
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.

2 participants