Event Contract: pin.selections.selection-created (SelectionCreatedKafkaEvent)
Версионируемый контракт интеграционного события «подборка создана». Consumer-документы ссылаются сюда,
не переописывая payload. Дом полей-источников — entity: Selection.
Назначение
Фиксирует создание подборки владельцем — вручную (Source = Manual) или из текущего избранного
(Source = Favorites) — и даёт user-activity (модуль actions, ADR-0054) факт для ActionEvent
«создал подборку», который через поток user-activity → crm виден агенту в карточке лида (создание
подборки — сильный сигнал вовлечённости инвестора). Состав (PropertyObjectId-список) и комментарии в
событие не входят — потребителю достаточно факта и счётчика, состав читается API по id.
Metadata
| Поле | Значение |
|---|---|
| Event type | pin.selections.selection-created |
| Topic | pin.selections.selection-created.v1 |
| Partitions / key | 3 партиции (низкий объём: ≤ 100 подборок на владельца, INV-SEL-007; ADR-0056) / key = AggregateId = SelectionId |
| ContractVersion | 1 |
| Producer | selections: POST /selections и POST /selections/from-favorites |
| Owning team | PIN Engagement |
| Статус | draft |
Событие публикуется атомарно с созданием подборки (корень + элементы — граница агрегата): пока подборка не зафиксирована, событие не отправляется потребителям; после фиксации — доставляется гарантированно (at-least-once). Ключ агрегата —
SelectionId, тип агрегата —Selection.
Payload SelectionCreatedKafkaEvent
Источники полей — entity: Selection (раздел «Доменные и интеграционные
события»).
| Поле | Тип | Обязательность | Источник (поле агрегата) | Compatibility | Описание |
|---|---|---|---|---|---|
SelectionId | Guid | Да | Selection.Id | Immutable | Идентификатор подборки (= AggregateId, = Kafka key). |
OwnerUserId | Guid | Да | Selection.OwnerUserId | Immutable | Владелец (инвестор или агент). Гость подборки не создаёт — поле не nullable (в отличие от избранного). |
Title | string | Да | Selection.Title | Additive only | Название (1..256) — для читаемого текста ActionEvent («создал подборку „Видовые у моря“»). |
Source | string (enum SelectionSource) | Да | Selection.Source | Additive only (новые значения) | Manual / Favorites — как создана (текстовая сериализация enum). |
ItemsCount | int | Да | Selection.Items.Count после создания | Additive only | Число объектов недвижимости в подборке на момент создания (0..200, INV-SEL-004). |
OccurredAt | DateTimeOffset | Да | Selection.CreatedAt | Immutable | Момент создания (дублирует время события). |
В payload не входят: PublicCode (публичная ссылка — не дело ленты действий; выдаётся API
владельцу), Description, список PropertyObjectId, Comment-ы элементов (объём/приватность — правило
selection.md). Вложенных моделей нет.
Когда публикуется
| Условие | Переход состояния | Публикация |
|---|---|---|
POST /selections — подборка создана (лимит INV-SEL-007 пройден, PublicCode сгенерирован INV-SEL-005) | Selection: [*] → Active | атомарно с созданием подборки |
POST /selections/from-favorites — состав скопирован из internal API favorites (INV-SEL-010), подборка создана | Selection: [*] → Active (Source = Favorites) | атомарно с созданием подборки |
Событие не публикуется при снятии snapshot-а для поста (news, m2m) — подборка не создаётся,
см. README событий и selection-snapshot.md.
Потребители (consumers)
Сверено с ../README.md (Events И Consumers) и service-boundaries.md.
| Consumer-контекст | Consumer | Эффект (событие → что меняется) | Идемпотентность | Задержка (SLA) |
|---|---|---|---|---|
user-activity | UserActivitySelectionCreatedConsumer (будущий док: docs/06-services/user-activity/consumers/selections-actions.md) | ActionEvent «создал подборку» (Title, Source, ItemsCount) в историю действий OwnerUserId; проброс в карточку лида — поток user-activity → crm | MessageId (дубль — skip) | < 1 мин |
crm и news на топик не подписаны: CRM хранит SelectionId у себя и читает подборку синхронно
(GET /internal/selections/{id}); news работает только со snapshot-ами (синхронный m2m).
Доставка и обработка отказов
- At-least-once через outbox (атомарно с созданием подборки);
user-activityдедуплицирует поMessageId— повторная доставка не плодит дублей ActionEvent. - Транзиентный сбой консюмера → повторная доставка до ack; неустранимая (malformed payload) → DLQ + alert, без потери (реплей из топика). Отставание консюмера создание подборки не блокирует — сама подборка доступна сразу по API, ActionEvent в карточке лида появляется в пределах SLA (< 1 мин).
- Общая политика доставки/порядка/DLQ — README.md, раздел «Доставка, идемпотентность и обработка отказов».
Версионирование и совместимость
ContractVersion = 1; несовпадение версии события — warn-and-proceed.- Additive-only: новые optional-поля — без bump; breaking —
ContractVersion = 2+ топикpin.selections.selection-created.v2+ dual-publish + sunset.v1. - Unknown enum
Source— fallback: consumer записывает исходную строку + warning, не падает. - События
created/updated/deletedживут в разных топиках — порядок между ними не гарантирован; consumer упорядочивает поOccurredAtи терпитupdated, пришедший раньшеcreated(upsert-семантика проекции).
Безопасность
| Поле | Класс данных | Правило |
|---|---|---|
SelectionId, Source, ItemsCount, OccurredAt | Internal | include |
OwnerUserId | Internal (в публичные ответы API не попадает — но Kafka-контур внутренний) | include |
Title | Internal (владелец публикует его по ссылке сам) | include |
Список PropertyObjectId, Comment элементов, PublicCode, Description | Internal/приватная зона владельца | exclude |
Событие НЕ содержит secrets, tokens, PII-профиля.
Обратные ссылки
Автоссылки: где используется этот документ.
- Use Cases (1): UC-SEL-005. Агент отправляет подборку клиенту в лиде/сделке
- События (5): События контекста selections: карта топиков и отклонённые события, Event Contract: pin.selections.selection-deleted (SelectionDeletedKafkaEvent), Event Contract: pin.selections.selection-item-added (SelectionItemAddedKafkaEvent), Event Contract: pin.selections.selection-shared (SelectionSharedKafkaEvent), Event Contract: pin.selections.selection-updated (SelectionUpdatedKafkaEvent)
- Консюмеры (1): Consumer: Selection Shared (SelectionSharedConsumer)
- registries (1): Реестр событий PIN
- index.md (1): Selections Service (Pin.Selections)
Связанные документы
- Источник полей: entity:
Selection(INV-SEL-002..010). - Соседние события: selection-updated.md, selection-deleted.md; карта и отклонённые события — README.md.
- Источник состава from-favorites: ../../favorites/domain/favorite.md.
- Границы: ../README.md; решения: ADR-0054, ADR-0056.