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

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

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

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

Глава 162 · После Manager, Query, объектов и регистрации SDAMSubscriber

MongoDB: heartbeat, ошибка адреса и понятная диагностика сервера

Настоящие started/succeeded/failed, служебный hello, микросекунды и время страницы, безопасный отчёт, readonly-свойства и ограниченная панель.

Почему ответ heartbeat ещё не готовая страница

Каталог должен показать доступные товары, а интеграция — связаться с нужной базой. Если экран пуст или ждёт соединения, полезно понять: драйвер ещё начал проверку узла, получил служебный ответ или столкнулся с ошибкой. Разберём настоящие heartbeat-события, получим товарные строки и соберём понятную запись об отказе без остановки общего сервера.

Проверка сервера и работа страницы — связанные, но разные действия
  1. Клиенту нужен узел → started: началась служебная проверка адреса
  2. Узел ответил → succeeded: reply и duration; иначе failed: error и duration
  3. Приложение выполняет Query → только два нужных товара → таблица с ценами
  4. Диагностический отчёт → адрес, исход, фактические измерения и следующий шаг

Представьте звонок в справочную, чтобы узнать, отвечает ли нужное отделение. Успешный звонок ещё не означает, что заказ оформлен и товар есть на складе. Аналогия объясняет различие задач, но не устройство сетевого протокола: настоящий heartbeat выполняет драйвер через служебный обмен hello, а не пользовательский обработчик магазина.

public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void {
    $this->lastReply = $event->getReply();
    $this->lastDurationUs = $event->getDurationMicros();
}

Это один метод наблюдателя: callback вызывается драйвером, $event уже содержит состоявшееся событие. -> читает метод объекта, а присваивание сохраняет результат в нашем наблюдателе. Полный класс реализует все девять методов SDAMSubscriber и находится в архиве первого примера. Здесь показан именно текущий маленький шаг, без всей служебной подготовки.

Предварительные темы: Manager, Query и выборка документов, подписчик и регистрация событий, снимок ServerDescription и hello. Пользовательские команды имеют свою трассу started/succeeded и свои ошибки.

Различить начало, успешную проверку и отказ

Событие / результатЧто уже известноЧего ещё нельзя утверждать
ServerHeartbeatStartedEventhost, port и streaming-флагЧто узел ответил; duration/reply/error отсутствуют
ServerHeartbeatSucceededEventУспешный служебный ответ, его duration и replyЧто Query вернул нужные товары или запись принята
ServerHeartbeatFailedEventНеудача проверки, её duration и ExceptionЧто любая ошибка означает выключенный mongod
Результат QueryТовары 101 и 102 с выбранными полямиЧто следующий запрос обязательно удастся
isAwaited()В текущем PHP всегда false: нет streaming monitoringДоступность узла, async-режим приложения или отсутствие ожидания

У трёх heartbeat-классов нет requestId пользовательской команды. В учебных программах каждый свежий клиент имеет отдельного наблюдателя и подпись, события сохраняются в своём порядке. Статус — наблюдение определённого момента, не бессрочная гарантия. Общий жизненный цикл клиента помогает понять, почему создание Manager и закрытие его ссылок тоже не равны success/failure.

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

Девять самостоятельных архивов требуют PHP 8.4+ CLI x64, ext-mongodb 2.5+ и отдельный MongoDB 8.0+ standalone. Проверяемая среда — PHP 8.5.11 / mongodb 2.5.5 / MongoDB 8.0.34. Composer не нужен. В каждом архиве example.php, hb125-helper.php и README.txt с установкой расширения, запуском локального mongod и пояснением всех ограничений.

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

Строки выполняются в PowerShell из распакованного каталога. README показывает подготовку отдельного dbpath и запуск mongod. Helper принимает только явный loopback-адрес, порт и учебное ASCII-имя базы; admin/local/config и URI с учётными данными отвергаются. Это ограничение лаборатории, а не описание всех допустимых MongoDB URI.

В четырёх программах создаётся ровно одна собственная коллекция с префиксом mongodb125_heartbeat_ и случайной частью. После трёх исходных товаров запрос выбирает только нужные два; finally удаляет только точное созданное имя и затем проверяет его отсутствие. Остальные пять программ не создают коллекций и читают служебные ответы.

В шести программах отказ возникает на сокете, который сам процесс зарезервировал без LISTEN. Никакая существующая служба не выключается. Отдельный Manager получает реальное неудачное подключение с ограниченными таймаутами, затем сокет освобождается. Ожидается конкретное внешнее исключение выбора сервера; прочие ошибки не скрываются.

Свежий непереиспользуемый клиент нужен этому опыту для первого обнаружения: disableClientPersistence=true, подписчик до первого I/O. Это не совет создавать новый Manager при каждом запросе посетителя. В callback не выполняются новые запросы. Наблюдатель хранит до 40 heartbeat-объектов и отдельный признак переполнения.

От служебной проверки к двум товарам на странице

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

Исходные данные и подготовка

Создаём три товара: Кабель — 900 коп., остаток 4; Чехол — 2500 коп., остаток 3; Зарядка — 3100 коп., остаток 0. Поле internal_note существует в базе, но не нужно странице. Перед первым обращением регистрируем наблюдателя.

Путь от действия к результату
  1. Manager создан → heartbeat-событий пока нет
  2. Первый buildInfo требует соединения → started → succeeded
  3. Query: stock > 0, три нужных поля, сортировка по ID, LIMIT 2
  4. Два товара → отдельная таблица; служебный ответ → диагностический блок

Самое маленькое действие

public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void {
    $this->reply = $event->getReply(); // ответ проверки; товары получит отдельный Query
}

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

Что получится

ТоварНазваниеЦена, коп.Что известно о соединении
101Кабель900служебный ответ получен
102Чехол2500служебный ответ получен

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Heartbeat — служебная проверка узла драйвером. В SDAMSubscriber метод serverHeartbeatSucceeded вызывается самим расширением после удачной проверки. Его параметр $event — готовый объект события. ->getReply() читает ответ этой проверки; это не коллекция товаров.

Сначала helper выполняет buildInfo, чтобы сохранить фактическую версию сервера. Это первое I/O — ввод-вывод по сети, для которого нужно соединение. До него событий нет, после него появился настоящий ответ. В приложении первым действием может быть обычный Query, а не buildInfo.

В executeQuery фильтр, projection, sort и limit задают требуемые данные на стороне MongoDB. Программа не загружает весь каталог для последующей сортировки PHP-массивом. toArray здесь применяется к результату, заранее ограниченному двумя записями.

В result.html рядом с товарами будут фактические host, port, awaited и длительность проверки. internal_note не выбирается и не попадает в таблицу. Разделите пользовательский экран и доступный разработчику диагностический отчёт и в своём сервисе.

Ошибки и границы применения

Успешная служебная проверка подтверждает ответ узла в этот момент. Она не подтверждает имя коллекции, пользовательские права, правильность фильтра, успешную запись или наличие товара. Эти действия имеют собственные результаты и ошибки.

Полная самостоятельная программа и архив
От служебной проверки к двум товарам на страницеСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$namespace=hb125Create($manager,$database,$owned);
$catalog=hb125Catalog($manager,$namespace);$reply=$succeeded->getReply();
$rows=[];foreach($catalog as $product){$rows[]=[$product['_id'],$product['title'],$product['price_kopecks'],'служебный ответ получен'];}
$observations['measurements']=['before_first_io'=>$beforeIo,'heartbeat_reply_type'=>get_class($reply),'returned_products'=>count($catalog)];
$checks=['selected_products'=>array_column($catalog,'_id')===[101,102],
    'actual_product_values'=>array_column($catalog,'price_kopecks')===[900,2500],
    'hello_success'=>(float)($reply->ok??0)===1.0,'private_field_not_selected'=>!array_key_exists('internal_note',$catalog[0])];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-catalog-ready', ['Товар', 'Название', 'Цена, коп.', 'Что известно о соединении'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-catalog-ready: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-catalog-ready: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

Попробуйте изменить. Поставьте у Чехла stock=0 в подготовке примера и измените ожидаемые ID на [101]. Таблица должна содержать один товар, но успешная проверка сервера останется отдельным фактом.

Прочитать настоящий hello и выбрать понятные поля диагностики

В обращении в поддержку написано «сервер ответил». Этого мало: полезно показать, в каком PHP-виде пришёл ответ, заявил ли узел роль для записи и какие сведения вообще были в настоящем служебном документе.

Исходные данные и подготовка

Здесь не создаются коллекции и не меняются настройки. Свежий клиент обращается к работающему учебному standalone. Событие succeeded даёт фактический reply; короткий белый список оставляет числовые и логические поля.

Путь от действия к результату
  1. Настоящий succeeded → getReply()
  2. BSON служебного ответа → stdClass по стандартным правилам
  3. Проверить isWritablePrimary, при отсутствии — ismaster
  4. Показать найденное имя поля и реальные значения отдельно от вывода

Самое маленькое действие

$reply = $event->getReply();
$primaryRole = $reply->isWritablePrimary ?? $reply->ismaster ?? null;
$documentLimitBytes = $reply->maxBsonObjectSize ?? null;

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

Что получится

Поле / задачаРезультатКак использовать
Ответ heartbeatstdClassчитаем поля через ->
Роль standaloneготов к записиэто роль, не права пользователя
Предел BSON-документаполучен в байтахфактическое значение ниже
Протокол helloподдерживаетсяэто не streaming awaited

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

stdClass — простой объект PHP с полями. Для него $reply->ok читает поле ok; запись $reply["ok"] потребовала бы массива. Это отличается от ServerDescription::getHelloResponse(), где контракт возвращает массив. Не переносите форму доступа между API наугад.

Служебный обмен может использовать прежние названия полей. Выражение ?? подставляет запасной вариант, если слева отсутствующее поле или NULL; значение false при этом сохраняется. В полной программе дополнительно записано, какое именно имя роли фактически присутствовало.

Роль, допускающая запись, и readOnly=false описывают сервер. Они не выдают права вашему пользователю и не заменяют результат write-команды. maxBsonObjectSize — предел одного документа в байтах, а не объём всей коллекции. Его реальное число показано ниже таблицы, без подстановки привычных 16 MiB.

helloOk сообщает о поддержке hello; isAwaited относится к другому вопросу — использован ли streaming-протокол мониторинга. Успешный современный hello и awaited=false совместимы.

Ошибки и границы применения

Поля зависят от версии и роли узла. В replica set, mongos и при другой конфигурации состав ответа отличается. Пример проверяет конкретные условия учебного standalone, а не объявляет их обязательными для любой MongoDB. Полный hello может содержать сведения, не предназначенные для публичного журнала.

Полная самостоятельная программа и архив
Прочитать настоящий hello и выбрать понятные поля диагностикиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$reply=$succeeded->getReply();$safe=hb125Hello($reply);
$roleField=property_exists($reply,'isWritablePrimary')?'isWritablePrimary':(property_exists($reply,'ismaster')?'ismaster':null);
if($roleField===null){throw new RuntimeException('Expected a primary-role field from the standalone lab');}
$role=$reply->$roleField;$limit=$reply->maxBsonObjectSize??null;
$readOnly=$reply->readOnly??null;$helloOk=$reply->helloOk??null;
$observations['measurements']=['reply_php_class'=>get_class($reply),'actual_role_field'=>$roleField,
    'actual_role_value'=>$role,'hello_capabilities'=>$safe];
$rows=[['Ответ heartbeat',get_class($reply),'читаем поля через ->'],
    ['Роль standalone',$role===true?'готов к записи':'не подтверждена','это роль, не права пользователя'],
    ['Предел BSON-документа',is_int($limit)&&$limit>0?'получен в байтах':'не получен','фактическое значение ниже'],
    ['Протокол hello',$helloOk===true?'поддерживается':'не заявлен','это не streaming awaited']];
$checks=['default_reply_stdclass'=>$reply instanceof stdClass,'role_true'=>$role===true,
    'capacity_positive'=>is_int($limit)&&$limit>0,'hello_supported'=>$helloOk===true,
    'server_not_readonly'=>$readOnly===false,'safe_fields_only'=>!array_key_exists('localTime',$safe)&&!array_key_exists('topologyVersion',$safe)];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-hello-capabilities', ['Поле / задача', 'Результат', 'Как использовать'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-hello-capabilities: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-hello-capabilities: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

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

Разделить время проверки сервера и получения страницы

Страница каталога иногда задерживается. Нужно измерить именно получение страницы и не сделать ложный вывод, что маленькое число в heartbeat автоматически означает быстрый запрос.

Исходные данные и подготовка

Используется тот же каталог из трёх товаров, но выбираются только два доступных. Один раз берём длительность служебной проверки. Другой интервал измеряем hrtime вокруг executeQuery и получения всех строк этой ограниченной страницы.

Путь от действия к результату
  1. Succeeded хранит длительность одной проверки в мкс
  2. hrtime перед Query → запрос и чтение двух строк → hrtime после
  3. Сравнить время страницы с учебным бюджетом 200000 мкс
  4. Показать оба измерения и фактический результат сравнения

Самое маленькое действие

$heartbeatUs = $event->getDurationMicros();
$start = hrtime(true);
$products = $cursor->toArray(); // полный пример измеряет также executeQuery
$fetchUs = intdiv(hrtime(true) - $start, 1000);

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

Что получится

Что измереноИсточникЕдиница / результат
Проверка сервераgetDurationMicros()микросекунды
Чтение страницы из двух товаровhrtime вокруг Query и получения строкмикросекунды
Решение о бюджете страницыпо измерению страницыфактический bool ниже

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

getDurationMicros() возвращает целое число микросекунд: 1000 мкс составляют 1 мс. Значение включает передачу служебного сообщения и получение ответа. Это не время выполнения пользовательского фильтра и не усреднённый RTT из ServerDescription.

hrtime(true) даёт монотонные наносекунды; intdiv разности на 1000 получает микросекунды. Начало полного примера стоит до executeQuery, конец после toArray. Мини-фрагмент отдельно иллюстрирует чтение уже полученного Cursor; его fetchUs не надо выдавать за время всего запроса.

В observations.json сохраняются heartbeat_us, query_and_fetch_us и bool page_within_example_budget. В программе нет утверждения «обязательно быстрее 200 мс»: на загруженной машине сравнение может дать false, и это честный результат измерения, а не сломанный опыт.

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

Ошибки и границы применения

Нельзя вычитать длительность heartbeat из времени страницы, считая остаток временем MongoDB. Интервалы могут относиться к разным действиям. Учитывайте сетевое ожидание, выбор сервера, передачу результата и обработку клиента отдельно там, где это требуется.

Полная самостоятельная программа и архив
Разделить время проверки сервера и получения страницыСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$namespace=hb125Create($manager,$database,$owned);
$begin=hrtime(true);$catalog=hb125Catalog($manager,$namespace);$queryUs=intdiv(hrtime(true)-$begin,1000);
$heartbeatUs=$succeeded->getDurationMicros();$pageBudgetUs=200000;$withinBudget=$queryUs<=$pageBudgetUs;
$observations['measurements']=['heartbeat_us'=>$heartbeatUs,'query_and_fetch_us'=>$queryUs,
    'example_page_budget_us'=>$pageBudgetUs,'page_within_example_budget'=>$withinBudget,'returned_products'=>count($catalog)];
$rows=[['Проверка сервера','getDurationMicros()','микросекунды'],
    ['Чтение страницы из двух товаров','hrtime вокруг Query и получения строк','микросекунды'],
    ['Решение о бюджете страницы','по измерению страницы','фактический bool ниже']];
$checks=['heartbeat_nonnegative'=>is_int($heartbeatUs)&&$heartbeatUs>=0,'query_nonnegative'=>$queryUs>=0,
    'actual_page_read'=>array_column($catalog,'_id')===[101,102],
    'budget_uses_application_time'=>$withinBudget===($queryUs<=$pageBudgetUs)];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-duration-boundaries', ['Что измерено', 'Источник', 'Единица / результат'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-duration-boundaries: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-duration-boundaries: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

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

Реальная постановка проблемы: Mongodb connection checkout is slow. Разработчик сопоставляет задержку получения подключения и команды с журналом heartbeat, где встречаются другие длительности и awaited=true. Это повод разделить измеряемые этапы и не переносить особенности Go-драйвера на PHP. Обсуждение относится к другой среде и не является контрактом PHP API; здесь дан самостоятельный локальный опыт, а правила методов сверены с официальной документацией.

Исправить адрес, когда проверка сервера не получила ответа

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

Исходные данные и подготовка

Рабочий MongoDB остаётся включённым. Для неработающего адреса процесс сам резервирует свободный loopback-порт без LISTEN. Отдельный Manager пробует ping на нём; затем рабочий Manager читает два товара из собственной учебной коллекции.

Путь от действия к результату
  1. Собственный порт зарезервирован, но на нём нет слушающего MongoDB
  2. Новый клиент → started → failed; выбор сервера заканчивается исключением
  3. Сохранить host, port и ошибку события без полного сообщения
  4. Использовать правильный endpoint → Query возвращает 101 и 102

Самое маленькое действие

$endpoint = [$event->getHost(), $event->getPort()];
$error = $event->getError(); // не внешний ConnectionTimeoutException автоматически
$diagnostic = ['class' => get_class($error), 'code' => $error->getCode()];

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

Что получится

Куда обращалисьНаблюдениеСледующий шаг / результат
Выделенный порт без LISTENheartbeat failedпроверить адрес и слушающую службу
Настроенный учебный MongoDBheartbeat succeededпрочитаны товары 101,102

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Endpoint — адрес конкретной службы: вместе host и port. Один и тот же 127.0.0.1 с другим портом ведёт к другой точке подключения. Поэтому одного hostname недостаточно в диагностике.

getError() читает Exception, связанное с неудачной служебной проверкой. Снаружи executeReadCommand завершается ConnectionTimeoutException после неуспешного выбора сервера. Это связанные, но разные объекты и уровни ошибки; полная программа сохраняет оба класса.

catch обрабатывает только ожидаемый ConnectionTimeoutException этого собственного адреса. Ошибки настройки примера, неожиданные исключения или внезапно отвечающий endpoint прерывают программу. Сокет освобождается в finally.

Исправление здесь не абстрактное «повторить ещё раз»: используются проверенные переменные рабочего учебного сервера, и результатом становятся реальные товарные строки. В рабочем сервисе сначала установите причину адреса и сетевого доступа, а не добавляйте бесконечные повторы.

Ошибки и границы применения

Опыт показывает один отказ на порту без слушателя. Он не воспроизводит DNS, TLS, firewall, аутентификацию или падение replica set и не определяет эти причины по одному числу ошибки. Настройки таймаутов не являются гарантией точной длительности процесса при любой нагрузке ОС.

Полная самостоятельная программа и архив
Исправить адрес, когда проверка сервера не получила ответаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$namespace=hb125Create($manager,$database,$owned);
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');
$catalog=hb125Catalog($manager,$namespace);$error=$failed->getError();
$observations['measurements']=['failed_endpoint'=>[$failed->getHost(),$failed->getPort()],
    'correct_endpoint'=>[$succeeded->getHost(),$succeeded->getPort()],
    'outer_exception_class'=>$failure['caught']['class'],'heartbeat_error_class'=>get_class($error),'recovered_product_ids'=>array_column($catalog,'_id')];
$rows=[['Выделенный порт без LISTEN','heartbeat failed','проверить адрес и слушающую службу'],
    ['Настроенный учебный MongoDB','heartbeat succeeded','прочитаны товары 101,102']];
$checks=['different_ports'=>$failed->getPort()!==$succeeded->getPort(),
    'actual_failed_exception'=>$error instanceof Exception,'outer_selection_timeout'=>$failure['caught']['class']===MongoDB\Driver\Exception\ConnectionTimeoutException::class,
    'recovered_catalog'=>array_column($catalog,'_id')===[101,102],'failure_duration_recorded'=>$failed->getDurationMicros()>=0];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-wrong-port-recovery', ['Куда обращались', 'Наблюдение', 'Следующий шаг / результат'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-wrong-port-recovery: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-wrong-port-recovery: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

Попробуйте изменить. Выведите в закрытом интерфейсе поддержки рабочий и ошибочный порт рядом. Ожидается одинаковый host и разные порты; не печатайте весь URI с возможными учётными данными.

Реальная постановка проблемы: mongoDB, connection refused. Подключение работает через loopback, но другой адрес приводит к connection refused. Вопрос показывает, почему адрес слушателя и адрес клиента нужно проверять явно. Обсуждение относится к другой среде и не является контрактом PHP API; здесь дан самостоятельный локальный опыт, а правила методов сверены с официальной документацией.

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

В сервисе работают каталог и интеграция. Каталог подключился, а интеграция нет. Одна общая зелёная лампа скрыла бы проблему; нужна небольшая таблица по потребителям и адресам.

Исходные данные и подготовка

У двух независимых клиентов разные endpoint: реальный учебный MongoDB и выделенный порт без LISTEN. Наблюдатели раздельные, поэтому метки «Каталог» и «Интеграция» принадлежат нашей программе, а не придумываются по совпадению адреса.

Путь от действия к результату
  1. Started сохраняет адрес попытки каждого клиента
  2. Succeeded или failed сохраняет адрес её завершения
  3. Сопоставить начала и окончания внутри одного наблюдателя
  4. Раздельно показать рабочий каталог и ошибочную интеграцию

Самое маленькое действие

$endpointKey = $event->getHost() . ':' . $event->getPort();
// Сохраняем также свою метку клиента: один endpoint может использоваться разными Manager.

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

Что получится

ПотребительФактический путьДействие
Каталогstarted → succeededоставить рабочий адрес
Интеграцияstarted → failedисправить адрес этой интеграции

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Started означает начало проверки и ещё не знает результата. Поэтому у него нет getReply(), getError() и getDurationMicros(). Для исхода нужен один из двух других классов.

В программе проверяется совпадение host/port начала и завершения каждой истории. Количество служебных повторов не фиксируется: не следует ожидать строго одну попытку при любой загрузке и настройке драйвера.

У heartbeat-событий нет requestId и operationId пользовательских команд. Для этой небольшой лаборатории используются отдельные наблюдатели и порядок событий. В общем наблюдателе большого процесса дополнительно продумайте границы клиентов; один endpoint может встречаться у разных Manager.

Таблица помогает направить действие адресно: конфигурацию каталога не нужно менять из-за сбоя другого подключения. Не путайте число созданных клиентов с числом физических серверов.

Ошибки и границы применения

host:port — удобный адрес, а не криптографическая идентичность узла. Этот опыт не тестирует переключение primary и не доказывает, что последующая команда будет успешной. Нельзя переносить хронологию двух коротких локальных историй на распределённую трассу без модели корреляции.

Полная самостоятельная программа и архив
Не объявить все подключения исправными по одной зелёной проверкеСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');
$goodStarted=hb125First($observer,'started');$badStarted=hb125First($failure['observer'],'started');
$matrix=[['label'=>'Каталог','start'=>[$goodStarted->getHost(),$goodStarted->getPort()],
    'end'=>[$succeeded->getHost(),$succeeded->getPort()],'outcome'=>'succeeded'],
    ['label'=>'Ошибочно настроенная интеграция','start'=>[$badStarted->getHost(),$badStarted->getPort()],
    'end'=>[$failed->getHost(),$failed->getPort()],'outcome'=>'failed']];
$observations['measurements']=['endpoint_matrix'=>$matrix];
$rows=[['Каталог','started → succeeded','оставить рабочий адрес'],['Интеграция','started → failed','исправить адрес этой интеграции']];
$checks=['healthy_start_matches_finish'=>$matrix[0]['start']===$matrix[0]['end'],
    'failed_start_matches_finish'=>$matrix[1]['start']===$matrix[1]['end'],
    'independent_endpoints'=>$matrix[0]['start']!==$matrix[1]['start'],'labels_not_merged'=>count($matrix)===2];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-endpoint-matrix', ['Потребитель', 'Фактический путь', 'Действие'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-endpoint-matrix: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-endpoint-matrix: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

Попробуйте изменить. Переименуйте метки клиентов в «Сайт» и «Фоновый импорт». Адреса и исходы должны остаться фактическими, а понятность отчёта для оператора — улучшиться.

Составить полезную запись об ошибке без полного errmsg и URI

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

Исходные данные и подготовка

Получаем реальный failed на принадлежащем процессу порту. Из события берём host, port, класс и код исключения, длительность. Отдельным полем сохраняем класс внешнего исключения выбора сервера.

Путь от действия к результату
  1. Failed → получить Exception, не бросая его заново
  2. Выбрать заранее оговорённые ключи отчёта
  3. Записать этап server-check и следующее действие
  4. Проверить отсутствие URI, message и trace в публичной записи

Самое маленькое действие

$error = $event->getError();
$log = ['class' => get_class($error), 'code' => $error->getCode(),
        'duration_us' => $event->getDurationMicros()];

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

Что получится

Часть отчётаЧто сохраняемЗачем
Этапserver-checkкоманда каталога ещё не отправлена этому адресу
Ошибка событиякласс и код Exceptionне угадываем по одной длительности
Публичный журналбелый список полейбез URI, message и trace
Рекомендацияпроверить адрес и службуне утверждаем, что любой сбой — выключенный сервер

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Белый список означает: мы вручную перечисляем разрешённые поля. Нельзя сначала сериализовать весь объект Exception и надеяться, что фильтр потом надёжно уберёт все чувствительные данные.

Класс и код — технические признаки, а не универсальный диагноз. Здесь известно, что порт зарезервирован без LISTEN, поэтому разумный шаг — проверить настроенный endpoint и слушающую службу. Другая ошибка требует другой проверки.

Сам getError() возвращает Exception и не повторяет его throw. Мы вызываем get_class и getCode, а getMessage/getTraceAsString в публичном файле не используем. Полное сообщение при необходимости можно хранить отдельно с соответствующим доступом и сроком хранения.

Длительность записана с суффиксом _us. Так человек или обработчик JSON не перепутает микросекунды с миллисекундами. Она помогает описать наблюдение, но по ней нельзя объявить причину отказа.

Ошибки и границы применения

Наш allowlist уменьшает объём публикуемых данных, но реальное приложение должно учитывать и чувствительность host/port. Для общего пользователя замените их разрешённой меткой среды. Это пример диагностического формата, а не готовая система контроля доступа или хранения инцидентов.

Полная самостоятельная программа и архив
Составить полезную запись об ошибке без полного errmsg и URIСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');$error=$failed->getError();
$incident=['stage'=>'server-check','host'=>$failed->getHost(),'port'=>$failed->getPort(),
    'error_class'=>get_class($error),'error_code'=>$error->getCode(),'duration_us'=>$failed->getDurationMicros(),
    'outer_exception_class'=>$failure['caught']['class'],'action'=>'check-configured-endpoint-and-listener'];
$encoded=json_encode($incident,JSON_THROW_ON_ERROR);$observations['measurements']=['incident'=>$incident];
$rows=[['Этап','server-check','команда каталога ещё не отправлена этому адресу'],
    ['Ошибка события','класс и код Exception','не угадываем по одной длительности'],
    ['Публичный журнал','белый список полей','без URI, message и trace'],
    ['Рекомендация','проверить адрес и службу','не утверждаем, что любой сбой — выключенный сервер']];
$checks=['actual_exception_object'=>$error instanceof Exception,'duration_nonnegative'=>$incident['duration_us']>=0,
    'exact_incident_schema'=>array_keys($incident)===['stage','host','port','error_class','error_code','duration_us','outer_exception_class','action'],
    'no_raw_connection_string'=>!str_contains($encoded,'mongodb://'),'no_message_or_trace'=>!array_key_exists('message',$incident)&&!array_key_exists('trace',$incident),
    'separate_exception_levels'=>$incident['outer_exception_class']!==$incident['error_class']];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-safe-incident', ['Часть отчёта', 'Что сохраняем', 'Зачем'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-safe-incident: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-safe-incident: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

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

Реальная постановка проблемы: Spring boot mongo time out while connecting with mongo driver. В журнале есть ошибка мониторинга узла и последующий общий таймаут выбора сервера. Эти сообщения описывают разные уровни неудачного подключения; одна внешняя ошибка недостаточна для объяснения всей причины. Обсуждение относится к другой среде и не является контрактом PHP API; здесь дан самостоятельный локальный опыт, а правила методов сверены с официальной документацией.

Прочитать 13 свойств трёх событий и не превратить их в настройки

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

Исходные данные и подготовка

Используем три настоящих объекта: started и succeeded рабочего сервера, failed отдельного ошибочного адреса. Сверяем 3 + 5 + 5 полей со значениями методов. По одному разу пробуем изменить host и ловим именно Error.

Путь от действия к результату
  1. Драйвер передал готовое событие
  2. Сравнить property с соответствующим getter
  3. Попытка присвоить host → Error
  4. Исходное событие сохраняет адрес; свою запись можно строить в отдельном массиве

Самое маленькое действие

$host = $event->host;          // mongodb 2.3+
$sameHost = $event->getHost(); // метод доступен с 1.13
// $event->host = 'other';    // Error: событие нельзя перенастроить

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

Что получится

СобытиеСвойствЧтениеЗапись
started3совпали с методамиизменение host отклонено
succeeded5совпали с методамиизменение host отклонено
failed5совпали с методамиизменение host отклонено

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

С mongodb 2.3.0 появились public readonly properties. readonly разрешает чтение, но не присваивание новой ссылки/значения самому свойству. У started их три; у succeeded и failed по пять.

Свойство duration соответствует методу getDurationMicros(), а не несуществующему свойству durationMicros. У успешного события reply — объект ответа, у неуспешного error — Exception. Эти два поля нельзя читать у противоположного типа события.

readonly — не обещание глубокой неизменяемости любого вложенного объекта. Не меняйте полученный stdClass reply для оформления: создайте отдельный массив только нужных полей. Диагностика должна описывать полученное событие, а не отредактированный документ.

Reflection показывает, что все три класса final и недоступны для обычного создания через new. В рабочем коде их получает callback от драйвера. Мы не создаём поддельное событие, чтобы нарисовать успешную проверку.

Ошибки и границы применения

Сами методы доступны с 1.13.0, а свойства требуют 2.3.0+. Версия сервера не сообщает версию PHP-расширения: проверяйте phpversion("mongodb") в той CLI/FPM-среде, где работает код. Повторять опасную запись свойства в обработчике каждого события не нужно — это демонстрация контракта.

Полная самостоятельная программа и архив
Прочитать 13 свойств трёх событий и не превратить их в настройкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');
$groups=[['started',$started,['host'=>'getHost','port'=>'getPort','awaited'=>'isAwaited']],
    ['succeeded',$succeeded,['host'=>'getHost','port'=>'getPort','awaited'=>'isAwaited','duration'=>'getDurationMicros','reply'=>'getReply']],
    ['failed',$failed,['host'=>'getHost','port'=>'getPort','awaited'=>'isAwaited','duration'=>'getDurationMicros','error'=>'getError']]];
$rows=[];$allEqual=true;$blocked=0;$observed=[];
foreach($groups as [$kind,$event,$fields]){
    $equal=true;foreach($fields as $property=>$method){if($event->$property!=$event->$method()){$equal=false;}}
    $before=$event->getHost();$rejected=false;
    try{$event->host='changed.invalid';}catch(Error $error){$rejected=true;unset($error);}
    if($rejected){$blocked++;}$allEqual=$allEqual&&$equal&&$event->getHost()===$before;
    $reflection=new ReflectionClass($event);$observed[]=['kind'=>$kind,'fields'=>array_keys($fields),'final'=>$reflection->isFinal(),'instantiable'=>$reflection->isInstantiable()];
    $rows[]=[$kind,count($fields),$equal?'совпали с методами':'не совпали',$rejected?'изменение host отклонено':'изменён'];
}
$observations['measurements']=['readonly_contract'=>$observed];
$checks=['thirteen_properties_match'=>$allEqual&&array_sum(array_column($rows,1))===13,'three_writes_rejected'=>$blocked===3,
    'three_final_noninstantiable'=>count(array_filter($observed,fn($v)=>$v['final']===true&&$v['instantiable']===false))===3];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-readonly-snapshots', ['Событие', 'Свойств', 'Чтение', 'Запись'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-readonly-snapshots: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-readonly-snapshots: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

Попробуйте изменить. Вместо изменения события создайте $display = ["host" => $event->getHost()] и добавьте в него подпись среды. Убедитесь, что оригинальное событие не меняется.

Не спутать awaited=false с зависанием или асинхронным PHP

В журнале другого драйвера встречается awaited=true, а в PHP всегда false. Нужно объяснить это поле, чтобы его не принимали за отказ сервера или настройку асинхронного исполнения.

Исходные данные и подготовка

Собираются started, succeeded и failed в тех же контролируемых условиях. Метод isAwaited и readonly property awaited проверяются на одном и том же объекте каждого вида.

Путь от действия к результату
  1. Три действительных класса heartbeat-событий
  2. Прочитать isAwaited() и awaited
  3. Получить false у всех трёх в PHP ext-mongodb
  4. Судить об успехе по виду события, а не по этому флагу

Самое маленькое действие

$streaming = $event->isAwaited(); // в текущем PHP-драйвере всегда false
// Не использовать как признак: «сервер недоступен» или «PHP работает async».

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

Что получится

СобытиеisAwaited()Что означает
startedfalsestreaming monitoring не используется
succeededfalsestreaming monitoring не используется
failedfalsestreaming monitoring не используется

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Streaming monitoring — способ служебного обмена, при котором запрос мониторинга может ожидать изменений. Это термин протокола проверки узла. Он не означает, что пользователь PHP применил await, Fibers или асинхронный Query.

Текущая документация PHP прямо указывает: расширение не использует streaming-протокол для мониторинга, поэтому все три isAwaited() возвращают false. Нельзя переносить true из примера Go или Java в ожидаемый результат PHP только потому, что сервер одинаковый.

В таблице успешный ответ и отказ имеют одинаковый false. Следовательно, if (!$event->isAwaited()) не является проверкой аварии. Успех или неуспех сообщает класс события и соответствующий callback.

В observations.json сохраняется фактическая версия расширения. Это делает вывод проверяемым и позволяет пересмотреть ожидание, если в будущем официальный контракт изменится.

Ошибки и границы применения

Флаг нельзя включить присваиванием awaited=true: свойство readonly. Это не переключатель нагрузки, таймаута и не гарантия отсутствия сетевого ожидания. Никакие настройки mongod в опыте не меняются.

Полная самостоятельная программа и архив
Не спутать awaited=false с зависанием или асинхронным PHPСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');
$events=[['started',$started],['succeeded',$succeeded],['failed',$failed]];$rows=[];$allFalse=true;
foreach($events as [$kind,$event]){
    $value=$event->isAwaited();$allFalse=$allFalse&&$value===false&&$event->awaited===$value;
    $rows[]=[$kind,$value,'streaming monitoring не используется'];
}
$observations['measurements']=['driver_extension'=>phpversion('mongodb'),'awaited_values'=>array_column($rows,1)];
$checks=['all_three_false'=>$allFalse,'healthy_and_failed_both_present'=>count($rows)===3&&$failed instanceof MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-awaited-contract', ['Событие', 'isAwaited()', 'Что означает'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-awaited-contract: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-awaited-contract: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

Попробуйте изменить. Сгруппируйте события по kind, оставив awaited отдельной колонкой. Должны остаться разные исходы succeeded и failed даже при одинаковом false.

Собрать небольшую панель: данные, проверка сервера и следующий шаг

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

Исходные данные и подготовка

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

Путь от действия к результату
  1. Query → названия и цены страницы
  2. Настоящие healthy/failed → отдельные диагностические статусы
  3. Полезное следующее действие для каждого подключения
  4. Последние 6 событий → панель; исходная ограниченная история → JSON

Самое маленькое действие

$recent = array_slice($observedEvents, -6); // уже ограниченная история учебного наблюдателя
// Статус подключения показываем рядом с результатом Query, не вместо товаров.

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

Что получится

Блок панелиРезультатПольза / действие
Каталогдва доступных товараКабель: 900 коп.; Чехол: 2500 коп.
Проверка рабочего сервераесть succeededрезультат Query проверен отдельно
Адрес интеграцииесть failedпроверить только адрес интеграции
Лента наблюденийне более 6 последних событийполная ограниченная история в observations.json

Фактический HTML также показывает реальные события, host, port, awaited, длительность в микросекундах и разрешённую диагностику. Эти изменяющиеся данные не подменяются эталонными числами из таблицы.

Почему это работает

Панель не заменяет полезный результат общей надписью OK. На ней есть Кабель за 900 коп. и Чехол за 2500 коп.; оператор может одновременно увидеть отказ неверно настроенного адреса интеграции.

array_slice(..., -6) выбирает последние шесть элементов уже ограниченной учебной истории. Сам по себе array_slice не ограничивает память, если до него накопили миллион событий. В долгоживущем сервисе используйте кольцевой буфер или отправляйте разрешённые записи по мере появления.

Числа healthy_checks и failed_checks в фактическом файле рассчитываются по полученным событиям. Они не фиксируются в эталоне, потому что драйвер может повторять служебные проверки. Количество попыток не равно количеству пользовательских запросов.

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

Ошибки и границы применения

В callback не отправляются запросы в MongoDB и не пишется через тот же наблюдаемый клиент. Иначе диагностика способна сама породить лишнюю работу или рекурсию. Публичный интерфейс и внутренние сведения об адресах должны иметь разный доступ.

Полная самостоятельная программа и архив
Собрать небольшую панель: данные, проверка сервера и следующий шагСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/hb125-helper.php';
$settings=hb125Settings();$database=$settings['database'];
$observer=new Hb125Observer;$manager=hb125Manager($settings,$observer);
$beforeIo=count($observer->events);$owned=[];$failure=null;
$observations=['events'=>[],'measurements'=>[]];
try{
$version=hb125Command($manager,$database,['buildInfo'=>1])[0]['version'];
if(version_compare($version,'8.0','<')){throw new RuntimeException('MongoDB 8.0+ required');}
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>$version,'execution'=>'database'];
$started=hb125First($observer,'started');$succeeded=hb125First($observer,'succeeded');
$namespace=hb125Create($manager,$database,$owned);
$failure=hb125Failure($database);$failed=hb125First($failure['observer'],'failed');
$catalog=hb125Catalog($manager,$namespace);$events=hb125Events($observer,'Каталог');
$errorEvents=hb125Events($failure['observer'],'Интеграция');$recent=array_slice(array_merge($events,$errorEvents),-6);
$stats=['healthy_checks'=>count(array_filter($events,fn($e)=>$e['kind']==='succeeded')),
    'failed_checks'=>count(array_filter($errorEvents,fn($e)=>$e['kind']==='failed')),'displayed_recent_events'=>count($recent)];
$observations['measurements']=['summary_counts'=>$stats,'recent_events'=>$recent,'catalog_ids'=>array_column($catalog,'_id')];
$rows=[['Каталог','два доступных товара','Кабель: 900 коп.; Чехол: 2500 коп.'],
    ['Проверка рабочего сервера','есть succeeded','результат Query проверен отдельно'],
    ['Адрес интеграции','есть failed','проверить только адрес интеграции'],
    ['Лента наблюдений','не более 6 последних событий','полная ограниченная история в observations.json']];
$checks=['useful_catalog'=>array_column($catalog,'_id')===[101,102]&&array_column($catalog,'price_kopecks')===[900,2500],
    'both_outcomes_real'=>$stats['healthy_checks']>=1&&$stats['failed_checks']>=1,
    'bounded_recent_log'=>count($recent)>0&&count($recent)<=6,'not_silent_overflow'=>!$observer->overflow&&!$failure['observer']->overflow];
    $checks['no_events_before_first_io']=$beforeIo===0;
    $checks['healthy_events_have_real_endpoint']=hb125EventChecks($observer,$settings,'succeeded');
    $observations['events']=array_merge(hb125Events($observer,'Учебный MongoDB'),
        $failure===null?[]:hb125Events($failure['observer'],'Зарезервированный порт без LISTEN'));
    $checks['failure_socket_released']=$failure===null || $failure['socket_closed'];
}finally{
    $manager->removeSubscriber($observer);
    foreach(array_reverse($owned) as $name){hb125Command($manager,$database,['drop'=>$name],true);}
}
$removed=true;foreach($owned as $name){if(hb125Exists($manager,$database,$name)){$removed=false;}}
$checks['only_owned_collections_removed']=$removed;
hb125Report('mongodb125-heartbeat-summary-panel', ['Блок панели', 'Результат', 'Польза / действие'], $rows, $checks, $runtime, $observations);
echo 'mongodb125-heartbeat-summary-panel: saved result.html and result.json
';
Ожидаемый результат
mongodb125-heartbeat-summary-panel: saved result.html and result.json

Настоящие heartbeat callbacks и сервер MongoDB. HTML/JSON показывают результат и реальные измерения; helper, README, ограничение журналов и очистка собственных ресурсов включены.

Открыть фактический результат и измерения · JSON таблицы · JSON настоящих наблюдений

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

Три класса и все их readonly properties

Класс событияПолный набор public readonly properties с 2.3Доступные сведения
Startedhost: string; port: int; awaited: boolАдрес и streaming-флаг
Succeededhost: string; port: int; awaited: bool; duration: int; reply: objectАдрес, длительность в мкс и служебный ответ
Failedhost: string; port: int; awaited: bool; duration: int; error: ExceptionАдрес, длительность в мкс и ошибка проверки

Свойства читаются через ->, методы — через ->имя(). Поле duration соответствует getDurationMicros. Методы доступны с 1.13.0; readonly properties появились в 2.3.0. Свойство не настройка подключения. Не меняйте вложенный reply ради оформления: копируйте разрешённые значения в свой массив.

Справочник: три класса и тринадцать методов

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

Класс или методДля чего пригодится
MongoDB\Driver\Monitoring\ServerHeartbeatStartedEventУзнать, что драйвер начал служебную проверку конкретного адреса.
MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEventПрочитать фактический результат успешной служебной проверки.
MongoDB\Driver\Monitoring\ServerHeartbeatFailedEventПрочитать адрес, длительность и Exception неудачной проверки сервера.
ServerHeartbeatStartedEvent::getHostПрочитать hostname адреса, проверка которого началась.
ServerHeartbeatStartedEvent::getPortПолучить порт, на котором началась проверка узла.
ServerHeartbeatStartedEvent::isAwaitedПрочитать признак streaming-протокола начатой проверки.
ServerHeartbeatSucceededEvent::getDurationMicrosПолучить длительность одной успешной проверки в микросекундах.
ServerHeartbeatSucceededEvent::getHostУказать hostname узла, ответившего на служебную проверку.
ServerHeartbeatSucceededEvent::getPortПрочитать порт успешной проверки сервера.
ServerHeartbeatSucceededEvent::getReplyПолучить служебный документ ответа heartbeat.
ServerHeartbeatSucceededEvent::isAwaitedУзнать, использовала ли успешная проверка streaming-протокол.
ServerHeartbeatFailedEvent::getDurationMicrosИзмерить длительность завершившейся неудачей служебной проверки.
ServerHeartbeatFailedEvent::getErrorПолучить Exception, связанное с неудачным heartbeat.
ServerHeartbeatFailedEvent::getHostНазвать hostname адреса неудачной проверки.
ServerHeartbeatFailedEvent::getPortУказать порт endpoint неудачной проверки.
ServerHeartbeatFailedEvent::isAwaitedПрочитать streaming-флаг неудачной служебной проверки.

От наблюдения к исправлению конкретного действия

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

Дальше: жизненный цикл клиентов и освобождение ссылок; команды, requestId и длительность запроса; различие командной ошибки и ошибки выбора сервера; ограниченные страницы и чтение партиями.

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

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

MongoDB\Driver\Monitoring\ServerHeartbeatStartedEventУзнать, что драйвер начал служебную проверку конкретного адреса.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final class MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
}

Узнать, что драйвер начал служебную проверку конкретного адреса.

final class MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
}

Это готовый объект, который PHP-драйвер передаёт в соответствующий метод SDAMSubscriber. final запрещает наследование. Публичного конструктора нет: не создавайте событие вручную и не вызывайте callback с выдуманным экземпляром.

Полный набор свойств класса

Readonly propertyТипЗначениеМетод чтения
hoststringHostname узлаgetHost()
portintПорт адреса узлаgetPort()
awaitedboolStreaming monitoring; в PHP falseisAwaited()

Все перечисленные свойства public readonly с mongodb 2.3.0. Методы доступны с 1.13.0 и остаются частью текущего API. Присваивание свойству вызывает Error; для собственного оформления создайте отдельный PHP-массив. Readonly не делает вложенные объекты универсально неизменяемыми.

Класс не является функцией с параметрами и возвращаемым значением: объект получает callback. Методы в приведённой полной сводке вызываются без аргументов; для них документирован MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Подробные значения каждого метода разобраны в карточках ниже.

Границы смысла

Событие ещё не содержит результата, длительности, ответа или ошибки. Оно не доказывает подключение приложения и не означает начало пользовательского Query. У одного клиента может быть несколько проверок.

Объяснить первое обращение каталога

В catalog-ready до первого I/O история пуста. После buildInfo появляется настоящий started; дальше отдельно появляются служебный ответ и две строки товаров. Так видно, почему создать Manager и получить данные — разные действия.

public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void {
    $this->events[] = ['host'=>$event->getHost(), 'port'=>$event->getPort()];
}

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

Развести попытки сайта и интеграции

В endpoint-matrix начальный адрес каждого клиента сопоставлен с его succeeded или failed. Одна зелёная история не закрывает проблему другого потребителя.

$attempt = [$started->getHost(), $started->getPort()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEventПрочитать фактический результат успешной служебной проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final class MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    public readonly int $duration;
    public readonly object $reply;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
    final public function getDurationMicros(): int;
    final public function getReply(): object;
}

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

final class MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    public readonly int $duration;
    public readonly object $reply;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
    final public function getDurationMicros(): int;
    final public function getReply(): object;
}

Это готовый объект, который PHP-драйвер передаёт в соответствующий метод SDAMSubscriber. final запрещает наследование. Публичного конструктора нет: не создавайте событие вручную и не вызывайте callback с выдуманным экземпляром.

Полный набор свойств класса

Readonly propertyТипЗначениеМетод чтения
hoststringHostname узлаgetHost()
portintПорт адреса узлаgetPort()
awaitedboolStreaming monitoring; в PHP falseisAwaited()
durationintДлительность проверки в микросекундахgetDurationMicros()
replyobjectДокумент ответа, стандартно stdClassgetReply()

Все перечисленные свойства public readonly с mongodb 2.3.0. Методы доступны с 1.13.0 и остаются частью текущего API. Присваивание свойству вызывает Error; для собственного оформления создайте отдельный PHP-массив. Readonly не делает вложенные объекты универсально неизменяемыми.

Класс не является функцией с параметрами и возвращаемым значением: объект получает callback. Методы в приведённой полной сводке вызываются без аргументов; для них документирован MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Подробные значения каждого метода разобраны в карточках ниже.

Границы смысла

reply описывает ответ проверки, а duration — её обмен с сервером. Наличие события не подтверждает пользовательские права или успех Query. В changelog 2.3 duration назван заменой getter; метод getDurationMicros остаётся в текущем API и реально вызывается в этих программах.

Подготовить сведения о возможностях узла

В hello-capabilities stdClass ответа превращается в небольшой allowlist. Программа показывает найденное поле роли и фактический предел BSON, не выдавая их за права пользователя.

$reply = $succeeded->getReply();
$limitBytes = $reply->maxBsonObjectSize ?? null;

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

Разобрать задержку страницы

В duration-boundaries длительность succeeded сохраняется рядом с отдельным временем настоящего Query. Учебный бюджет сравнивается именно со временем страницы.

$heartbeatUs = $succeeded->getDurationMicros();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

MongoDB\Driver\Monitoring\ServerHeartbeatFailedEventПрочитать адрес, длительность и Exception неудачной проверки сервера.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final class MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    public readonly int $duration;
    public readonly Exception $error;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
    final public function getDurationMicros(): int;
    final public function getError(): Exception;
}

Прочитать адрес, длительность и Exception неудачной проверки сервера.

final class MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent {
    public readonly string $host;
    public readonly int $port;
    public readonly bool $awaited;
    public readonly int $duration;
    public readonly Exception $error;
    final public function getHost(): string;
    final public function getPort(): int;
    final public function isAwaited(): bool;
    final public function getDurationMicros(): int;
    final public function getError(): Exception;
}

Это готовый объект, который PHP-драйвер передаёт в соответствующий метод SDAMSubscriber. final запрещает наследование. Публичного конструктора нет: не создавайте событие вручную и не вызывайте callback с выдуманным экземпляром.

Полный набор свойств класса

Readonly propertyТипЗначениеМетод чтения
hoststringHostname узлаgetHost()
portintПорт адреса узлаgetPort()
awaitedboolStreaming monitoring; в PHP falseisAwaited()
durationintДлительность проверки в микросекундахgetDurationMicros()
errorExceptionИсключение неудачной проверкиgetError()

Все перечисленные свойства public readonly с mongodb 2.3.0. Методы доступны с 1.13.0 и остаются частью текущего API. Присваивание свойству вызывает Error; для собственного оформления создайте отдельный PHP-массив. Readonly не делает вложенные объекты универсально неизменяемыми.

Класс не является функцией с параметрами и возвращаемым значением: объект получает callback. Методы в приведённой полной сводке вызываются без аргументов; для них документирован MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Подробные значения каждого метода разобраны в карточках ниже.

Границы смысла

Это не CommandFailedEvent пользовательского запроса и не гарантия конкретного класса внешнего исключения. У failed нет reply. Одно событие не позволяет автоматически приписать отказ firewall, TLS или аутентификации. duration и одноимённый getter доступны в текущем API.

Исправить неверный endpoint

В wrong-port-recovery настоящий failed относится к собственному порту без LISTEN. После выбора правильного адреса возвращаются товары 101 и 102; общий сервер не останавливается.

$failedEndpoint = [$failed->getHost(), $failed->getPort()];

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

Собрать компактный инцидент

В safe-incident сохраняются разрешённые поля Exception и длительность. Полный message, trace и URI не сериализуются в публичный файл.

$error = $failed->getError();
$record = ['class'=>get_class($error), 'code'=>$error->getCode()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatStartedEvent::getHostПрочитать hostname адреса, проверка которого началась.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getHost(): string

Прочитать hostname адреса, проверка которого началась.

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getHost(): string

Параметры и возвращаемое значение

Параметров нет. Строка hostname сервера из события. Здесь это 127.0.0.1; в другой среде допустимо DNS-имя. Это не полный URI, не база, не коллекция и не адрес посетителя.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Добавляйте порт и контекст клиента. Успешный результат пока неизвестен; getter только читает сохранённое поле и не инициирует новое подключение.

Зафиксировать начало подключения каталога

Первый started в catalog-ready даёт фактический hostname. Проверка события сравнивает его с разрешённой учебной настройкой; товары выводятся только после отдельного Query.

$host = $started->getHost();

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

Сопоставить разные истории

Endpoint-matrix показывает, что одинаковый host не делает рабочую и ошибочную интеграции одним адресом: их port различается.

$attempt = [$badStarted->getHost(), $badStarted->getPort()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatStartedEvent::getPortПолучить порт, на котором началась проверка узла.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getPort(): int

Получить порт, на котором началась проверка узла.

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::getPort(): int

Параметры и возвращаемое значение

Параметров нет. Целый номер порта сервера, указанного событием. В событии начала это адрес попытки; из одного числа нельзя сделать вывод, что на нём реально есть слушающий процесс.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Не путайте порт с ID соединения, операции, запроса или версией протокола. Для получения endpoint требуются оба поля host и port.

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

Catalog-ready проверяет совпадение фактического порта started с явно выбранным учебным портом. Это помогает не принять ответ другой локальной службы за нужную MongoDB.

$expectedPort = $started->getPort() === $settings['port'];

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

Найти, какой потребитель пошёл по ошибочному адресу

В endpoint-matrix порт начала истории интеграции совпадает с её failed, но отличается от порта каталога. Действие адресовано интеграции.

$sameAttempt = $badStarted->getPort() === $failed->getPort();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatStartedEvent::isAwaitedПрочитать признак streaming-протокола начатой проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::isAwaited(): bool

Прочитать признак streaming-протокола начатой проверки.

final public MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent::isAwaited(): bool

Параметры и возвращаемое значение

Параметров нет. Текущий контракт PHP возвращает false: расширение не использует streaming-протокол мониторинга. Это точное правило данного API, а не вероятность или настройка конкретного сервера.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Метод не сообщает, сколько нужно ждать, не включает async и не означает отказ соединения. Для исхода дождитесь succeeded или failed.

Разобрать одинаковый флаг при разных исходах

В awaited-contract started, succeeded и failed имеют false; выводит это одна таблица. Программа проверяет именно bool, не строку "false".

$value = $started->isAwaited(); // false

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

Перейти на свойства без изменения смысла

Readonly-snapshots сравнивает started.awaited с вызовом метода среди трёх полей события. Это проверяет совместимость чтения при обновлении расширения.

$same = $started->awaited === $started->isAwaited();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatSucceededEvent::getDurationMicrosПолучить длительность одной успешной проверки в микросекундах.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getDurationMicros(): int

Получить длительность одной успешной проверки в микросекундах.

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getDurationMicros(): int

Параметры и возвращаемое значение

Параметров нет. Целое число микросекунд, рассчитанное для проверки. В интервал входит отправка сообщения и получение ответа сервера. Это значение события, а не новая операция замера при каждом вызове getter.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Не подменяйте им время Query или RTT ServerDescription в миллисекундах. Нулевая длительность после округления допустима. Свойство duration с 2.3 содержит то же значение; метод сохранён в текущем API.

Сравнить нужное время с бюджетом страницы

Duration-boundaries хранит getDurationMicros отдельно от hrtime вокруг реальной выборки. Время страницы сравнивается с её бюджетом, heartbeat для этого не используется.

$heartbeatUs = $succeeded->getDurationMicros();

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

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

Summary-panel выводит фактическую длительность каждого завершённого heartbeat в таблице событий. Неизвестную длительность started показывает как NULL, а не 0.

$sample = ['duration_us'=>$succeeded->getDurationMicros()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatSucceededEvent::getHostУказать hostname узла, ответившего на служебную проверку.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getHost(): string

Указать hostname узла, ответившего на служебную проверку.

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getHost(): string

Параметры и возвращаемое значение

Параметров нет. Строка hostname из успешного heartbeat. Это адрес проверяемого узла; не постоянный идентификатор кластера и не доказательство источника каждой последующей бизнес-команды.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Сопоставляйте порт и метку клиента. Чтобы установить источник конкретного Query, используйте его Cursor/Server или командную трассу; событие heartbeat относится к служебному обмену.

Показать рабочее соединение рядом с каталогом

В catalog-ready адрес успешной проверки сохранён в фактическом отчёте рядом с двумя товарами. Проекция Query и её результат проверяются независимо.

$checkedHost = $succeeded->getHost();

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

Сравнить неверный и правильный адрес

Wrong-port-recovery сохраняет оба endpoint. В лаборатории host одинаков, но порт исправлен; это видно по значениям объектов, не по надписи «исправлено».

$correct = [$succeeded->getHost(), $succeeded->getPort()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatSucceededEvent::getPortПрочитать порт успешной проверки сервера.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getPort(): int

Прочитать порт успешной проверки сервера.

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getPort(): int

Параметры и возвращаемое значение

Параметров нет. Целый номер порта узла этого успешного события. В наших настройках обычно 27075, но пример читает фактическое значение и не вшивает его в эталон пользовательских результатов.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Успех одного порта нельзя переносить на другой порт того же хоста. Не делайте из этого значения номер сессии MongoDB.

Сопоставить начало и окончание проверки

Endpoint-matrix проверяет совпадение порта started и succeeded рабочего клиента; история ошибочной интеграции остаётся отдельной.

$samePort = $goodStarted->getPort() === $succeeded->getPort();

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

Проверить исправление конфигурации

В wrong-port-recovery успешный порт отличается от выделенного неслушающего, и рабочая выборка действительно получает товары.

$different = $failed->getPort() !== $succeeded->getPort();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatSucceededEvent::getReplyПолучить служебный документ ответа heartbeat.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getReply(): object

Получить служебный документ ответа heartbeat.

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::getReply(): object

Параметры и возвращаемое значение

Параметров нет. Объект ответа, преобразованного из BSON по стандартным правилам десериализации; корневой документ представлен stdClass. Вложенные значения следуют тем же правилам. Аргумента typeMap у этого метода нет.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Чтение не выполняет новый hello. Пользовательские товары находятся в результате Query, а не в reply. Проверяйте наличие полей и не публикуйте весь служебный документ автоматически. Для полного BSON-контракта см. страницу Persisting Data.

Описать возможности узла

Hello-capabilities читает роль с запасным именем ismaster и maxBsonObjectSize. Реальный тип stdClass и использованное имя поля сохраняются в observations.json.

$reply = $succeeded->getReply();
$role = $reply->isWritablePrimary ?? $reply->ismaster ?? null;

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

Разделить сеть и результат страницы

Catalog-ready проверяет ok служебного ответа и отдельно IDs/цены двух товаров. Даже ok=1 не подменяет проверку данных страницы.

$heartbeatAnswered = (float) ($succeeded->getReply()->ok ?? 0) === 1.0;

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatSucceededEvent::isAwaitedУзнать, использовала ли успешная проверка streaming-протокол.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::isAwaited(): bool

Узнать, использовала ли успешная проверка streaming-протокол.

final public MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent::isAwaited(): bool

Параметры и возвращаемое значение

Параметров нет. Всегда false в текущем PHP-расширении: оно не использует streaming monitoring. Успешность обмена задаётся классом SucceededEvent, а не значением этого флага.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Не считайте false ошибкой или отсутствием ожидания сети. helloOk и awaited имеют разный смысл; поддержка hello не включает streaming в PHP.

Правильно прочитать совместимые признаки

Hello-capabilities сохраняет helloOk и awaited в настоящем ответе/событии. Поддержка hello и false у isAwaited не противоречат друг другу.

$helloSupported = $succeeded->getReply()->helloOk ?? null;
$streamingUsed = $succeeded->isAwaited();

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

Проверить формат для трёх событий

Awaited-contract выводит bool успешного события рядом с началом и отказом. Это выявляет неверное правило «false = недоступно».

$streaming = $succeeded->isAwaited();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatFailedEvent::getDurationMicrosИзмерить длительность завершившейся неудачей служебной проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getDurationMicros(): int

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

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getDurationMicros(): int

Параметры и возвращаемое значение

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

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Это не весь serverSelectionTimeoutMS, не время Query и не календарная дата. Не делайте вывод «должно быть ровно 300000» только из connectTimeoutMS=300. Текущее readonly duration содержит то же число.

Показать, сколько заняла конкретная ошибка адреса

Wrong-port-recovery сохраняет измерение реального failed с собственным портом без LISTEN. Проверяется неотрицательность, а не заранее придуманная задержка.

$attemptUs = $failed->getDurationMicros();

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

Не потерять единицы в инциденте

Safe-incident кладёт значение в duration_us вместе с классом/кодом Exception. Оператор видит величину в правильных единицах, не принимая её за причину ошибки.

$record = ['duration_us'=>$failed->getDurationMicros()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatFailedEvent::getErrorПолучить Exception, связанное с неудачным heartbeat.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getError(): Exception

Получить Exception, связанное с неудачным heartbeat.

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getError(): Exception

Параметры и возвращаемое значение

Параметров нет. Объект Exception, описывающий отказ проверки. Сигнатура указывает общий Exception, а не обещает один конкретный подкласс на все причины. Getter возвращает сохранённый объект и не бросает его повторно.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Внешнее исключение executeReadCommand может отличаться: выбор подходящего сервера и одна проверка узла — разные уровни. getMessage/trace могут содержать чувствительные сведения; публичный allowlist не должен включать их автоматически.

Отделить две причины в цепочке наблюдений

Wrong-port-recovery сохраняет класс ошибки heartbeat отдельно от ConnectionTimeoutException, полученного вызывающим кодом. Оба относятся к настоящему отказу соединения, но не приравниваются.

$heartbeatErrorClass = get_class($failed->getError());

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

Подготовить запись для поддержки

Safe-incident читает get_class/getCode у возвращённого объекта, выбирая только оговорённые ключи. Проверяется отсутствие полного message и trace.

$error = $failed->getError();
$safe = ['class'=>get_class($error), 'code'=>$error->getCode()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatFailedEvent::getHostНазвать hostname адреса неудачной проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getHost(): string

Назвать hostname адреса неудачной проверки.

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getHost(): string

Параметры и возвращаемое значение

Параметров нет. Строка hostname сервера из события отказа. Это адрес, с которым связывалась проверка, а не доказательство существования или полного отсутствия сервиса на этом хосте.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Нужен также порт. Сам факт отказа не позволяет определить DNS/TLS/firewall или права; причина разбирается по окружению и допустимой диагностике.

Выделить ошибочную интеграцию

Endpoint-matrix использует hostname отказа вместе с началом этой же истории. Рабочий каталог имеет свою историю и не объявляется неисправным.

$sameHost = $badStarted->getHost() === $failed->getHost();

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

Записать место инцидента

Safe-incident сохраняет host отдельным полем allowlist. Для внешнего интерфейса его можно заменить разрешённой меткой среды, не сериализуя весь URI.

$location = ['host'=>$failed->getHost(), 'port'=>$failed->getPort()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatFailedEvent::getPortУказать порт endpoint неудачной проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getPort(): int

Указать порт endpoint неудачной проверки.

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::getPort(): int

Параметры и возвращаемое значение

Параметров нет. Целый номер порта из события. Формулировка API относится к адресу сервера; у failed она не доказывает, что на порту действительно работает слушатель.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

В этой лаборатории порт назначается ОС и меняется между запусками. Не вставляйте его в постоянную конфигурацию и не используйте как ID инцидента. Значение имеет смысл вместе с host и контекстом клиента.

Объяснить результат исправления адреса

Wrong-port-recovery сравнивает фактические порты failed и succeeded. После выбора рабочего адреса результатом становятся настоящие товары.

$wrongPort = $failed->getPort();
$workingPort = $succeeded->getPort();

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

Не объединить ошибку с другим сервисом того же хоста

Endpoint-matrix хранит start/end пары и проверяет их совпадение. На одной машине каталог и ошибочная интеграция различаются портом.

$failedEndpoint = [$failed->getHost(), $failed->getPort()];

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

ServerHeartbeatFailedEvent::isAwaitedПрочитать streaming-флаг неудачной служебной проверки.

mongodb 1.13.0; readonly properties 2.3.0 · mongodb

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::isAwaited(): bool

Прочитать streaming-флаг неудачной служебной проверки.

final public MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent::isAwaited(): bool

Параметры и возвращаемое значение

Параметров нет. Возвращает false по текущему контракту PHP: streaming-протокол мониторинга расширением не используется. Это не код ошибки и не утверждение, что ожидания не было.

Ошибки и версии

PHP Manual документирует MongoDB\Driver\Exception\InvalidArgumentException при ошибках разбора аргументов. Метод доступен с ext-mongodb 1.13.0; readonly property для того же поля появилось в 2.3.0. Версия MongoDB-сервера и версия PHP-расширения проверяются отдельно. Примеры используют PHP 8.5.11 и mongodb 2.5.5.

Границы смысла

Не используйте флаг для классификации причины отказа или переключения async-режима. Тип FailedEvent и getError сообщают о неудаче; awaited отвечает на другой вопрос.

Сопоставить отказ с успешной проверкой

Awaited-contract показывает одинаковый false у succeeded и failed, подтверждая, что это не индикатор доступности.

$failedStreaming = $failed->isAwaited();

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

Проверить переход к readonly-свойству

Readonly-snapshots сравнивает failed.awaited с методом среди пяти полей ошибки. Событие остаётся исходным снимком, попытка перенастроить host отклонена.

$same = $failed->awaited === $failed->isAwaited();

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

Основа: три разных этапа проверки; открытие, использование и закрытие клиента; отдельная трасса пользовательских команд.

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

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

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

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

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