Перейти к основному содержимому

События сервиса support: карта топиков и решения об интеграциях

Индекс интеграционных событий pin.support.* (по одному контракт-доку на топик) + дом решений об интеграциях контекста «Служба заботы»: что публикуется, что потребляется и что сознательно не публикуется. Минимальность — ADR-0056: топик существует только при живом потребителе, которому синхронный API не подходит. Единственный внешний потребитель produced-событий supportnotifications (оповещения операторов/заявителя/сторон).

Metadata

ПолеЗначение
Owning teamPIN Platform (Care squad)
Статус документаdraft
Область действияконтекст support, папка events/ (produced + consumed + отклонённые)
ЗависимостиKafka (outbox producer + консюмер identity), identity (upstream-топик реплики заявителя), notifications (потребитель produced-событий)
Change contextgreenfield; фиксирует Produced/Consumed из ../README.md («Events И Consumers»)

Метаданные и общие правила

Каждое событие несёт метаданные: MessageId (Guid v7, для дедупликации), CreatedAt, версию контракта, типизированный payload, AggregateId, AggregateType; сквозной trace восстанавливается из метаданных. Все produced-топики публикуются через транзакционный outbox атомарно с мутацией агрегата: пока изменение не зафиксировано, событие не отправляется потребителям. У всех ContractVersion = 1 и NumberOfPartitions = 3 (низкий объём тикетов/дел, 1–10k активных, ADR-0056). Прямого PII payload'ы не несут по построению — ФИО/телефон/email потребитель (notifications) резолвит из собственной реплики identity; события несут только id/enum/метки времени.

Публикуемые события (по одному контракт-доку на топик)

СобытиеTopicКлюч (AggregateId)Producer-операцияConsumersКонтракт
TicketCreatedKafkaEventpin.support.ticket-created.v1TicketIdcreate-ticket (веб-форма) / create-ticket-on-behalf (оператор) → Newnotifications (оповестить дежурных операторов очереди)ticket-created.md
TicketMessagePostedKafkaEventpin.support.ticket-message-posted.v1TicketIdreply-ticket (публичный ответ оператора, Visibility = Public)notifications (уведомить заявителя о новом ответе, 4.1/4.5)ticket-message-posted.md
TicketStatusChangedKafkaEventpin.support.ticket-status-changed.v1TicketIdtake/assign/change-ticket-status (take/resolve/close/reopen)notifications (информировать заявителя, 4.5/4.6)ticket-status-changed.md
ArbitrageResolvedKafkaEventpin.support.arbitrage-resolved.v1CaseIdresolve/escalate-arbitrage-case (решение 6.3 / эскалация 6.5)notifications (информировать стороны, 6.4)arbitrage-resolved.md

Дом полей payload — доменные агрегаты (ticket.md / arbitrage-case.md, раздел «Доменные и интеграционные события»); контракт-доки несут типизированную проекцию (дельту), а не второй дом. Ключ = AggregateId даёт per-ticket / per-case порядок переходов (одна партиция на ключ).

Событие worker-а SLA (additive, дом — в background-доке)

ticket-sla-monitor при обнаружении просрочки первого ответа/решения (флаг SlaBreached) публикует TicketSlaBreachedKafkaEvent (pin.support.ticket-sla-breached.v1, AggregateId = TicketId) через тот же транзакционный outbox — консюмер notifications (эскалация просрочки супервизору/дежурным). Полный payload и решение об этом топике инлайнятся в доме worker-а (../background/ticket-sla-monitor.md, шаг 6) — как у CRM timeline-overdue (../../crm/background/timeline-overdue.md); это additive-расширение реестра produced-событий (отдельный контракт-док — по мере стабилизации).

Потребляемые события (consumed)

Display-реплика подписи заявителя из identity для карточек тикетов/арбитража без джойна (дом полей — ticket.md / arbitrage-case.md). Мутация реплики и отметка идемпотентности выполняются в одном согласованном изменении.

Топик (upstream)СобытиеConsumer-докSide effectИдемпотентность
pin.identity.users.v1UserUpsertedKafkaEvent../consumers/identity-user-upserted.mdUpsert RequesterName/RequesterPhone на всех тикетах (RequesterUserId) и ComplainantName/ComplainantPhone на арбитражных делах (ComplainantUserId) заявителя (fan-out)MessageId + монотонный version-guard (IdentityRequesterVersion/IdentityComplainantVersion)

Контракт источника — ../../identity/events/user-upserted.md. UserBlockedKafkaEvent того же топика консюмер игнорирует (статус заявителя на display тикета не влияет). Собственные интеграционные события реплики не публикуют (внутренние данные, ADR-0056).

Гарантии доставки, порядка и восстановления

  • Доставка. Produced-события — at-least-once через транзакционный outbox: публикуются атомарно с мутацией агрегата (пока изменение не зафиксировано — событие не уходит), потребитель обязан дедуплицировать по MessageId (first-seen). Повторная доставка (дубли) — штатное поведение at-least-once, не ошибка.
  • Порядок внутри топика. Ключ = AggregateId (TicketId / CaseId) даёт per-ticket / per-case порядок переходов в пределах одного топика (одна партиция на ключ).
  • Порядок между топиками не гарантирован. ticket-created, ticket-status-changed, ticket-message-posted и ticket-sla-breachedразные топики; общий ключ TicketId колокализует сообщения только внутри своего топика, но межтопикового порядка не даёт. Потребитель (notifications) не должен полагаться на то, что ticket-created придёт раньше ticket-status-changed того же тикета: при расхождении — обрабатывать факт как самодостаточный (каждое событие несёт Number/Status), а недостающую подпись/детали дорезолвивать из собственных реплик/по API. То же для arbitrage-resolved относительно внутренних доменных фактов дела.
  • Retry / DLQ (потребление). Обработка produced-событий и consumed-реплики identity — с ретраями транзиентных сбоев; исчерпание попыток → карантин (DLQ) с алертом, без блокировки партиции. Для реплики identity устаревшее/out-of-order событие не ретраится, а штатно игнорируется version-guard-ом (IdentityRequesterVersion/IdentityComplainantVersion) — это не ошибка. Дом ретраев/DLQ консюмера — ../consumers/identity-user-upserted.md.
  • Промежуточное состояние для пользователя. Между коммитом операции и доставкой уведомления есть окно (SLA потребления < 1 мин): заявитель уже видит новый статус/ответ в карточке тикета (source of truth PostgreSQL), уведомление приходит следом. Отставание поисковой проекции описано в ../search/tickets.md / ../search/kb.md.

Отклонённые события/консюмеры (решение, не пробел)

pin.support.arbitrage-registered / ticket-assigned / queue-* — НЕ публикуются

КандидатПричина отклонения
arbitrage-registeredРегистрация дела (6.1) не имеет внешнего потребителя: информирование сторон нужно только по терминальному исходу (arbitrage-resolved, 6.4); внутренние оповещения арбитра — доменное событие той же операции.
ticket-assignedНазначение оператора — внутренний факт support; смену статуса при взятии несёт ticket-status-changed, а оповещение оператора — доменное событие/дежурная модель notifications. Внешнего потребителя нет.
ticket-message-added (заметки/ответ заявителя)Внутренние заметки (Visibility = Internal) и сообщения самого заявителя (add-ticket-message) внешнего потребителя не имеют. Исключение: публичный ответ оператора (reply-ticket, Visibility = Public) публикуется как ticket-message-posted (уведомление заявителя, см. таблицу produced выше) — внешний потребитель notifications есть.
queue-created / queue-archivedTicketQueueEntity — внутренний справочник маршрутизации (ticket-queue.md); внешние контексты о нём не знают. Только доменные события (QueueCreated/QueueArchived), без Kafka.

Сквозной просмотр / ручные вмешательства (2.x/3.x/5.x) — синхронно, без событий

Просмотр пользователей/сделок/финансов и ручные интервенции support делает синхронно через platform-scope API чужих сервисов (identity/crm/chessboard/rewards), а не событиями (README, «Не делает»). Факт вмешательства фиксируется ссылкой в ArbitrageNoteEntity.AuditRefs, не Kafka-топиком.

Пересмотр любого пункта — additive при появлении реального событийного потребителя.

Безопасность

ПотокКласс данныхПравило
ticket-created / ticket-message-posted / ticket-status-changed / arbitrage-resolved payloadInternalinclude (только id/enum/метки времени; ФИО/телефон/email/тексты сообщений исключены — exclude)
consumed identity-репликаPII (ФИО/телефон заявителя)приходит из доверенного топика identity (m2m ACL); в репликах support — display-подпись карточки; в логах ФИО/телефон маскируются (И***, +7***1234)

Actor/permission — на стороне producer-операций (support.tickets.*/support.arbitrage.*); консюмер — system-actor (platform-scope). События НЕ содержат secrets, tokens, raw PII/платёжных реквизитов, тел переписки/обоснований, unbounded-вложений.

Связанные документы