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