|
1
|
|
|
<?php
|
|
2
|
|
|
|
|
3
|
|
|
namespace yiicod\socketio\commands;
|
|
4
|
|
|
|
|
5
|
|
|
use Symfony\Component\Process\Process;
|
|
6
|
|
|
use Yii;
|
|
7
|
|
|
use yii\helpers\ArrayHelper;
|
|
8
|
|
|
use yii\helpers\Console;
|
|
9
|
|
|
use yii\helpers\Json;
|
|
10
|
|
|
use yiicod\socketio\Broadcast;
|
|
11
|
|
|
|
|
12
|
|
|
trait CommandTrait
|
|
13
|
|
|
{
|
|
14
|
|
|
/**
|
|
15
|
|
|
* @var string
|
|
16
|
|
|
*/
|
|
17
|
|
|
public $server = 'locahost:1212';
|
|
18
|
|
|
|
|
19
|
|
|
/**
|
|
20
|
|
|
* [
|
|
21
|
|
|
* key => 'path to key',
|
|
22
|
|
|
* cert => 'path to cert',
|
|
23
|
|
|
* ]
|
|
24
|
|
|
*
|
|
25
|
|
|
* @var array
|
|
26
|
|
|
*/
|
|
27
|
|
|
public $ssl = [];
|
|
28
|
|
|
|
|
29
|
|
|
/**
|
|
30
|
|
|
* Process job by id and connection
|
|
31
|
|
|
* @param $handler
|
|
32
|
|
|
* @param $data
|
|
33
|
|
|
* @param $id
|
|
34
|
|
|
*/
|
|
35
|
|
|
public function actionProcess($handler, $data, $id)
|
|
36
|
|
|
{
|
|
37
|
|
|
Broadcast::process($handler, @json_decode($data, true) ?? [], $id);
|
|
38
|
|
|
}
|
|
39
|
|
|
|
|
40
|
|
|
public function nodejs()
|
|
41
|
|
|
{
|
|
42
|
|
|
// Automatically send every new message to available log routes
|
|
43
|
|
|
Yii::getLogger()->flushInterval = 1;
|
|
44
|
|
|
|
|
45
|
|
|
$cmd = sprintf('node %s/%s', realpath(dirname(__FILE__) . '/../server'), 'index.js');
|
|
46
|
|
|
$args = array_filter([
|
|
47
|
|
|
'server' => $this->server,
|
|
48
|
|
|
'pub' => json_encode(array_filter([
|
|
49
|
|
|
'host' => Broadcast::getDriver()->hostname,
|
|
50
|
|
|
'port' => Broadcast::getDriver()->port,
|
|
51
|
|
|
'password' => Broadcast::getDriver()->password,
|
|
52
|
|
|
])),
|
|
53
|
|
|
'sub' => json_encode(array_filter([
|
|
54
|
|
|
'host' => Broadcast::getDriver()->hostname,
|
|
55
|
|
|
'port' => Broadcast::getDriver()->port,
|
|
56
|
|
|
'password' => Broadcast::getDriver()->password,
|
|
57
|
|
|
])),
|
|
58
|
|
|
'channels' => implode(',', Broadcast::channels()),
|
|
59
|
|
|
'nsp' => Broadcast::getManager()->nsp,
|
|
60
|
|
|
'ssl' => empty($this->ssl) ? null : json_encode($this->ssl),
|
|
61
|
|
|
'runtime' => Yii::getAlias('@runtime/logs'),
|
|
62
|
|
|
], 'strlen');
|
|
63
|
|
|
foreach ($args as $key => $value) {
|
|
64
|
|
|
$cmd .= ' -' . $key . '=\'' . $value . '\'';
|
|
65
|
|
|
}
|
|
66
|
|
|
|
|
67
|
|
|
$process = new Process($cmd);
|
|
|
|
|
|
|
68
|
|
|
|
|
69
|
|
|
return $process;
|
|
70
|
|
|
}
|
|
71
|
|
|
|
|
72
|
|
|
/**
|
|
73
|
|
|
* Predis proccess
|
|
74
|
|
|
*/
|
|
75
|
|
|
public function predis()
|
|
76
|
|
|
{
|
|
77
|
|
|
$pubSubLoop = function () {
|
|
78
|
|
|
$client = Broadcast::getDriver()->getConnection(true);
|
|
79
|
|
|
|
|
80
|
|
|
// Initialize a new pubsub consumer.
|
|
81
|
|
|
$pubsub = $client->pubSubLoop();
|
|
82
|
|
|
|
|
83
|
|
|
$channels = [];
|
|
84
|
|
|
foreach (Broadcast::channels() as $key => $channel) {
|
|
85
|
|
|
$channels[$key] = $channel . '.io';
|
|
86
|
|
|
}
|
|
87
|
|
|
|
|
88
|
|
|
// Subscribe to your channels
|
|
89
|
|
|
$pubsub->subscribe(ArrayHelper::merge(['control_channel'], $channels));
|
|
90
|
|
|
|
|
91
|
|
|
// Start processing the pubsup messages. Open a terminal and use redis-cli
|
|
92
|
|
|
// to push messages to the channels. Examples:
|
|
93
|
|
|
// ./redis-cli PUBLISH notifications "this is a test"
|
|
94
|
|
|
// ./redis-cli PUBLISH control_channel quit_loop
|
|
95
|
|
|
/** @var object $message */
|
|
96
|
|
|
foreach ($pubsub as $message) {
|
|
|
|
|
|
|
97
|
|
|
switch ($message->kind) {
|
|
98
|
|
|
case 'subscribe':
|
|
99
|
|
|
$this->output("Subscribed to {$message->channel}\n");
|
|
|
|
|
|
|
100
|
|
|
break;
|
|
101
|
|
|
case 'message':
|
|
102
|
|
|
if ('control_channel' == $message->channel) {
|
|
103
|
|
|
if ('quit_loop' == $message->payload) {
|
|
104
|
|
|
$this->output("Aborting pubsub loop...\n", Console::FG_RED);
|
|
|
|
|
|
|
105
|
|
|
$pubsub->unsubscribe();
|
|
106
|
|
|
} else {
|
|
107
|
|
|
$this->output("Received an unrecognized command: {$message->payload}\n", Console::FG_RED);
|
|
|
|
|
|
|
108
|
|
|
}
|
|
109
|
|
|
} else {
|
|
110
|
|
|
$payload = Json::decode($message->payload);
|
|
111
|
|
|
$data = $payload['data'] ?? [];
|
|
112
|
|
|
$id = $payload['id'] ?? '';
|
|
113
|
|
|
|
|
114
|
|
|
// $pid = pcntl_fork();
|
|
115
|
|
|
// if ($pid == -1) {
|
|
116
|
|
|
// exit('Error while forking process.');
|
|
117
|
|
|
// } elseif ($pid) {
|
|
118
|
|
|
// //parent. Wait for the child and continues
|
|
119
|
|
|
// pcntl_wait($status);
|
|
120
|
|
|
// $exitStatus = pcntl_wexitstatus($status);
|
|
121
|
|
|
// if ($exitStatus !== 0) {
|
|
122
|
|
|
// //put job back to queue or other stuff
|
|
123
|
|
|
// }
|
|
124
|
|
|
// }else {
|
|
125
|
|
|
Broadcast::on($payload['name'], $data, $id);
|
|
126
|
|
|
// Yii::$app->end();
|
|
127
|
|
|
// }
|
|
128
|
|
|
// Received the following message from {$message->channel}:") {$message->payload}";
|
|
129
|
|
|
}
|
|
130
|
|
|
break;
|
|
131
|
|
|
}
|
|
132
|
|
|
}
|
|
133
|
|
|
|
|
134
|
|
|
// Always unset the pubsub consumer instance when you are done! The
|
|
135
|
|
|
// class destructor will take care of cleanups and prevent protocol
|
|
136
|
|
|
// desynchronizations between the client and the server.
|
|
137
|
|
|
unset($pubsub);
|
|
138
|
|
|
};
|
|
139
|
|
|
|
|
140
|
|
|
// Auto recconnect on redis timeout
|
|
141
|
|
|
try {
|
|
142
|
|
|
$pubSubLoop();
|
|
143
|
|
|
} catch (\Predis\Connection\ConnectionException $e) {
|
|
144
|
|
|
$pubSubLoop();
|
|
145
|
|
|
}
|
|
146
|
|
|
|
|
147
|
|
|
return true;
|
|
148
|
|
|
}
|
|
149
|
|
|
}
|
|
150
|
|
|
|
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: