ReactPHP-使用Laravel和计时器

ReactPHP-使用Laravel和计时器,laravel,websocket,reactphp,Laravel,Websocket,Reactphp,这是我遇到的一个非常有趣的问题。我一心想弄清楚如何将websocket客户端集成到Laravel5.5中,以便在我的应用程序和客户端之间通过websocket进行通信。我开发了一个新的Laravel应用程序,并通过构建在其上的composer实现了这一点 在此之后,我正试图构建一个PHP Discord机器人,我曾经使用过它,但在它使用的一个主要应用程序停止使用后,我放弃了它 我已经想出了如何添加一个计时器,以便像这样发送 $app->addTimer(x, function ($thin

这是我遇到的一个非常有趣的问题。我一心想弄清楚如何将websocket客户端集成到Laravel5.5中,以便在我的应用程序和客户端之间通过websocket进行通信。我开发了一个新的Laravel应用程序,并通过构建在其上的composer实现了这一点

在此之后,我正试图构建一个PHP Discord机器人,我曾经使用过它,但在它使用的一个主要应用程序停止使用后,我放弃了它

我已经想出了如何添加一个计时器,以便像这样发送

$app->addTimer(x, function ($thing) use ($etc) {});
在我的应用程序收到来自Discord的事件之前,这一切都能正常工作。然后同步就丢失了,我的应用程序开始每隔3-9秒发送一次心跳信号,有时一次发送2到3次,而不是按照确定的时间间隔发送心跳信号。以下是控制台出于调试原因的一些输出,但它显示了我的问题:

"Sending Heartbeat - 41 - 2017-12-31 05:26:42"
"Sending Heartbeat - 41 - 2017-12-31 05:26:42"
Illuminate\Support\Collection {#679
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
Illuminate\Support\Collection {#679
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:26:51"
Illuminate\Support\Collection {#602
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:26:55"
Illuminate\Support\Collection {#695
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:26:56"
Illuminate\Support\Collection {#688
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
Illuminate\Support\Collection {#688
  #items: array:4 [
    "t" => "TYPING_START"
    "s" => 7
    "op" => 0
    "d" => array:3 [
      "user_id" => "277968564827324416"
      "timestamp" => 1514698064
      "channel_id" => "394991263344230411"
    ]
  ]
}
Illuminate\Support\Collection {#688
  #items: array:4 [
    "t" => "MESSAGE_CREATE"
    "s" => 8
    "op" => 0
    "d" => array:15 [
      "type" => 0
      "tts" => false
      "timestamp" => "2017-12-31T05:27:47.057000+00:00"
      "pinned" => false
      "nonce" => "396897209817235456"
      "mentions" => []
      "mention_roles" => []
      "mention_everyone" => false
      "id" => "396897202448105494"
      "embeds" => []
      "edited_timestamp" => null
      "content" => "!about"
      "channel_id" => "394991263344230411"
      "author" => array:4 [
        "username" => "David Davaham"
        "id" => "277968564827324416"
        "discriminator" => "2471"
        "avatar" => "0c27e1bed49121e8aaf3f284d6b74e55"
      ]
      "attachments" => []
    ]
  ]
}
Illuminate\Support\Collection {#688
  #items: array:4 [
    "t" => "MESSAGE_CREATE"
    "s" => 9
    "op" => 0
    "d" => array:15 [
      "type" => 0
      "tts" => false
      "timestamp" => "2017-12-31T05:27:49.382000+00:00"
      "pinned" => false
      "nonce" => null
      "mentions" => array:1 [
        0 => array:4 [
          "username" => "David Davaham"
          "id" => "277968564827324416"
          "discriminator" => "2471"
          "avatar" => "0c27e1bed49121e8aaf3f284d6b74e55"
        ]
      ]
      "mention_roles" => []
      "mention_everyone" => false
      "id" => "396897212199862276"
      "embeds" => []
      "edited_timestamp" => null
      "content" => "<@!277968564827324416> Unfortunately That is not a command I recognize. Please try again. Reply with `!help` for a list of commands"
      "channel_id" => "394991263344230411"
      "author" => array:5 [
        "username" => "Claire Underwood (Dev)"
        "id" => "394988052360986635"
        "discriminator" => "8397"
        "bot" => true
        "avatar" => null
      ]
      "attachments" => []
    ]
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:12"
Illuminate\Support\Collection {#616
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:23"
"Sending Heartbeat - 41 - 2017-12-31 05:27:23"
Illuminate\Support\Collection {#622
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
Illuminate\Support\Collection {#622
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:32"
Illuminate\Support\Collection {#652
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:36"
Illuminate\Support\Collection {#667
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:37"
Illuminate\Support\Collection {#661
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:46"
Illuminate\Support\Collection {#663
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:49"
Illuminate\Support\Collection {#660
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:51"
Illuminate\Support\Collection {#656
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:27:53"
Illuminate\Support\Collection {#698
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:28:04"
"Sending Heartbeat - 41 - 2017-12-31 05:28:04"
Illuminate\Support\Collection {#701
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
Illuminate\Support\Collection {#701
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:28:13"
Illuminate\Support\Collection {#706
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:28:17"
Illuminate\Support\Collection {#707
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41 - 2017-12-31 05:28:18"
Illuminate\Support\Collection {#709
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
有人知道如何更好地管理心跳吗?或者这只是我需要容忍的事情吗


还有,有人对我的做法有什么建议或批评吗?我找不到任何关于如何执行此操作的可靠文档,因此我正在将其拼凑起来。

因此,此问题已得到解决。以下是我的发现:

使用概述的代码,执行以下代码块时:

if (!$this->is_ready) {
    ...
    if ($message->get('op') == 0) {
        if ($message->get('t') === "READY" || $message->get('t') === "GUILD_CREATE") {
            $this->is_ready = true;
            $this->seq = $message->get('s');
        }
    }
    ...
}
由于
$this->is_ready
被设置为
true
,因此会导致添加两个计时器。除此之外,因为我已经准备好了
的代码如下:

if ($this->is_ready) {
     if ($message->get('op') == 0) {
         if ($message->get('t') === "MESSAGE_CREATE") {
             $trigger = config('discord.message.trigger');
             $data = $message->get('d');
             $msgContent = $data['content'];
             if (starts_with($msgContent, $trigger)) {
                 ProcessMessage::dispatch($data);
             }
         }
     }
     $now = Carbon::now();
     $loop->addTimer($this->heartbeat, function ($x) use ($now, $conn, $socket) {
         dump("Sending Heartbeat - " . $this->heartbeat . " - " .$now->toDateTimeString());
         $payload = collect([
             'op' => 1,
             'd' => (int)$this->seq,
         ]);
         $conn->send($payload->toJson());
     });
 }
if ($message->get('op') == 0) {
    if ($message->get('t') === "READY" || $message->get('t') === "GUILD_CREATE") {
        $this->is_ready = true;
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
if ($this->is_ready) {
    if ($message->get('op') == 0) {
        if ($message->get('t') === "MESSAGE_CREATE") {
            $trigger = config('discord.message.trigger');
            $data = $message->get('d');
            $msgContent = $data['content'];
            if (starts_with($msgContent, $trigger)) {
                ProcessMessage::dispatch($data);
            }
        }
    } else {
        $now = Carbon::now();
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
每次我收到一个新事件时,都会安排另一个计时器,导致计时器堆叠,并在计时器过期时发送心跳信号。这导致计时器最终每秒被发送多次,如果我不想让它这样的话。以下是我所做的更改:

我在第一个块中添加了一个计时器,如下所示:

if ($this->is_ready) {
     if ($message->get('op') == 0) {
         if ($message->get('t') === "MESSAGE_CREATE") {
             $trigger = config('discord.message.trigger');
             $data = $message->get('d');
             $msgContent = $data['content'];
             if (starts_with($msgContent, $trigger)) {
                 ProcessMessage::dispatch($data);
             }
         }
     }
     $now = Carbon::now();
     $loop->addTimer($this->heartbeat, function ($x) use ($now, $conn, $socket) {
         dump("Sending Heartbeat - " . $this->heartbeat . " - " .$now->toDateTimeString());
         $payload = collect([
             'op' => 1,
             'd' => (int)$this->seq,
         ]);
         $conn->send($payload->toJson());
     });
 }
if ($message->get('op') == 0) {
    if ($message->get('t') === "READY" || $message->get('t') === "GUILD_CREATE") {
        $this->is_ready = true;
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
if ($this->is_ready) {
    if ($message->get('op') == 0) {
        if ($message->get('t') === "MESSAGE_CREATE") {
            $trigger = config('discord.message.trigger');
            $data = $message->get('d');
            $msgContent = $data['content'];
            if (starts_with($msgContent, $trigger)) {
                ProcessMessage::dispatch($data);
            }
        }
    } else {
        $now = Carbon::now();
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
这会导致循环停止处理该计时器,但在底部,我在发送心跳信号后取消计时器。我不确定这是否重要,因为它只是一个
计时器,而不是
周期计时器,但我不认为它有什么坏处

接下来,我将
is_ready
if语句重组如下:

if ($this->is_ready) {
     if ($message->get('op') == 0) {
         if ($message->get('t') === "MESSAGE_CREATE") {
             $trigger = config('discord.message.trigger');
             $data = $message->get('d');
             $msgContent = $data['content'];
             if (starts_with($msgContent, $trigger)) {
                 ProcessMessage::dispatch($data);
             }
         }
     }
     $now = Carbon::now();
     $loop->addTimer($this->heartbeat, function ($x) use ($now, $conn, $socket) {
         dump("Sending Heartbeat - " . $this->heartbeat . " - " .$now->toDateTimeString());
         $payload = collect([
             'op' => 1,
             'd' => (int)$this->seq,
         ]);
         $conn->send($payload->toJson());
     });
 }
if ($message->get('op') == 0) {
    if ($message->get('t') === "READY" || $message->get('t') === "GUILD_CREATE") {
        $this->is_ready = true;
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
if ($this->is_ready) {
    if ($message->get('op') == 0) {
        if ($message->get('t') === "MESSAGE_CREATE") {
            $trigger = config('discord.message.trigger');
            $data = $message->get('d');
            $msgContent = $data['content'];
            if (starts_with($msgContent, $trigger)) {
                ProcessMessage::dispatch($data);
            }
        }
    } else {
        $now = Carbon::now();
        $loop->addTimer(20, function ($x) use ($conn,$loop) {
            dump("Sending Heartbeat - " . $this->heartbeat . " - " .Carbon::now()->toDateTimeString());
            $payload = collect([
                'op' => 1,
                'd' => (int)$this->seq,
            ]);
            $conn->send($payload->toJson());
            $loop->cancelTimer($x);
        });
    }
}
请注意,我仅在
op
code不等于0时安排计时器。我依赖于这样一个事实:之前的
心跳
已经安排好并将运行。这几乎是一种保证,只要在服务器启动时执行第一个

这是控制台到目前为止的输出,它已经用这个配置运行了大约五到十分钟,没有双心跳,或者任何东西

"Sending Heartbeat - 41.25 - 2017-12-31 08:41:18"
Illuminate\Support\Collection {#702
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:41:38"
Illuminate\Support\Collection {#704
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:41:58"
Illuminate\Support\Collection {#706
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:42:18"
Illuminate\Support\Collection {#708
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:42:39"
Illuminate\Support\Collection {#710
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
Illuminate\Support\Collection {#712
  #items: array:4 [
    "t" => "PRESENCE_UPDATE"
    "s" => 7
    "op" => 0
    "d" => array:6 [
      "user" => array:1 [
        "id" => "277968564827324416"
      ]
      "status" => "idle"
      "roles" => []
      "nick" => null
      "guild_id" => "394991263344230409"
      "game" => null
    ]
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:42:59"
Illuminate\Support\Collection {#712
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}
"Sending Heartbeat - 41.25 - 2017-12-31 08:43:19"
Illuminate\Support\Collection {#717
  #items: array:4 [
    "t" => null
    "s" => null
    "op" => 11
    "d" => null
  ]
}

如果你有任何问题,请随时联系我。如果您想查看,此代码最终将提交到my Github上的公共回购。目前,回购协议是私人的。查看我的个人资料以获得指向我的GitHub的链接。

我知道这个问题很老,但您可能想使用库。