Reputation: 323
I've started to use Laravel 5.1 and its pretty awesome, just wanted to play around with the new 'Broadcasting Event' feature by using NodeJs as the server and Redis as the driver following the guide here: http://blog.nedex.io/laravel-5-1-broadcasting-events-using-redis-driver-socket-io/. When i fire an event which implements the ShouldBroadcast interface i receive an error: "Error while reading line from the server. [tcp://127.0.0.1:4365]"
4365 - is the port which the server is running on (listening in that port). Do you have any idea why does it happend?
I tried also to use Redis directly:
$redis = Redis::connection();
$redis->publish('test-channel', 'msg');
Got the same result, "Error while reading line from the server. [tcp://127.0.0.1:4365]".
socket.js:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('test-channel', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log('Message Recieved: ' + message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.payload);
});
http.listen(4365, function(){
console.log('Listening on Port 4365');
});
config\database.php:
'redis' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => 4365,
'database' => 0,
'timeout' => 100,
],
],
Tried to change the defulat timeout, set it to 0, -1 or >10 Also tried to disable Xdebug in php.ini the problem persists.
I made some debug deeply to the code trying to undertand what might cause this problem and it fails in class: Predis\Connection\StreamConnection
public function read()
{
$socket = $this->getResource();
$chunk = fgets($socket);
if ($chunk === false || $chunk === '') {
$this->onConnectionError('Error while reading line from the server.');
}
...
chunk is false why? And why does the redis client is trying to read data from the server, for my understanding it should 'publish' data to the server, means it should write (broadcast) not read..
Upvotes: 1
Views: 2125
Reputation: 58142
If you receive the above error, after x seconds (not straight away), then you need to set the read write timeout in your database.php config file.
If this is intended to run as a background task, something like the following will work:
'redis' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => '6379',
'database' => 0,
'read_write_timeout' => -1
],
],
Upvotes: 1
Reputation: 91
I think there is a misunderstanding of what Redis is and does.
Redis is an open source, BSD licensed, advanced key-value cache and store.
It is often used for interprocess communication (IPC) with it's nice PUBLISH and SUBSCRIBE commands.
So with Laravel and Node, Redis enables the communication between the permanently running process of Node and Laravel. Laravel publishs its events to Redis and Node subscribes to the specific channel of Redis. Here you can emit a message via socket connection most likely the channel names are the same.
To get this all working you have to to the following (very well explained in the docs):
Redis::publish('test-channel', json_encode(['foo' => 'bar']));
. Maybe its a Bug?ShouldBroadcast
. For testing purposes you can use this: Redis::publish('test-channel', json_encode(['foo' => 'bar']));
Now its time to switch over to Node:
Your code of socket.js looks good, assumed Redis is on Port 6379. If Node is running locally you can connect to your Node server in your Browser like so: localhost:4365
.
Here's my code testing Node and Socket.io in front- and backend:
socket.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
redis.subscribe('test-channel', function () {
console.log('Redis: test-channel subscribed');
});
redis.on('message', function(channel, message) {
console.log('Redis: Message on ' + channel + ' received!');
console.log(message);
message = JSON.parse(message);
io.emit(channel, message.payload)
});
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
index.html
<!doctype html>
<html>
<head>
<title>Socket.IO</title>
</head>
<body>
<ul id="messages">
<li>Hardcoded Message</li>
</ul>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
socket.on("test-channel", function(message) {
console.log(message);
$('#messages').append($('<li>').text(message));
});
</script>
</body>
</html>
I hope this helps a bit :)
Upvotes: 2