Menu

[ru] SO-5.5.4: MPMC-mbox-ы, message_limits и ошибки redirect-а

2015-03-05
2015-03-05
  • Yauheni Akhotnikau

    Возник вопрос, связанный с реализацией message_limits. При превышении лимита можно предпринять одно из предусмотренных в SObjectizer-е действий: выбросить лишнее сообщение, прервать работу приложения, а так же переслать сообщение на другой mbox (это называется redirect).

    Так вот, при выполнении redirect-а можно столкнуться с ситуацией, когда на целевом mbox-е так же возникает превышение лимита и нужно выполнить еще одну операцию redirect, а на следующем целевом mbox-е -- очередное превышение лимита и т.д. В простейшем случае такая ситуация может возникнуть, если пользователь зациклил redirect (например, по ошибке редиректит сообщение на тот же mbox).

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

    Но этот вариант представляется однозначно правильным только, если первоначальная отсылка осуществлялась в direct_mbox. Т.е. пытались доставить сообщение конкретному агенту, это не удалось, поэтому исключение вполне уместно, т.к. оно говорит отправителю, что доставка не удалась.

    Однако, если речь идет о MPMC-mbox-ах, где получателей может быть несколько, прерывание всей доставки сообщения из-за сбоя на одном получателе -- это выглядит довольно странно. Т.е. может быть ситуация, когда за MPMC-mbox-ом спрятано 100 подписчиков. Первые 10 успешно получают сообщение. На 11-м происходит превышение лимита, серия операций redirect с зацикливанием и вылет по исключению. При этом попытки доставки сообщения до оставшихся 89 подписчиков не будет в принципе.

    Что, наверное, не всегда хорошо.

    Собственно, вопрос в том, как реагировать на невозможность корректного выполнения операции redirect при отсылке сообщения в MPMC-mbox?

    PS. Аналогичная проблема может быть и с операцией transform (при этой операции сообщение M, для которого обнаружено превышение лимита, преобразуется в новое сообщение другого типа N, которое отсылается на другой или тот же самый mbox).

     
  • Yauheni Akhotnikau

    Одно из возможных решений: при задании лимита с действием redirect для получателя указывается, что должно происходить в случае невозможности выполнения redirect-а.

    Например, если получатель согласен потерять сообщение, если переслать его другому обработчику не удалось, то это оформляется так:

    // В очереди не должно быть более 100 сообщений check_signature. 
    message_limit< check_signature >( 100 )
      // В случае превышения пересылаем сообщение логгеру, который
      // просто зафиксирует факт потери сообщения в журнале приложения.
      .redirect( drop_logger_mbox )
      // Если логгер не сможет принять это сообщение, то просто проигнорировать его.
      .drop_on_failure
    

    Другие возможные варианты:

    Логирование факта проблемы через error_logger самого SObjectizer-а:

    message_limit< check_signature >( 100 )
      .redirect( drop_logger_mbox )
      .log_on_failure
    

    Выбрасывание исключения и прерывание процедуры доставки сообщения. В этом случае, если в MPMC-mbox-е для сообщения 100 подписчиков, а ошибка возникла на 11-м, то подписчики 12..100 не получат сообщение вообще.

    message_limit< check_signature >( 100 )
      .redirect( drop_logger_mbox )
      .throw_on_failure
    

    Ну и, разумется, жесткое прибитие приложения посредством std::abort():

    message_limit< check_signature >( 100 )
      .redirect( drop_logger_mbox )
      .abort_on_failure
    
     

Log in to post a comment.