Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 159 · После Manager, Server и первого каталога

MongoDB: снимки топологии, события SDAM и ограниченный журнал подключения

Настоящие уведомления открытия, heartbeat, изменения и закрытия; immutable old/new, пригодность чтения и записи, global и Manager-подписки, два клиента и ограничение памяти.

Получить понятную историю подключения

В сервисе нужна понятная история подключения: клиент создан, узел ещё неизвестен, проверка прошла или отказала, клиент освобождён. Без такой истории легко принять Single за успешное соединение, старый снимок — за текущее состояние, а закрытие клиента — за остановку MongoDB. Здесь построим небольшой журнал настоящих событий и свяжем его с полезным чтением каталога.

Предварительные понятия: документ, коллекция и первый товар, Manager, Server и реальный источник ответа, объект и метод. Топология — известная клиенту картина подключения: какие узлы обнаружены и как организован доступ к ним. Снимок сохраняет эту картину на один момент. Событие сообщает о произошедшем изменении. Подписчик — наш объект, которому драйвер передаёт события вызовом его методов.

SDAM означает Server Discovery and Monitoring: обнаружение и мониторинг серверов. Это служебная работа драйвера, а не перебор товаров. Heartbeat — проверка серверного hello; её начало, успех и отказ отличаются от результата пользовательского find/insert. У Single есть один прямой endpoint; Standalone — тип обнаруженного mongod. Эти имена относятся к разным уровням.

Кто вызывает код журнала
  1. Программа регистрирует объект $journal
  2. Программа выполняет ping через Manager
  3. Драйвер проверяет сервер служебным hello
  4. Драйвер вызывает $journal->topologyChanged($event)
  5. Метод читает old/new и topologyId
  6. Программа показывает снимок и ограниченный журнал

Самое короткое полезное чтение, когда снимок уже пришёл из события: первая строка сохраняет логический ответ в переменную, echo показывает понятный текст. Знак -> вызывает метод объекта; ?: выбирает один из двух текстов. Этот getter не соединяется с сервером заново.

$readable = $snapshot->hasReadableServer();
echo $readable ? 'В снимке есть читаемый узел' : 'Подходящий узел пока не известен';

Чтобы получить $snapshot, реализуем метод интерфейса SDAMSubscriber. Интерфейс — договор о названиях, входных параметрах и результате методов; драйвер умеет обращаться к любому объекту с таким договором. $event является параметром метода, который заполняет сам драйвер. : void означает, что обработчик сохраняет наблюдение и не возвращает значение.

public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void {
    $this->snapshot = $event->getNewDescription();
}

Это короткая часть класса, а не самостоятельный файл. Полная реализация всех девяти методов есть в helper каждого ZIP. Никто не вызывает их вручную для получения красивой таблицы: сначала регистрируется объект, затем выполняется настоящая команда. Регистрация, обработчик события и операция базы — три отдельных действия.

Событие, подписчик и неизменяемый снимок

Для отчёта полезно сохранять и смысл действия, и границу его доказательства. Снимок — фотография известного клиенту состояния: он не обновляется сам и не является сетевой проверкой в момент чтения getter.

НаблюдениеОткуда берётсяЧто оно означает
topologyOpeningCallback после открытия клиентской топологииНачало жизни клиента; успешный handshake ещё не подтверждён
serverOpeningУзел добавлен в топологиюУзел стал объектом наблюдения; ещё не обязательно доступен
heartbeat Started / Succeeded / FailedСлужебная проверка hello драйверомХод мониторинга; результат прикладной операции проверяется отдельно
serverChangedИзменилось описание конкретного узлаНапример, Unknown стал Standalone
topologyChanged: old/new/idИзменилось описание всей топологииТочная пара снимков для одной идентичности клиента
hasReadableServer / hasWritableServerЧтение сохранённого снимкаПригодность по этому описанию; не гарантия будущего запроса
serverClosed / topologyClosedУдаление наблюдаемого сервера / закрытие клиентаНе команда остановки MongoDB и не удаление данных

Global-подписчик регистрируется функцией Monitoring\addSubscriber и видит события любых Manager. Manager::addSubscriber ограничивает область одним Manager. Один и тот же объект не получает одно событие дважды из-за повторной регистрации или сочетания global+Manager. Для снятия используются соответствующие removeSubscriber: удаление одной регистрации не удаляет другую. Наблюдать открытие удобнее глобально до создания Manager, а закрытие — глобально после освобождения всех ссылок на непостоянный клиент.

getNewDescription и getPreviousDescription возвращают TopologyDescription. Его getServers возвращает ServerDescription, а не подключаемые объекты Server из Manager::getServers. topologyId — ObjectId для клиентской топологии; это не _id документа и не обязательный идентификатор физического кластера. Когда два клиента используют один адрес, такой ключ позволяет разделить их истории.

Callbacks должны быть короткими. В этой главе они только добавляют ограниченную запись и обновляют счётчик в памяти. Журнал хранит до четырёх идентичностей и 16 переходов; обычный список событий ограничен 64 записями, в последнем задании — шестью. Политика переполнения видна через discarded. Медленный HTTP-запрос или новый MongoDB-запрос внутри callback менял бы работу наблюдаемой программы.

Запустить стенд и самостоятельные программы

Нужны PHP 8.4+ CLI, ext-mongodb 2.5+ и отдельный локальный MongoDB Community 8.0+. Composer не нужен. README каждого ZIP объясняет установку DLL под версию PHP/TS/NTS/x64, проверку php.ini и запуск mongod с отдельным dbpath, bind_ip 127.0.0.1, портом 27075. Это изолированный учебный Standalone, а не публичный сервер без аутентификации.

php --ri mongodb
$env:PHPMAN_MONGODB_URI='mongodb://127.0.0.1:27075/?directConnection=true&retryWrites=false'
$env:PHPMAN_MONGODB_DATABASE='php_manual_lab'
php example.php

Распакуйте каждый пример в отдельную папку вместе с mt123-helper.php и README. result.html содержит настоящую таблицу и раскрываемые события; result.json — строки таблицы; metrics.json — версии, проверки и SHA256. Все восемь программ обращаются к реальному MongoDB. Два сценария чтения создают только свои коллекции со случайными именами и удаляют их в finally; остальные не создают коллекций.

Для настоящих lifecycle-событий helper создаёт Manager с disableClientPersistence=true и освобождает его до завершения request. Для контролируемого отказа программа резервирует собственный loopback-порт без LISTEN и ограничивает connect/selection timeout; существующий MongoDB продолжает работать. Не копируйте случайный номер из результата: порт каждый раз выдаёт ОС, и он удерживается нашим сокетом до очистки.

Получить статус подключения из настоящего события, а не из new Manager

В панели диагностики хочется показать понятный статус базы. Сам факт создания Manager для этого не подходит: это ещё не успешный обмен. Сохраним снимок, который драйвер сообщает при обнаружении доступного сервера.

Исходные данные

Один локальный mongod на 127.0.0.1:27075. До создания Manager регистрируется объект Mt123Journal. Его метод topologyChanged вызывается драйвером; он сохраняет старое и новое описание. Сам конструктор не обязан доставить события: сначала выполняется ping, затем из настоящего события обнаружения берётся пара прежнего и нового описаний.

Путь действий и наблюдений
  1. Зарегистрировать подписчик до new Manager
  2. Создать Manager и выполнить настоящий ping
  3. Найти событие перехода от нечитаемого Single к читаемому
  4. Взять previousDescription и newDescription этого события
  5. Показать false/false/0 и true/true/1
  6. Освободить непостоянный клиент и снять подписчик

Короткое действие

public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void {
    $snapshot = $event->getNewDescription();
    $this->readable = $snapshot->hasReadableServer();
} // Метод вызывает драйвер после регистрации объекта-подписчика.

Видимый результат

МоментТопологияЕсть читаемый узелЕсть writable узелИзвестных описаний
Прежнее описание из событияSinglefalsefalse0
Новое описание после pingSingletruetrue1

Почему получился такой результат

В обеих строках тип Single: это топология прямого подключения, а не синоним «соединение проверено». В previousDescription события hasReadableServer и hasWritableServer возвращают false. В newDescription после обнаружения есть один Standalone. Оба описания программа получает из настоящего события во время первого ping, а не читает пустой журнал до обращения. В раскрываемом журнале видны topologyOpening, serverOpening, heartbeat и изменения описания; события вручную не создаются.

Ошибки и ограничения

Статус относится к сохранённому описанию и моменту наблюдения. Он не гарантирует, что следующий запрос не встретит сетевой отказ или проблему прав. Частоту heartbeat и точное число вспомогательных уведомлений не превращаем в универсальную константу. Наш запуск проверяет начальное обнаружение и освобождение клиента, а не смену primary.

Самостоятельная программа, helper и архив
Получить статус подключения из настоящего события, а не из new ManagerСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal; $manager=null;
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $manager=mt123Manager($uri); $ping=mt123Ping($manager,$database);
    $transition=null;
    foreach ($journal->changes as $change) {
        if ($change['old']->getType()==='Single' && !$change['old']->hasReadableServer()
            && $change['new']->hasReadableServer()) { $transition=$change; break; }
    }
    if ($transition===null) { throw new RuntimeException('Expected actual discovery transition'); }
    $before=$transition['old']; $after=$transition['new'];
    $servers=$after->getServers();
    $rows=[['Прежнее описание из события',$before->getType(),$before->hasReadableServer(),$before->hasWritableServer(),count($before->getServers())],
        ['Новое описание после ping',$after->getType(),$after->hasReadableServer(),$after->hasWritableServer(),count($servers)]];
    $checks=['real_ping'=>$ping,'actual_standalone'=>count($servers)===1 && $servers[0]->getType()==='Standalone',
        'real_notifications'=>$journal->count('topologyOpening')===1 && $journal->count('serverOpening')===1
            && $journal->count('serverHeartbeatStarted')>=1 && $journal->count('serverHeartbeatSucceeded')>=1
            && $journal->count('serverChanged')>=1 && $journal->count('topologyChanged')>=2];
} finally {
    unset($manager); MongoDB\Driver\Monitoring\removeSubscriber($journal);
}
$checks['actual_close']=$journal->count('topologyClosed')===1 && $journal->count('serverClosed')===1;
$details=['Настоящий журнал'=>$journal->events,'Счётчики'=>$journal->counts,'Снимок после ping'=>mt123Snapshot($after),
    'Граница'=>'Снимок пригодности не заменяет try/catch у следующего запроса; topologyOpening не подтверждает подключение'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['Прежнее описание из события', 'Single', false, false, 0], ['Новое описание после ping', 'Single', true, true, 1]];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-connect-status',['Момент', 'Топология', 'Есть читаемый узел', 'Есть writable узел', 'Известных описаний'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-connect-status: OK',"\n";
Ожидаемый результат
mongodb123-topology-connect-status: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Если интерфейс показывает только «Single», можно ли считать базу доступной? Нет: посмотрите прежнее описание из события. Для статуса различайте тип топологии, известную пригодность узла и результат реальной операции.

Сопоставить читаемый снимок с реальной карточкой CUP

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

Исходные данные

В собственной коллекции создаются CUP за 500 и LAMP за 1200. Один ограниченный Query получает CUP с полями sku/price без _id. Для одного сохранённого снимка отдельно проверяются primary, secondary и nearest.

Путь действий и наблюдений
  1. Получить снимок после ping
  2. Проверить primary/secondary/nearest на этом снимке
  3. Создать собственный учебный каталог
  4. Запросить один CUP с проекцией и limit 1
  5. Показать цену 500 рядом с результатами проверки
  6. Удалить только свою коллекцию

Короткое действие

$preference = new MongoDB\Driver\ReadPreference('secondary');
$readable = $snapshot->hasReadableServer($preference);
// Single с доступным Standalone не становится replica set из-за слова secondary.

Видимый результат

Политика снимкаТипЧитаемый узел естьОдин реальный товарЦена
primarySingletrueCUP500
secondarySingletrueCUP500
nearestSingletrueCUP500

Почему получился такой результат

Три строки таблицы — три проверки одного снимка, а не три обращения к разным репликам. Документ читается один раз. В Single доступный единственный Standalone подходит независимо от read preference; слово secondary не создаёт второй сервер. hasReadableServer получает необязательный объект ReadPreference, хотя на официальной странице в блоке параметров встречается ошибочная строка «параметров нет»; сигнатура содержит аргумент.

Ошибки и ограничения

При replica set правила выбора другие. Даже true не гарантирует свежесть прикладных данных, права на коллекцию или будущую доступность. Проверка не выполняет Query и не блокирует изменения топологии. Подходящий узел и корректный товар — два независимых условия, поэтому реальная операция всё равно требует обработки ошибок.

Самостоятельная программа, helper и архив
Сопоставить читаемый снимок с реальной карточкой CUPСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal; $manager=null;
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $manager=mt123Manager($uri); mt123Ping($manager,$database); $snapshot=$journal->last();
    $documents=mt123WithCatalog($manager,$database,fn($namespace)=>mt123Products($manager,$namespace,['sku'=>'CUP'],1));
    $rows=[];
    foreach (['primary','secondary','nearest'] as $mode) {
        $readable=$snapshot->hasReadableServer(new MongoDB\Driver\ReadPreference($mode));
        $rows[]=[$mode,$snapshot->getType(),$readable,$documents[0]['sku'],$documents[0]['price']];
    }
    $checks=['bounded_actual_document'=>$documents===[['sku'=>'CUP','price'=>500]],
        'snapshot_writable'=>$snapshot->hasWritableServer(),'owned_collection_removed'=>true,
        'one_known_standalone'=>count($snapshot->getServers())===1 && $snapshot->getServers()[0]->getType()==='Standalone'];
} finally { unset($manager);MongoDB\Driver\Monitoring\removeSubscriber($journal); }
$details=['Полученная карточка'=>$documents,'Снимок'=>mt123Snapshot($snapshot),'Журнал'=>$journal->events,
    'Как читать строки'=>'Три вызова проверяют один снимок Single. Карточка CUP действительно запрошена один раз; три режима не означают три прочитанные реплики'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['primary', 'Single', true, 'CUP', 500], ['secondary', 'Single', true, 'CUP', 500], ['nearest', 'Single', true, 'CUP', 500]];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-read-policy',['Политика снимка', 'Тип', 'Читаемый узел есть', 'Один реальный товар', 'Цена'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-read-policy: OK',"\n";
Ожидаемый результат
mongodb123-topology-read-policy: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Поменяйте фильтр sku на LAMP: единственный реальный документ должен содержать цену 1200, а три результата проверки того же доступного Single останутся true. Это показывает, что выбор документа и пригодность топологии — разные задачи.

Сохранить старый снимок и показать, почему он сам не обновляется

Отчёт «до/после» должен сохранять историю, а не дважды печатать новое состояние. Получим старое описание из настоящего события обнаружения узла и покажем, что ещё один ping его не переписывает.

Исходные данные

Первый ping вызывает реальные события обнаружения. Из одного такого события сохраняются previousDescription с false и newDescription с true. Оба принадлежат одному topologyId. После сохранения значений выполняется второй ping.

Путь действий и наблюдений
  1. Выполнить первый ping для получения реального события
  2. Сохранить его old как A и new как B
  3. Показать прежний A: false и ноль известных описаний
  4. Выполнить второй настоящий ping
  5. Повторно прочитать A: всё ещё false
  6. Показать B: true и один Standalone; topologyId тот же

Короткое действие

$old = $event->getPreviousDescription();
$new = $event->getNewDescription();
$id = (string) $event->getTopologyId();
// Храним оба значения. Старый объект не превратится в $new после следующей команды.

Видимый результат

Какое значениеТипЧитаемый узелОписаний узлов
Прежнее описание из событияSinglefalse0
Этот же объект после ещё одного pingSinglefalse0
Новое описание из событияSingletrue1

Почему получился такой результат

TopologyDescription — неизменяемое описание, а не ссылка на постоянно обновляющуюся панель состояния. Программа не пытается получить его до первых событий. getPreviousDescription и getNewDescription дают точную пару конкретного события после первого обращения; номер клиента берётся через getTopologyId. Затем второй ping действительно выполняется, но сохранённый old остаётся прежним. В таблице видны его значения до и после второго обращения, а новое описание хранится отдельно.

Ошибки и ограничения

Previous означает непосредственно предыдущее описание данного события, а не обязательно первый снимок за жизнь приложения. Одного объекта A недостаточно для текущей диагностики через час. Журнал переходов в helper ограничен 16 записями; для долгого процесса нужна явная политика хранения истории, а не бесконечный массив.

Самостоятельная программа, helper и архив
Сохранить старый снимок и показать, почему он сам не обновляетсяСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal; $manager=null;
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $manager=mt123Manager($uri); $ping=mt123Ping($manager,$database);
    $transition=null;
    foreach ($journal->changes as $change) {
        if ($change['old']->getType()==='Single' && !$change['old']->hasReadableServer()
            && $change['new']->hasReadableServer()) { $transition=$change; break; }
    }
    if ($transition===null) { throw new RuntimeException('Expected actual discovery transition'); }
    $saved=$transition['old'];$savedValue=mt123Snapshot($saved);$fresh=$transition['new'];
    $rows=[['Прежнее описание из события',$saved->getType(),$saved->hasReadableServer(),count($saved->getServers())]];
    $secondPing=mt123Ping($manager,$database);
    $rows[]=['Этот же объект после ещё одного ping',$saved->getType(),$saved->hasReadableServer(),count($saved->getServers())];
    $rows[]=['Новое описание из события',$fresh->getType(),$fresh->hasReadableServer(),count($fresh->getServers())];
    $checks=['real_ping'=>$ping && $secondPing,'old_snapshot_immutable'=>mt123Snapshot($saved)===$savedValue,
        'event_transition_actual'=>!$transition['old']->hasReadableServer() && $transition['new']->hasReadableServer(),
        'same_topology_identity'=>count(array_unique(array_column($journal->changes,'id')))===1];
} finally { unset($manager);MongoDB\Driver\Monitoring\removeSubscriber($journal); }
$details=['Переход события'=>['topologyId'=>$transition['id'],'before'=>mt123Snapshot($transition['old']),'after'=>mt123Snapshot($transition['new'])],
    'Старый снимок остаётся прежним'=>mt123Snapshot($saved),'Журнал'=>$journal->events,
    'Что не происходило'=>'Смена primary и отказ живого сервера не моделировались: это начальное обнаружение Standalone'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['Прежнее описание из события', 'Single', false, 0], ['Этот же объект после ещё одного ping', 'Single', false, 0], ['Новое описание из события', 'Single', true, 1]];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-snapshot-history',['Какое значение', 'Тип', 'Читаемый узел', 'Описаний узлов'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-snapshot-history: OK',"\n";
Ожидаемый результат
mongodb123-topology-snapshot-history: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Сделайте две колонки отчёта old/new из одного TopologyChangedEvent. Не запрашивайте случайное текущее значение отдельно для колонки old. Если old=false и new=true, это в нашем случае обнаружение узла, не автоматическое доказательство восстановления после аварии.

Разделить события каталога и импорта на одном адресе

Один процесс использует MongoDB для каталога и импорта. Оба клиента ходят на один адрес, поэтому host:port не позволяет понять, к какой задаче относится событие. Разделим наблюдение по области регистрации и по идентификатору топологии.

Исходные данные

Два независимых Manager с disableClientPersistence=true подключаются к одному стенду. Один журнал зарегистрирован глобально; для каталога есть второй, привязанный только к его Manager. Тот же глобальный объект дополнительно регистрируется в Manager и повторно добавляется: по контракту он не должен удваивать доставку.

Путь действий и наблюдений
  1. Global-журнал получает события любых клиентов
  2. Создать клиент каталога и добавить scoped-подписчик
  3. Проверить его настоящий ping
  4. Снять scoped-подписчик
  5. Создать отдельный клиент импорта и выполнить ping
  6. Сопоставить два topologyId и один endpoint

Короткое действие

MongoDB\Driver\Monitoring\addSubscriber($journal); // Все Manager процесса.
$catalog->addSubscriber($onlyCatalog);              // Только этот Manager.
$catalog->removeSubscriber($onlyCatalog);           // Снять эту регистрацию.
MongoDB\Driver\Monitoring\removeSubscriber($journal);

Видимый результат

Область наблюденияНаблюдениеЧто учтено
Глобальный журнал2каталог + импорт
Подписчик Manager каталога1только каталог
Один объект global + Managerбез удвоенияодни heartbeat-уведомления

Почему получился такой результат

Глобальная регистрация действует на события расширения для любых Manager, а привязка к Manager ограничивает область наблюдения. Повторная регистрация того же объекта является no-op. Если он одновременно global и Manager-scoped, одно событие для данного Manager не доставляется дважды. Это проверяется сравнением heartbeat-счётчиков двух наблюдателей каталога. topologyId сохраняется в реальном журнале и связывается с именем задачи.

Ошибки и ограничения

Два объекта-подписчика с одинаковым кодом — не один и тот же объект: они могут законно получить одно событие каждый. topologyId относится к клиентской топологии, не к физическому кластеру или _id товара. Чтобы получить независимые клиенты здесь выключена persistence; обычное приложение может повторно использовать внутренний клиент. Снятие Manager-регистрации не снимает global-регистрацию того же объекта.

Самостоятельная программа, helper и архив
Разделить события каталога и импорта на одном адресеСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$global=new Mt123Journal; $onlyCatalog=new Mt123Journal; $catalog=null;$import=null;
MongoDB\Driver\Monitoring\addSubscriber($global);MongoDB\Driver\Monitoring\addSubscriber($global);
try {
    $catalog=mt123Manager($uri);
    $catalog->addSubscriber($global);$catalog->addSubscriber($global);
    $catalog->addSubscriber($onlyCatalog);$catalog->addSubscriber($onlyCatalog);
    $catalogOk=mt123Ping($catalog,$database);$catalogId=$global->openingIds[0];
    $deduplicated=$global->count('serverHeartbeatStarted')===$onlyCatalog->count('serverHeartbeatStarted')
        && $global->count('serverHeartbeatSucceeded')===$onlyCatalog->count('serverHeartbeatSucceeded');
    $scopeBefore=$onlyCatalog->counts;
    $catalog->removeSubscriber($onlyCatalog);$catalog->removeSubscriber($onlyCatalog);
    $import=mt123Manager($uri);$importOk=mt123Ping($import,$database);$importId=$global->openingIds[1];
    $catalog->removeSubscriber($global); // Global registration still exists.
    $rows=[['Глобальный журнал',count(array_unique($global->openingIds)),'каталог + импорт'],
        ['Подписчик Manager каталога',count($onlyCatalog->latest),'только каталог'],
        ['Один объект global + Manager',$deduplicated?'без удвоения':'есть дубли','одни heartbeat-уведомления']];
    $checks=['both_real_pings'=>$catalogOk && $importOk,'distinct_topology_ids'=>$catalogId!==$importId,
        'manager_scope_only_catalog'=>array_keys($onlyCatalog->latest)===[$catalogId],
        'removed_scope_unchanged'=>$scopeBefore===$onlyCatalog->counts,'duplicate_registration_noop'=>$deduplicated];
} finally {
    if ($catalog!==null) { $catalog->removeSubscriber($onlyCatalog);$catalog->removeSubscriber($global); }
    unset($catalog,$import);MongoDB\Driver\Monitoring\removeSubscriber($global);MongoDB\Driver\Monitoring\removeSubscriber($global);
}
$checks['both_global_closures']=count(array_unique($global->closedIds))===2;
$details=['Назначения клиентов'=>['каталог'=>$catalogId,'импорт'=>$importId],
    'Общий журнал'=>$global->events,'Журнал только каталога'=>$onlyCatalog->events,
    'Идентичность'=>'Один host:port, но два независимых непостоянных клиента. topologyId не является _id товара или идентификатором физического кластера'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['Глобальный журнал', 2, 'каталог + импорт'], ['Подписчик Manager каталога', 1, 'только каталог'], ['Один объект global + Manager', 'без удвоения', 'одни heartbeat-уведомления']];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-two-clients',['Область наблюдения', 'Наблюдение', 'Что учтено'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-two-clients: OK',"\n";
Ожидаемый результат
mongodb123-topology-two-clients: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Нужно наблюдать только импорт. Зарегистрируйте отдельный объект через $import->addSubscriber и снимите его тем же Manager. Если оставить этот объект зарегистрированным глобально, ожидаемой изоляции не будет.

Увидеть настоящее закрытие клиента и оставить сервер работающим

После unset($manager) разработчик ждёт сообщение о закрытии и не получает его. Покажем реальные условия такого события и отличие закрытия клиента от остановки базы.

Исходные данные

Свежий Manager создаётся с driverOptions disableClientPersistence=true. Global-журнал зарегистрирован заранее. Короткий ping полностью прочитан внутри функции, её Cursor уже освобождён; других ссылок на Manager нет. Затем удаляется последняя ссылка на клиент.

Путь действий и наблюдений
  1. Global-подписка до создания клиента
  2. Получить ping и сохранить исторический снимок
  3. Зафиксировать ноль закрытий пока Manager существует
  4. Освободить клиент до завершения PHP request
  5. Драйвер сообщает serverClosed/topologyClosed
  6. Снять подписку и новым клиентом проверить живой сервер

Короткое действие

$manager = new MongoDB\Driver\Manager($uri, [], ['disableClientPersistence'=>true]);
// После реальной команды освободить Cursor/Server/другие ссылки на клиент.
unset($manager); // Subscriber получает closure; mongod продолжает работать.

Видимый результат

МоментОткрытий топологииЗакрытий топологииСмысл
После ping10клиент ещё существует
После освобождения11клиент закрыт; сервер не остановлен

Почему получился такой результат

В таблице появляется одно закрытие, а последующий контрольный ping к тому же mongod успешен: закрыт клиент, не серверный процесс. Сохранённый до закрытия снимок продолжает сообщать true — потому что он историческое значение. Снятый global-подписчик больше не получает события контрольного клиента. Само событие topologyClosed доступно до request shutdown при отключённой persistence и реальном освобождении внутреннего клиента.

Ошибки и ограничения

При обычной persistence время жизни внутреннего клиента не обязано совпадать с переменной Manager. Cursor, Server или иные ссылки тоже могут удерживать клиент. Не вводите отключение persistence для каждого веб-запроса только ради красивого журнала: это отдельное изменение стратегии соединений. Callback закрытия не является командой shutdown MongoDB.

Самостоятельная программа, helper и архив
Увидеть настоящее закрытие клиента и оставить сервер работающимСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal;$manager=null;
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $manager=mt123Manager($uri);$ping=mt123Ping($manager,$database);$connected=$journal->last();
    $beforeClosed=$journal->count('topologyClosed');
    unset($manager); // No Cursor or Server keeps the Manager alive.
    $afterClosed=$journal->count('topologyClosed');
    $rows=[['После ping',$journal->count('topologyOpening'),$beforeClosed,'клиент ещё существует'],
        ['После освобождения',count($journal->openingIds),$afterClosed,'клиент закрыт; сервер не остановлен']];
    $checks=['real_ping'=>$ping,'actual_lifecycle'=>$beforeClosed===0 && $afterClosed===1
        && $journal->count('serverClosed')===1 && $journal->count('serverOpening')===1,
        'same_open_close_id'=>$journal->openingIds===$journal->closedIds,
        'retained_snapshot_is_history'=>$connected->hasReadableServer() && $connected->hasWritableServer()];
} finally { unset($manager);MongoDB\Driver\Monitoring\removeSubscriber($journal); }
$countsAfterRemoval=$journal->counts;
$control=mt123Manager($uri);$stillAlive=mt123Ping($control,$database);unset($control);
$checks['server_still_running']=$stillAlive;
$checks['global_removal_effective']=$journal->counts===$countsAfterRemoval;
$details=['Настоящий жизненный цикл'=>$journal->events,'Счётчики'=>$journal->counts,
    'Снимок, сохранённый до закрытия'=>mt123Snapshot($connected),
    'Почему closure виден'=>'disableClientPersistence=true и освобождение клиента до завершения PHP request; обычная persistence имеет другую длительность жизни'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['После ping', 1, 0, 'клиент ещё существует'], ['После освобождения', 1, 1, 'клиент закрыт; сервер не остановлен']];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-client-lifetime',['Момент', 'Открытий топологии', 'Закрытий топологии', 'Смысл'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-client-lifetime: OK',"\n";
Ожидаемый результат
mongodb123-topology-client-lifetime: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Объясните три разные операции: unset Manager освобождает PHP-ссылку; removeSubscriber снимает наблюдение; остановка mongod прекращает серверный процесс. В этом примере выполняются только первые две, а сервер остаётся доступным.

Практический вопрос: PHP Mongodb driver 1.5: how to use connection pool?. Автор не различает pooling и persistence текущего PHP-клиента и находит старые руководства. Наш пример объясняет ограниченное время жизни непостоянного клиента и настоящие closure-события; старые рецепты не копируются. Обсуждение использовано для постановки задачи; технические правила PHP-драйвера сверены по первичным источникам.

Отделить отказ heartbeat от недоступности всего приложения

Пользователь видит отказ подключения, а разработчику нужно понять, что произошло на этапе обнаружения сервера. Получим настоящий failed heartbeat без остановки рабочей базы и без угадывания чужого свободного порта.

Исходные данные

Программа занимает собственный случайный loopback-порт через STREAM_SERVER_BIND, не включая LISTEN. У тестового Manager connectTimeoutMS=300 и serverSelectionTimeoutMS=500. Установить MongoDB handshake с этим endpoint нельзя. После отказа отдельно проверяется настоящий здоровый стенд.

Путь действий и наблюдений
  1. Зарезервировать свой локальный порт без слушателя
  2. Зарегистрировать журнал и создать тестовый Manager
  3. Выполнить настоящий ping к тестовой точке
  4. Драйвер сообщает heartbeatStarted и heartbeatFailed
  5. Операция выбрасывает исключение соединения
  6. Закрыть клиент/сокет и проверить здоровый MongoDB

Короткое действие

public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void {
    $this->failures++; // Сигнал наблюдения, а не результат пользовательского запроса.
}
// Исключение самой операции всё равно обрабатывается вокруг executeReadCommand.

Видимый результат

НаблюдениеТип или этапЧтение / отказ замеченЗапись доступнаВывод
Проверяемый недоступный endpointSinglefalsefalseисключение соединения
Реальный heartbeatначатtruefalseотказ записан в журнал

Почему получился такой результат

В журнале находятся события, реально присланные драйвером. Исключение самой операции ловится отдельно: запись failed heartbeat не заменяет catch вокруг executeReadCommand. После сохранения имени класса исключение освобождается через unset($error): его стек может удерживать Manager и откладывать закрытие клиента. Тип Single остаётся способом подключения, но читаемого/writable узла в снимке нет. Реальный номер временного порта и длительность heartbeat выводятся в подробностях; они не закрепляются как постоянные значения.

Ошибки и ограничения

Опыт проверяет отказ начального handshake на собственном endpoint. Он не моделирует потерю данных, падение replica set, отказ любого конкретного production-сервера или автоматический retry записи. Указанные таймауты ограничивают соответствующие стадии драйвера, но не служат обещанием ровно 500 мс по внешним часам. В рабочем журнале сокращайте чувствительные данные и не выводите URI с паролем.

Самостоятельная программа, helper и архив
Отделить отказ heartbeat от недоступности всего приложенияСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal;$failed=null;$bound=null;$errorClass=null;
[$bound,$failureUri]=mt123BoundFailure();
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $failed=mt123Manager($failureUri,true);
    try { mt123Ping($failed,$database); }
    catch (MongoDB\Driver\Exception\ConnectionException $error) { $errorClass=get_class($error); unset($error); }
    $snapshot=$journal->last();
    $rows=[['Проверяемый недоступный endpoint',$snapshot->getType(),$snapshot->hasReadableServer(),$snapshot->hasWritableServer(),'исключение соединения'],
        ['Реальный heartbeat',$journal->count('serverHeartbeatStarted')>0?'начат':'не начат',
            $journal->count('serverHeartbeatFailed')>0,false,'отказ записан в журнал']];
    $checks=['real_connection_error'=>$errorClass!==null,'real_failed_heartbeat'=>$journal->count('serverHeartbeatFailed')>=1
            && $journal->count('serverHeartbeatStarted')>=$journal->count('serverHeartbeatFailed'),
        'snapshot_unavailable'=>!$snapshot->hasReadableServer() && !$snapshot->hasWritableServer(),
        'no_false_heartbeat_success'=>$journal->count('serverHeartbeatSucceeded')===0];
} finally {
    unset($failed);MongoDB\Driver\Monitoring\removeSubscriber($journal);
    if (is_resource($bound)) { fclose($bound); }
}
$checks['failed_client_closed']=$journal->count('topologyClosed')===1 && $journal->count('serverClosed')===1;
$control=mt123Manager($uri);$checks['healthy_control_ping']=mt123Ping($control,$database);unset($control);
$details=['Фактическая ошибка операции'=>$errorClass,'Фактический журнал отказа'=>$journal->events,
    'Тестовый endpoint'=>$failureUri,'Снимок отказа'=>mt123Snapshot($snapshot),
    'Ограничение'=>'Своя зарезервированная loopback-точка не слушает. Настоящий MongoDB не останавливался; последующий контрольный ping успешен'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['Проверяемый недоступный endpoint', 'Single', false, false, 'исключение соединения'], ['Реальный heartbeat', 'начат', true, false, 'отказ записан в журнал']];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-heartbeat-failure',['Наблюдение', 'Тип или этап', 'Чтение / отказ замечен', 'Запись доступна', 'Вывод'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-heartbeat-failure: OK',"\n";
Ожидаемый результат
mongodb123-topology-heartbeat-failure: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Найдите в полном коде две независимые проверки: наличие serverHeartbeatFailed и класс исключения операции. Успешное прохождение одной не позволяет автоматически выдумать результат другой. Сокет и клиент освобождаются в finally.

Практический вопрос: Cannot connect to MongoDB: server selection timed out. После перезапуска компьютера локальный endpoint не отвечает, хотя в диагностике показан Single. Пример отделяет тип топологии от доступности и собирает реальные started/failed события на собственном контролируемом endpoint. Обсуждение использовано для постановки задачи; технические правила PHP-драйвера сверены по первичным источникам.

Показать явное решение приложения после неудачной проверки

В диагностическом инструменте после неудачной проверки одной точки можно явно проверить другой заранее разрешённый стенд. Важно не назвать это автоматическим failover и не смешать две истории клиента.

Исходные данные

Первая точка — собственный non-listening сокет, вторая — существующий локальный MongoDB. После реального исключения первого ping приложение создаёт второй Manager и выполняет отдельный ping. Global-журнал сохраняет оба topologyId.

Путь действий и наблюдений
  1. Проверка тестового endpoint не проходит
  2. Сохранить его снимок false/false и topologyId A
  3. Закрыть первый клиент
  4. Программа явно выбирает известный стенд
  5. Второй ping даёт снимок true/true и topologyId B
  6. Вывести обе истории без подмены старого результата

Короткое действие

try { $ok = mt123Ping($candidate, $database); }
catch (MongoDB\Driver\Exception\ConnectionException $error) {
    // После сообщения об отказе явно выбираем разрешённый диагностический стенд.
    $ok = mt123Ping($knownLab, $database);
} // Это политика программы для ping, не автоматический повтор записи.

Видимый результат

Шаг приложенияЧтение в снимкеЗапись в снимкеЯвное действие
Проверяемая точкаfalsefalseпоказать отказ проверки
Заранее известный локальный стендtruetrueявно проверить другой клиент

Почему получился такой результат

Успех второй операции не исправляет исторический снимок первого клиента. Разные topologyId позволяют показать, где была ошибка и что именно проверено затем. Перед закрытием первого клиента сохраняется только имя класса ошибки, а объект исключения освобождается: его стек может удерживать Manager. В журнале видны и настоящий failed heartbeat, и successful heartbeat. Нет остановки базы, автоматического выбора нового primary или незаметного повторения пользовательской записи.

Ошибки и ограничения

Такая ветка допустима здесь для диагностического ping. Нельзя автоматически переносить запись заказов на другую базу лишь потому, что первая не ответила: нужны согласованность данных, права, политика восстановления и понимание неизвестного исхода. Поведение replica set управляется драйвером и его топологией, а не этой ручной последовательностью двух клиентов.

Самостоятельная программа, helper и архив
Показать явное решение приложения после неудачной проверкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal;$failed=null;$healthy=null;$bound=null;$errorClass=null;
[$bound,$failureUri]=mt123BoundFailure();
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    $failed=mt123Manager($failureUri,true);
    try { mt123Ping($failed,$database); }
    catch (MongoDB\Driver\Exception\ConnectionException $error) { $errorClass=get_class($error); unset($error); }
    $failedSnapshot=$journal->last();$failedId=$journal->openingIds[0];unset($failed);
    if ($errorClass===null) { throw new RuntimeException('Expected explicit test endpoint failure'); }
    $healthy=mt123Manager($uri);$ok=mt123Ping($healthy,$database);$healthySnapshot=$journal->last();$healthyId=$journal->openingIds[1];
    $rows=[['Проверяемая точка',$failedSnapshot->hasReadableServer(),$failedSnapshot->hasWritableServer(),'показать отказ проверки'],
        ['Заранее известный локальный стенд',$healthySnapshot->hasReadableServer(),$healthySnapshot->hasWritableServer(),'явно проверить другой клиент']];
    $checks=['actual_failure_and_success'=>$errorClass!==null && $ok,'two_client_identities'=>$failedId!==$healthyId,
        'both_real_heartbeat_outcomes'=>$journal->count('serverHeartbeatFailed')>=1 && $journal->count('serverHeartbeatSucceeded')>=1,
        'failed_history_unchanged'=>!$failedSnapshot->hasReadableServer() && $healthySnapshot->hasReadableServer()];
} finally { unset($failed,$healthy);MongoDB\Driver\Monitoring\removeSubscriber($journal);if(is_resource($bound)){fclose($bound);} }
$checks['both_clients_closed']=count(array_unique($journal->closedIds))===2;
$details=['Связь имён с topologyId'=>['проверяемая точка'=>$failedId,'здоровый стенд'=>$healthyId],
    'Журнал двух разных клиентов'=>$journal->events,'Ошибка первой операции'=>$errorClass,
    'Политика приложения'=>'После отказа только диагностического ping явно проверяется отдельный известный стенд. Это не retry записи, не запасная копия данных и не автоматический failover replica set'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['Проверяемая точка', false, false, 'показать отказ проверки'], ['Заранее известный локальный стенд', true, true, 'явно проверить другой клиент']];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-explicit-fallback',['Шаг приложения', 'Чтение в снимке', 'Запись в снимке', 'Явное действие'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-explicit-fallback: OK',"\n";
Ожидаемый результат
mongodb123-topology-explicit-fallback: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Почему нельзя назвать вторую строку «первая база восстановилась»? Потому что создан другой клиент с другим endpoint и topologyId. Отчёт должен прямо называть выполненное действие: проверен отдельный известный стенд.

Практический вопрос: MongoDB Atlas connections time out. Сообщения служебного monitor-потока принимаются за обязательный отказ каждой операции приложения. Наши два клиента позволяют раздельно показать отказ heartbeat, исключение первой операции и успех другой явно выполненной проверки, без обещаний автоматического failover. Обсуждение использовано для постановки задачи; технические правила PHP-драйвера сверены по первичным источникам.

Ограничить журнал двух заданий и снять подписчиков после работы

Долгий обработчик заданий не должен накапливать бесконечный массив событий. Сделаем две реальные задачи чтения, ограничим подробный буфер и сохраним понятный счётчик пропущенных записей.

Исходные данные

Первое задание читает экран CUP/LAMP с двумя нужными полями и limit=2, второе — одну карточку LAMP. У каждого собственная учебная коллекция и свой scoped-подписчик. Общий журнал сохраняет только первые шесть записей, но продолжает считать типы событий.

Путь действий и наблюдений
  1. Global-журнал ограничен шестью записями
  2. Задание 1: scoped-подписка → экран → очистка
  3. Снять scoped-подписку и освободить клиент
  4. Задание 2: отдельная карточка и такой же lifecycle
  5. Сохранить число отброшенных подробных записей
  6. Снять global-подписку и проверить отсутствие новой доставки

Короткое действие

if (count($this->events) < $this->limit) {
    $this->events[] = $record;
} else {
    ++$this->discarded;
} // Общий счётчик события увеличивается до этой проверки.

Видимый результат

ЗаданиеРеальные артикулыСтрок
экран каталогаCUP, LAMP2
карточка LAMPLAMP1

Почему получился такой результат

Результат задач — реальные артикулы, а не один счётчик событий. После переполнения буфера программа не притворяется, что журнал полный: discarded увеличивается. Проверяется равенство общей суммы событий сохранённым плюс отброшенным. Scoped-подписчик снимается в finally задания; глобальный остаётся до закрытия клиентов, затем тоже снимается. Контрольный клиент уже не меняет его счётчики.

Ошибки и ограничения

Это политика ограниченного учебного буфера, а не гарантированная доставка аудита. Сохраняются первые записи, поэтому поздняя ошибка может остаться только в счётчике; для production выбирают ротацию, кольцевой буфер, экспорт и правила хранения. Нельзя выполнять внутри callback медленный сетевой запрос, который задерживает или рекурсивно запускает наблюдаемую работу.

Самостоятельная программа, helper и архив
Ограничить журнал двух заданий и снять подписчиков после работыСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt123-helper.php';
$runtime=mt123Runtime();
[$uri,$database]=mt123Config();
$journal=new Mt123Journal(6);$worker=null;$scoped=null;$results=[];$scopeChecks=[];
MongoDB\Driver\Monitoring\addSubscriber($journal);
try {
    foreach (['экран каталога','карточка LAMP'] as $position=>$job) {
        $worker=mt123Manager($uri);$scoped=new Mt123Journal;
        $worker->addSubscriber($scoped);$worker->addSubscriber($scoped);
        try {
            $documents=mt123WithCatalog($worker,$database,fn($namespace)=>mt123Products($worker,$namespace,$position===0?[]:['sku'=>'LAMP'],$position===0?2:1));
            $results[]=['job'=>$job,'documents'=>$documents];
        } finally { $worker->removeSubscriber($scoped);$worker->removeSubscriber($scoped); }
        $scopeCounts=$scoped->counts;unset($worker);$worker=null;
        $scopeChecks[]=$scoped->counts===$scopeCounts && $scoped->count('serverHeartbeatSucceeded')>=1;
    }
} finally {
    if ($worker!==null && $scoped!==null) { $worker->removeSubscriber($scoped); }
    unset($worker);MongoDB\Driver\Monitoring\removeSubscriber($journal);
}
$frozenCounts=$journal->counts;
$quiet=mt123Manager($uri);$quietOk=mt123Ping($quiet,$database);unset($quiet);
$rows=[];
foreach($results as $item){$rows[]=[$item['job'],implode(', ',array_column($item['documents'],'sku')),count($item['documents'])];}
$checks=['actual_two_screens'=>$results[0]['documents']===[['sku'=>'CUP','price'=>500],['sku'=>'LAMP','price'=>1200]]
        && $results[1]['documents']===[['sku'=>'LAMP','price'=>1200]],
    'owned_collections_removed'=>true,'bounded_buffer'=>count($journal->events)===6 && $journal->discarded>0,
    'counts_preserved'=>array_sum($journal->counts)===count($journal->events)+$journal->discarded,
    'manager_removal_effective'=>!in_array(false,$scopeChecks,true),'global_removal_effective'=>$journal->counts===$frozenCounts && $quietOk,
    'real_two_closed_clients'=>count(array_unique($journal->closedIds))===2 && $journal->count('serverClosed')===2];
$details=['Сохранено первых записей'=>count($journal->events),'Пропущено после лимита'=>$journal->discarded,
    'Ограниченный журнал'=>$journal->events,'Полные счётчики по именам'=>$journal->counts,
    'topologyId закрытых заданий'=>$journal->closedIds,'Полученные экраны'=>$results,
    'Ограничение'=>'Буфер показывает начало, а не полную историю инцидента. В производстве нужны согласованные хранение/ротация/доставка; callback не должен делать блокирующий сетевой запрос'];
$runtime['server']=mt123BuildVersion($uri,$database);
$expected=[['экран каталога', 'CUP, LAMP', 2], ['карточка LAMP', 'LAMP', 1]];
$checks['expected_rows']=$rows===$expected;
mt123Report('mongodb123-topology-bounded-worker',['Задание', 'Реальные артикулы', 'Строк'],$rows,$checks,$runtime,$details);
echo 'mongodb123-topology-bounded-worker: OK',"\n";
Ожидаемый результат
mongodb123-topology-bounded-worker: OK

Все события вызываются настоящим драйвером при обращении к локальному MongoDB. В ZIP есть helper, README и исходные данные; собственные коллекции/сокеты освобождаются в finally. Нужен отдельный Standalone, описанный выше.

Открыть реальную таблицу и журнал · Строки JSON

Упражнение и направление решения. Поменяйте лимит 6 на 12 и сравните только число сохранённых/отброшенных записей, не придумывая неизменное число heartbeat. Сумма counts должна по-прежнему равняться saved+discarded. Полезные две таблицы товаров не должны измениться из-за размера журнала.

Снимки, события, девять callbacks и четыре способа регистрации

20 карточек сохраняют сигнатуры, параметры, возвращаемые значения, ошибки, версии и два применения в работающих программах. Методы интерфейса показываются как обработчики реальных уведомлений, а не как функции создания искусственного события.

APIПрактическая задача
MongoDB\Driver\TopologyDescription::getServersПолучить описания известных серверов из конкретного снимка топологии.
MongoDB\Driver\TopologyDescription::getTypeПрочитать строковый тип клиентской топологии.
MongoDB\Driver\TopologyDescription::hasReadableServerУзнать, содержит ли снимок сервер, пригодный для чтения.
MongoDB\Driver\TopologyDescription::hasWritableServerУзнать, есть ли в снимке сервер, пригодный для записи.
MongoDB\Driver\Monitoring\TopologyChangedEvent::getNewDescriptionПолучить новое описание из конкретного события изменения.
MongoDB\Driver\Monitoring\TopologyChangedEvent::getPreviousDescriptionСохранить состояние, непосредственно предшествовавшее этому изменению.
MongoDB\Driver\Monitoring\TopologyChangedEvent::getTopologyIdСвязать уведомления с одной клиентской топологией.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverChangedПринять уведомление: описание отдельного сервера изменилось.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverClosedПринять уведомление: сервер удалён из клиентской топологии.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatFailedПринять уведомление: служебная проверка hello завершилась неуспешно.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatStartedПринять уведомление: служебный hello отправлен для проверки сервера.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatSucceededПринять уведомление: служебный hello успешно выполнен.
MongoDB\Driver\Monitoring\SDAMSubscriber::serverOpeningПринять уведомление: новый сервер добавлен в клиентскую топологию.
MongoDB\Driver\Monitoring\SDAMSubscriber::topologyChangedПринять уведомление: описание клиентской топологии изменилось.
MongoDB\Driver\Monitoring\SDAMSubscriber::topologyClosedПринять уведомление: клиентская топология закрыта.
MongoDB\Driver\Monitoring\SDAMSubscriber::topologyOpeningПринять уведомление: клиентская топология открыта.
MongoDB\Driver\Monitoring\addSubscriberЗарегистрировать подписчик для событий всех Manager.
MongoDB\Driver\Manager::addSubscriberПривязать подписчик к конкретному Manager.
MongoDB\Driver\Monitoring\removeSubscriberСнять глобальную регистрацию конкретного подписчика.
MongoDB\Driver\Manager::removeSubscriberСнять привязку подписчика к конкретному Manager.

Связать мониторинг с реальным результатом операции

Полезный журнал отвечает на три вопроса: какому клиенту относится событие, что действительно изменилось в его описании и что получила сама прикладная операция. Сохраняйте точную пару old/new и topologyId, ограничивайте память, снимайте подписки по окончании области работы. Исторический true у снимка и successful heartbeat не отменяют обработку отказа следующего чтения или записи.

Следующие шаги: подробности ServerDescription и ServerChangedEvent, default-настройки Manager и фактический Server ответа, жизненный цикл Cursor, согласованность и выбор на replica set. Для диагностики бизнес-операций отдельно нужны их результаты и ошибки: квитанция пакетной записи и частичные отказы.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

MongoDB\Driver\TopologyDescription::getServersПолучить описания известных серверов из конкретного снимка топологии.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\TopologyDescription::getServers(): array

Получить описания известных серверов из конкретного снимка топологии.

final public MongoDB\Driver\TopologyDescription::getServers(): array

Параметры

Параметров нет.

Результат

Массив объектов MongoDB\Driver\ServerDescription. Это неизменяемые описания известных узлов в данном снимке, не Manager::getServers с объектами Server и не документы пользовательской коллекции.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Список относится к этому снимку и не заставляет драйвер искать новые узлы. Пустой список до handshake не означает, что вы никогда не задавали seed URI. Методы каждого ServerDescription подробно разобраны в соседней главе о снимках сервера.

Версии

Доступно с ext-mongodb 1.13.0.

Увидеть обнаруженный Standalone

$known = $snapshot->getServers();
foreach ($known as $description) { echo $description->getType(); }

После настоящего ping в снимке доступно описание Standalone; до него массив пуст.

Полный пример и исходные данные · Реальный журнал и таблица

Проверить основание пригодности для чтения

$known = $snapshot->getServers();
$isStandalone = count($known) === 1 && $known[0]->getType() === 'Standalone';

Проверка режима secondary объясняется известным Single, а не выдуманной второй репликой.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\TopologyDescription::getTypeПрочитать строковый тип клиентской топологии.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\TopologyDescription::getType(): string

Прочитать строковый тип клиентской топологии.

final public MongoDB\Driver\TopologyDescription::getType(): string

Параметры

Параметров нет.

Результат

Строка, соответствующая константе TopologyDescription::TYPE_*. Она обозначает вид топологии, а не признак доступности конкретного запроса.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Константы: TYPE_UNKNOWN="Unknown", TYPE_SINGLE="Single", TYPE_SHARDED="Sharded", TYPE_REPLICA_SET_NO_PRIMARY="ReplicaSetNoPrimary", TYPE_REPLICA_SET_WITH_PRIMARY="ReplicaSetWithPrimary", TYPE_LOAD_BALANCED="LoadBalanced". Не путайте Single у топологии со Standalone у ServerDescription. Примеры этой главы не воспроизводят все шесть видов.

Версии

Доступно с ext-mongodb 1.13.0.

Объяснить два разных статуса при одном Single

echo $before->getType(); // Single
echo $after->getType();  // Single

Пригодность меняется false→true, хотя способ прямого подключения остаётся прежним.

Полный пример и исходные данные · Реальный журнал и таблица

Не принять Single за успешное подключение

$type = $snapshot->getType(); // Single
$ready = $snapshot->hasReadableServer(); // false

Описание не теряет вид топологии лишь из-за того, что реальный handshake отказал.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\TopologyDescription::hasReadableServerУзнать, содержит ли снимок сервер, пригодный для чтения.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\TopologyDescription::hasReadableServer(?MongoDB\Driver\ReadPreference $readPreference = null): bool

Узнать, содержит ли снимок сервер, пригодный для чтения.

final public MongoDB\Driver\TopologyDescription::hasReadableServer(?MongoDB\Driver\ReadPreference $readPreference = null): bool

Параметры

readPreference — необязательный MongoDB\Driver\ReadPreference или NULL. Если передан объект, проверяется соответствие указанной политике. Сигнатура действительно содержит этот параметр; фраза «параметров нет» в одном блоке PHP.net является опиской.

Результат

bool: есть ли в данном описании читаемый сервер, либо сервер, подходящий переданной политике чтения.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Метод не выбирает новый сервер, не соединяется, не читает коллекцию и не проверяет права на неё. True не является разрешением безопасно игнорировать исключение следующей операции. Действительные правила зависят от Single, replica set, sharded и других топологий.

Версии

Доступно с ext-mongodb 1.13.0.

Сопоставить режимы на одном Single

$canRead = $snapshot->hasReadableServer(new MongoDB\Driver\ReadPreference('secondary'));

На доступном прямом Standalone значение true не означает наличие secondary replica.

Полный пример и исходные данные · Реальный журнал и таблица

Разделить плохую и хорошую диагностические точки

$failedReadable = $failedSnapshot->hasReadableServer(); // false
$healthyReadable = $healthySnapshot->hasReadableServer(); // true

Это два разных снимка и два topologyId, а не обновление одного старого значения.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\TopologyDescription::hasWritableServerУзнать, есть ли в снимке сервер, пригодный для записи.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\TopologyDescription::hasWritableServer(): bool

Узнать, есть ли в снимке сервер, пригодный для записи.

final public MongoDB\Driver\TopologyDescription::hasWritableServer(): bool

Параметры

Параметров нет.

Результат

bool: наличие writable-сервера в сохранённом описании топологии. Метод не выполняет пробную запись.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Writable-топология не гарантирует право пользователя менять конкретный документ, прохождение валидации, уникальность или требуемый write concern. Снимок может устареть. Положительный ответ не означает, что standalone стал primary replica set.

Версии

Доступно с ext-mongodb 1.13.0.

Показать готовность, которая появилась после обмена

$writable = $after->hasWritableServer(); // true

После обнаружения Standalone снимок содержит пригодный для записи узел.

Полный пример и исходные данные · Реальный журнал и таблица

Показать разные наблюдения двух клиентов

$first = $failedSnapshot->hasWritableServer(); // false
$second = $healthySnapshot->hasWritableServer(); // true

Неудачное подключение и отдельный здоровый стенд остаются разными историями.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\TopologyChangedEvent::getNewDescriptionПолучить новое описание из конкретного события изменения.

Метод существует с ext-mongodb 1.13.0. Public readonly свойства класса добавлены в 2.3.0. · mongodb

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getNewDescription(): MongoDB\Driver\TopologyDescription

Получить новое описание из конкретного события изменения.

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getNewDescription(): MongoDB\Driver\TopologyDescription

Параметры

Параметров нет.

Результат

Объект MongoDB\Driver\TopologyDescription с новым состоянием, которое сообщает событие.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Событие относится к изменению описания, не обязательно к смене типа топологии: Single может остаться Single, но сведения об узле изменятся. С 2.3.0 у события также есть публичное readonly-свойство newDescription; getter остаётся поддерживаемым способом чтения.

Версии

Метод существует с ext-mongodb 1.13.0. Public readonly свойства класса добавлены в 2.3.0.

Обновить отображаемый диагностический снимок

$snapshot = $event->getNewDescription();

Событие после успешного hello даёт читаемый Single со Standalone.

Полный пример и исходные данные · Реальный журнал и таблица

Хранить новое состояние отдельно от предыдущего

$history[] = ['old'=>$event->getPreviousDescription(), 'new'=>$event->getNewDescription()];

Старый объект остаётся false, а новый показывает true; оба сохранены как значения.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\TopologyChangedEvent::getPreviousDescriptionСохранить состояние, непосредственно предшествовавшее этому изменению.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getPreviousDescription(): MongoDB\Driver\TopologyDescription

Сохранить состояние, непосредственно предшествовавшее этому изменению.

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getPreviousDescription(): MongoDB\Driver\TopologyDescription

Параметры

Параметров нет.

Результат

Объект MongoDB\Driver\TopologyDescription с предыдущим описанием топологии для данного события.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Previous не означает «всегда самый первый снимок» и не запрашивает историю у сервера. Если необходима долговременная история, приложение само сохраняет нужные переходы. С 2.3.0 доступно также readonly-свойство previousDescription.

Версии

Доступно с ext-mongodb 1.13.0.

Построить честную пару до/после

$old = $event->getPreviousDescription();
$new = $event->getNewDescription();

Пара false→true относится к одному реальному событию обнаружения.

Полный пример и исходные данные · Реальный журнал и таблица

Объяснить разные истории отказа и успеха

$row['before'] = mt123Snapshot($event->getPreviousDescription());
$row['after'] = mt123Snapshot($event->getNewDescription());

Ограниченный журнал сохраняет пары отдельно для двух topologyId; успех второго не переписывает отказ первого.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\TopologyChangedEvent::getTopologyIdСвязать уведомления с одной клиентской топологией.

Доступно с ext-mongodb 1.13.0. · mongodb

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getTopologyId(): MongoDB\BSON\ObjectId

Связать уведомления с одной клиентской топологией.

final public MongoDB\Driver\Monitoring\TopologyChangedEvent::getTopologyId(): MongoDB\BSON\ObjectId

Параметры

Параметров нет.

Результат

MongoDB\BSON\ObjectId — идентификатор топологии события. Для текстового ключа журнала его можно явно преобразовать в строку.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов, согласно официальному контракту. Методы чтения описаний не выполняют новый сетевой запрос.

Это не _id товара, не серверный идентификатор кластера и не корреляционный ID пользовательского HTTP-запроса. Из-за persistence разные Manager могут использовать внутренний клиент; не выводите универсальное правило «любой new Manager всегда новый topologyId». С 2.3.0 есть readonly-свойство topologyId.

Версии

Доступно с ext-mongodb 1.13.0.

Различить каталог и импорт на одном host:port

$id = (string) $event->getTopologyId();
$latest[$id] = $event->getNewDescription();

Два непостоянных клиента имеют разные идентичности при одном endpoint.

Полный пример и исходные данные · Реальный журнал и таблица

Не смешать неудачную и успешную проверки

$history[] = ['id'=>(string)$event->getTopologyId(),
    'before'=>$event->getPreviousDescription(), 'after'=>$event->getNewDescription()];

Отчёт привязывает отдельные переходы к проверяемой точке и известному стенду.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverChangedПринять уведомление: описание отдельного сервера изменилось.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event): void

Принять уведомление: описание отдельного сервера изменилось.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerChangedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Например, Unknown превратился в Standalone при первом успешном обнаружении; secondary→primary — другой возможный случай, но здесь он не воспроизводится. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Обнаружение доступного Standalone

public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event): void {
    $this->counts['serverChanged'] = ($this->counts['serverChanged'] ?? 0) + 1;
}

Драйвер прислал serverChanged после реального hello.

Полный пример и исходные данные · Реальный журнал и таблица

Счётчик наблюдения каждой задачи

public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event): void {
    $this->counts['serverChanged'] = ($this->counts['serverChanged'] ?? 0) + 1;
}

Успешное обнаружение учитывается, даже если подробный буфер уже полон.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverClosedПринять уведомление: сервер удалён из клиентской топологии.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event): void

Принять уведомление: сервер удалён из клиентской топологии.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerClosedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Closed не означает команду shutdown mongod и не подтверждает остановку физического сервера. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Понять освобождение клиента

public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event): void {
    $this->counts['serverClosed'] = ($this->counts['serverClosed'] ?? 0) + 1;
}

serverClosed прислан при реальном уничтожении непостоянного клиента.

Полный пример и исходные данные · Реальный журнал и таблица

Завершить две независимые задачи

public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event): void {
    $this->counts['serverClosed'] = ($this->counts['serverClosed'] ?? 0) + 1;
}

Глобальный журнал учитывает два закрытия, хотя scoped-подписчики уже сняты.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatFailedПринять уведомление: служебная проверка hello завершилась неуспешно.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void

Принять уведомление: служебная проверка hello завершилась неуспешно.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Событие служебного мониторинга не заменяет исключение пользовательской операции. Не выводите из одного heartbeat отказ всего приложения или неизвестный исход записи. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Записать настоящую недоступность тестовой точки

public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void {
    $this->counts['serverHeartbeatFailed'] = ($this->counts['serverHeartbeatFailed'] ?? 0) + 1;
}

Собственный non-listening endpoint вызывает реальный failed heartbeat.

Полный пример и исходные данные · Реальный журнал и таблица

Отделить отказ первой проверки от успеха другой

public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void {
    $this->counts['serverHeartbeatFailed'] = ($this->counts['serverHeartbeatFailed'] ?? 0) + 1;
}

В одном ограниченном журнале присутствуют отказ и успех разных клиентов.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatStartedПринять уведомление: служебный hello отправлен для проверки сервера.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void

Принять уведомление: служебный hello отправлен для проверки сервера.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Начало не означает успех; результат сообщает succeeded или failed. Не обещайте одну фиксированную частоту или количество heartbeat для любого запроса. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Показать реальное начало обнаружения

public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void {
    $this->counts['serverHeartbeatStarted'] = ($this->counts['serverHeartbeatStarted'] ?? 0) + 1;
}

Начатый heartbeat предшествует обнаруженному Standalone.

Полный пример и исходные данные · Реальный журнал и таблица

Показать попытку, которая отказала

public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void {
    $this->counts['serverHeartbeatStarted'] = ($this->counts['serverHeartbeatStarted'] ?? 0) + 1;
}

Started есть и у неуспешной проверки, поэтому сам по себе не является зелёным статусом.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatSucceededПринять уведомление: служебный hello успешно выполнен.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void

Принять уведомление: служебный hello успешно выполнен.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Это успех проверки мониторинга, а не квитанция insert и не длительность запроса каталога. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Связать готовность с реальным обменом

public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void {
    $this->counts['serverHeartbeatSucceeded'] = ($this->counts['serverHeartbeatSucceeded'] ?? 0) + 1;
}

Журнал содержит успешный hello до нового читаемого снимка.

Полный пример и исходные данные · Реальный журнал и таблица

Подтвердить обмен со второй диагностической точкой

public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void {
    $this->counts['serverHeartbeatSucceeded'] = ($this->counts['serverHeartbeatSucceeded'] ?? 0) + 1;
}

Успех отдельного здорового клиента не стирает предыдущий failed heartbeat.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::serverOpeningПринять уведомление: новый сервер добавлен в клиентскую топологию.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void

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

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\ServerOpeningEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Opening не означает завершённый handshake или прочитанный товар. Событие описывает добавление наблюдаемого сервера. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Не показывать успех слишком рано

public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void {
    $this->counts['serverOpening'] = ($this->counts['serverOpening'] ?? 0) + 1;
}

Узел добавлен до получения положительного результата ping.

Полный пример и исходные данные · Реальный журнал и таблица

Связать добавление и удаление одного узла

public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void {
    $this->counts['serverOpening'] = ($this->counts['serverOpening'] ?? 0) + 1;
}

Opening и Closed относятся к одному endpoint и topologyId в настоящем lifecycle.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::topologyChangedПринять уведомление: описание клиентской топологии изменилось.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void

Принять уведомление: описание клиентской топологии изменилось.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\TopologyChangedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Используйте previous/new из одного события, сохраняйте topologyId и не предполагайте, что изменилось именно строковое имя типа. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Сохранить два разных значения

public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void {
    $this->counts['topologyChanged'] = ($this->counts['topologyChanged'] ?? 0) + 1;
}

Одно событие связывает старый нечитаемый и новый читаемый снимок.

Полный пример и исходные данные · Реальный журнал и таблица

Разнести изменения разных клиентов

public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void {
    $this->counts['topologyChanged'] = ($this->counts['topologyChanged'] ?? 0) + 1;
}

Карта latest индексируется настоящим topologyId, а не одним общим host.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::topologyClosedПринять уведомление: клиентская топология закрыта.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event): void

Принять уведомление: клиентская топология закрыта.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\TopologyClosedEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Из-за persistence событие наблюдается, когда Manager создан с disableClientPersistence и освобождён до request shutdown (RSHUTDOWN). Global-регистрация должна жить достаточно долго; ссылки Cursor/Server способны удерживать клиент. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Получить реальное закрытие до конца скрипта

public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event): void {
    $this->counts['topologyClosed'] = ($this->counts['topologyClosed'] ?? 0) + 1;
}

После освобождения последней ссылки приходит Closed, а новый ping подтверждает живой mongod.

Полный пример и исходные данные · Реальный журнал и таблица

Учесть завершение двух задач

public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event): void {
    $this->counts['topologyClosed'] = ($this->counts['topologyClosed'] ?? 0) + 1;
}

Оба непостоянных клиента закрыты, затем global-подписка снята.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\SDAMSubscriber::topologyOpeningПринять уведомление: клиентская топология открыта.

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется. · mongodb

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event): void

Принять уведомление: клиентская топология открыта.

abstract public MongoDB\Driver\Monitoring\SDAMSubscriber::topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event): void

Параметры

event — объект MongoDB\Driver\Monitoring\TopologyOpeningEvent, который передаёт драйвер зарегистрированному подписчику.

Результат

Возвращаемого значения нет (void). Это метод, который реализует ваш класс; он не является командой, вручную вызывающей событие.

Ошибки и границы

Официальная страница перечисляет InvalidArgumentException при ошибке разбора аргументов. Несоответствие сигнатуры реализации интерфейсу — ошибка PHP; возвращать значение из void нельзя. Обработчик не должен сам бросать исключение ради записи диагностического события.

Событие может не появиться при повторном использовании ранее сохранённого libmongoc-клиента. Global-подписку для полного начала ставят до создания Manager. Класс implements SDAMSubscriber должен реализовать все девять методов с правильными типами. В helper нет ручных вызовов этих callbacks. Обработчик лишь сохраняет ограниченные данные в память: не делает рекурсивных запросов к MongoDB, не отправляет письма и не блокирует работу сетевым логированием.

Версии

Интерфейс и метод доступны с ext-mongodb 1.13.0. С 1.15.0 возвращаемые типы объявлялись tentative на PHP 8.0+; с ext-mongodb 2.0.0 они обязательны. Текущая реализация явно объявляет : void; исторический ReturnTypeWillChange не используется.

Записать начало нового клиента

public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event): void {
    $this->counts['topologyOpening'] = ($this->counts['topologyOpening'] ?? 0) + 1;
}

Журнал заранее зарегистрирован, поэтому видит настоящее Opening.

Полный пример и исходные данные · Реальный журнал и таблица

Назвать две независимые диагностические истории

public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event): void {
    $this->counts['topologyOpening'] = ($this->counts['topologyOpening'] ?? 0) + 1;
}

Два явно непостоянных клиента дают две разные topologyId.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\addSubscriberЗарегистрировать подписчик для событий всех Manager.

Функция доступна с ext-mongodb 1.3.0; SDAMSubscriber — с 1.13.0. · mongodb

function MongoDB\Driver\Monitoring\addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Зарегистрировать подписчик для событий всех Manager.

function MongoDB\Driver\Monitoring\addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Параметры

subscriber — объект, реализующий подходящий интерфейс мониторинга, производный от Subscriber; в этой главе SDAMSubscriber.

Результат

Значение не возвращается. Меняется область доставки последующих событий этому объекту.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при неверных аргументах. Функция регистрирует/снимает объект; это не операция подключения и не команда MongoDB.

Повторное добавление того же объекта глобально — no-op. Если он также привязан к Manager, одно событие для этого Manager доставляется ему только один раз. Разные объекты не считаются одной регистрацией.

Версии

Функция доступна с ext-mongodb 1.3.0; SDAMSubscriber — с 1.13.0.

Общий журнал каталога и импорта

MongoDB\Driver\Monitoring\addSubscriber($journal);

Регистрация охватывает два независимых клиента; повторное добавление того же объекта не удваивает события.

Полный пример и исходные данные · Реальный журнал и таблица

Ограниченный журнал всего обработчика

MongoDB\Driver\Monitoring\addSubscriber($journal);

Общий объект наблюдает обе задачи с ограниченным буфером.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Manager::addSubscriberПривязать подписчик к конкретному Manager.

Метод существует с ext-mongodb 1.10.0. SDAMSubscriber появился в 1.13.0. · mongodb

final public MongoDB\Driver\Manager::addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Привязать подписчик к конкретному Manager.

final public MongoDB\Driver\Manager::addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Параметры

subscriber — объект подходящего интерфейса мониторинга. Область действия — данный Manager.

Результат

Возвращаемого значения нет (void). Метод изменяет подписку, а не данные коллекции.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при неверных аргументах. Также InvalidArgumentException, если передан LogSubscriber: логгеры разрешено регистрировать только глобально.

Повторная регистрация того же объекта в этом Manager — no-op. При одновременной global-регистрации одно событие для этого Manager не дублируется. Начало топологии может произойти до регистрации через уже созданный Manager; для полного lifecycle используйте заранее поставленный global-подписчик.

Версии

Метод существует с ext-mongodb 1.10.0. SDAMSubscriber появился в 1.13.0.

Наблюдать только каталог

$catalog->addSubscriber($onlyCatalog);

Scoped-журнал получает изменения каталога, а события отдельного импорта в него не попадают.

Полный пример и исходные данные · Реальный журнал и таблица

Подписка в границах задания

$worker->addSubscriber($scoped);

Каждое задание имеет собственного наблюдателя; повторная регистрация не нужна для повторной операции.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Monitoring\removeSubscriberСнять глобальную регистрацию конкретного подписчика.

Функция доступна с ext-mongodb 1.3.0; SDAMSubscriber — с 1.13.0. · mongodb

function MongoDB\Driver\Monitoring\removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Снять глобальную регистрацию конкретного подписчика.

function MongoDB\Driver\Monitoring\removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Параметры

subscriber — объект, реализующий подходящий интерфейс мониторинга, производный от Subscriber; в этой главе SDAMSubscriber.

Результат

Значение не возвращается. Меняется область доставки последующих событий этому объекту.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при неверных аргументах. Функция регистрирует/снимает объект; это не операция подключения и не команда MongoDB.

Если объект не зарегистрирован глобально, вызов — no-op. Снятие глобальной регистрации не снимает его отдельную привязку к Manager. Метод не останавливает сервер и не отменяет уже выполненные операции.

Версии

Функция доступна с ext-mongodb 1.3.0; SDAMSubscriber — с 1.13.0.

Общий журнал каталога и импорта

MongoDB\Driver\Monitoring\removeSubscriber($journal);

Глобальный журнал снимается после освобождения обоих клиентов; повторное снятие безопасно.

Полный пример и исходные данные · Реальный журнал и таблица

Ограниченный журнал всего обработчика

MongoDB\Driver\Monitoring\removeSubscriber($journal);

Контрольный клиент после снятия подписки не изменяет прежние счётчики.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

MongoDB\Driver\Manager::removeSubscriberСнять привязку подписчика к конкретному Manager.

Метод существует с ext-mongodb 1.10.0. SDAMSubscriber появился в 1.13.0. · mongodb

final public MongoDB\Driver\Manager::removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Снять привязку подписчика к конкретному Manager.

final public MongoDB\Driver\Manager::removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void

Параметры

subscriber — объект подходящего интерфейса мониторинга. Область действия — данный Manager.

Результат

Возвращаемого значения нет (void). Метод изменяет подписку, а не данные коллекции.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при неверных аргументах.

Если объект не был зарегистрирован с этим Manager, действие — no-op. Global-регистрация того же объекта продолжает действовать. Чтобы оставить наблюдение закрытия после освобождения Manager, в примерах используется отдельный глобальный журнал.

Версии

Метод существует с ext-mongodb 1.10.0. SDAMSubscriber появился в 1.13.0.

Наблюдать только каталог

$catalog->removeSubscriber($onlyCatalog);

Снятый scoped-журнал не меняется во время работы второго клиента.

Полный пример и исходные данные · Реальный журнал и таблица

Подписка в границах задания

$worker->removeSubscriber($scoped);

finally снимает scoped-подписку до закрытия клиента; общий журнал остаётся для lifecycle.

Полный пример и исходные данные · Реальный журнал и таблица

Как драйвер вызывает подписчик · Снимки отдельных серверов и ServerChangedEvent

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.