Как вы можете написать запас с динамом c динам? - PullRequest
6 голосов
/ 22 января 2020

Для чат-бота, который я реорганизую, не требуются блокировки для управления большей частью его состояния, веб-сайт, к которому он подключается через веб-сокет, регулирует сообщения, которые могут быть получены от обычных пользователей со скоростью 0,6 с, а озвученные пользователи - со скоростью 0,3 с, в то время как администраторы не имеют газа. Озвучен ли пользователь или администратор неизвестен до определенного момента после установления соединения; до этого каждый считался обычным пользователем.

В настоящее время я обрабатываю ограниченные сообщения, помещая блок react для прослушивания сообщений в al oop, который завершается после принудительного закрытия соединения. Когда дроссель обновляется, я вызываю done, чтобы войти в следующую итерацию, которая обновляет блок whenever для подачи сообщений для отправки, чтобы иметь обновленный дроссель. Это ужасный, грубый код!

Что я могу сделать, чтобы (а) убедиться, что соединение начинается с дросселем 0,3 с, который можно использовать сразу после установления соединения через веб-сокет, (б) сделать возможным вызвать метод, который обновляет этот газ, когда это необходимо, и (c) не сохранять никакого состояния, связанного с этим газом (что может быть выведено другими способами)?

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

Ответы [ 2 ]

6 голосов
/ 23 января 2020

Я нашел способ сделать это, используя комбинацию Supply.migrate, Supply.map и Supply.merge. Если я создаю поставщиков для дросселированных сообщений, нерегулируемых сообщений и обновлений дросселя, я могу сопоставить поставку обновлений дросселя с дросселированными источниками сообщений, дросселированными с использованием любых отправленных дросселей, вызвать Supply.migrate полученного источника и объединить его с источником нерегулируемых сообщений. , Это приводит к одному источнику, который я могу использовать для отправки всех типов сообщений:

react {
    my Supplier:D $unthrottled .= new;
    my Supplier:D $throttled   .= new;
    my Supplier:D $throttles   .= new;

    whenever Supply.merge(
        $unthrottled.Supply,
        $throttles.Supply.map({ $throttled.Supply.throttle: 1, $_ }).migrate,
    ) -> Str:D $message {
        say sprintf '%s @ %f', $message, now;
        done if ++$ == 12;
    }

    $throttles.emit: 1.2;
    $throttled.emit: "$_" for 1..3;
    whenever Promise.in(1) {
        $unthrottled.emit: "$_" for 7..9;
    }
    whenever Promise.in(5) {
        $throttles.emit: 0.6;
        $throttled.emit: "$_" for 4..6;
        whenever Promise.in(1) {
            $unthrottled.emit: "$_" for 10..12;
        }
    }
}

# OUTPUT:
# 1 @ 1579731916.713831
# 7 @ 1579731917.764047
# 8 @ 1579731917.769012
# 9 @ 1579731917.774584
# 2 @ 1579731917.913512
# 3 @ 1579731919.123057
# 4 @ 1579731921.749377
# 5 @ 1579731922.353073
# 10 @ 1579731922.768212
# 11 @ 1579731922.773777
# 12 @ 1579731922.780446
# 6 @ 1579731922.963087
1 голос
/ 22 января 2020

Интересно. Я дал ему go, и из того, что я прочитал в документации, которая редка, должно работать что-то вроде следующего:

my $s = Supply.from-list(^Inf);
my $control = Supplier.new.Supply;
my $throttle = $s.throttle( 10, 1, :$control );

react 
{
  whenever $throttle -> $n 
  { 
    $n.say 
  };

  # change speed every 5 seconds
  whenever Supply.interval(5) -> $x
  {
    "limit: { (1..10).pick }".say;
    $control.emit( "limit: { (1..10).roll }" );
  }
}

Но это не так. Программа зависает при нажатии $control.emit( ... ). Если вы это прокомментируете, он будет работать, как и ожидалось. Соответствующие do c части метода throttle:

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

[...]

Если второй позиционный параметр является значением цифры c, он интерпретируется как единица времени (в секундах). Если вы указываете значение .1 в качестве значения, то оно гарантирует, что вы не превысите предел для каждой десятой секунды.

[...]

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

[...]

Эти сообщения могут быть отправлены на: control Supply. Управляющее сообщение состоит из строки вида «ключ: значение», например, «предел: 4».

...