Does R have thrift bindings? - r

Apache Thrift is a way to declare data types and interfaces. You can compile the thrift into many other languages, called "bindings." Is there a compiler than can produce an R binding for thrift? I don't see one.

Still in its early adoption phase, but you can try: thriftr
service PingPong {
string ping(),
}
Server:
library(thriftr)
pingpong_thrift = thriftr::t_load("pingpong.thrift",
module_name="pingpong_thrift")
Dispatcher <- R6::R6Class("Dispatcher",
public = list(
ping = function() {
return('pong')
}
)
)
server = thriftr::make_server(pingpong_thrift$PingPong, Dispatcher$new(),
'127.0.0.1', 6000)
server$serve()
Client:
library(thriftr)
pingpong_thrift = thriftpy::t_load("pingpong.thrift",
module_name="pingpong_thrift")
client = thriftpy::make_client(pingpong_thrift$PingPong, "127.0.0.1", 6000)
cut(client$ping())

Related

Callback style API on socket connection readable in R

I have an R script which consumes a feed periodically and then produces signals or actions, which need to be sent to a TCP server implemented in other language. I have handled the signal generation part in this fashion:
sendViaSocket <- function(object, socket) {
byteLen <- as.integer(object$byteLen())
writeBin(
byteLen, socket,
endian = "little",
useBytes = TRUE
)
writeBin(
object$toRaw(), socket,
useBytes = TRUE
)
}
readFromSocket <- function(socket) {
packetLen <- readBin (
socket, integer(), endian = "little"
)
rawVec <- readBin(
socket, "raw", n = packetLen
)
return (
parse (messages.MyMessage, rawVec)
)
}
getOHLC <- function() {
# feed reading function
...
}
generateSignal <- function (candleStick) {
# signal generating function
...
}
performAction <- function(message) {
# Action on server message
}
clientLoop <- function() {
socket <- socketConnection(
host = 'localhost',
port = 42000,
blocking = TRUE,
server = FALSE,
open = "a+b"
)
while(TRUE) {
candleStick <- getOHLC()
signal <- generateSignal(candleStick)
sendViaSocket(signal, socket)
# Reading any message from server
object <- readFromSocket(message)
Sys.sleep(10)
}
}
clientLoop()
I have deliberately set the socket connection as blocking as I want to read all the data available in the connection in one go, and send message in one go.
Currently I am reading any notification from client loop itself, but if the server does not send anything, the client loop is blocked.
What I want to do is have a callback when the socket has received any data, and then process that data in the callback. This will not block the client loop. Something along the following lines
onServerDataReceived <- function (serverMessage) {
# Perform related action on receiving server message
}
socket$onDataReceived(callback = onServerDataReceived)
Is there a way in which I can use a client socket connection with a callback when the server actually sends a message/ or do this in a reactive / asynchronous way?
Edit: As a bonus I also don't want to do while (TRUE) {...} and use an API or package that provides a better way to call the clientLoop() function periodically every n seconds (minimum interval is 30 seconds)

Connect to redis cluster in R

Suppose there were several hosts and ports of the redis server, like
10.0.1.1:6381
10.0.1.1:6382
10.0.1.2:6381
10.0.1.2:6382
how can I configure the redux::hiredis()?
I have google around but can't find a solution. And I noticed that there was a note on db parameter of the redis_config function with "Do not use in a redis clustering context.", so I was wondering that this was a way to connect to a cluster. In addition, I have also try to pass redis://10.0.1.1:6381,10.0.1.1:6382,10.0.1.2:6381,10.0.1.2:6382 to the url parameter, but still failed.
Any suggestions? Or is there another package you would suggest?
My initial solution is writing a function to point to the correct node based on the error message.
check_redis <- function(key = "P10000", host = "10.0.1.1", port = 6381) {
r <- redux::hiredis(host = host, port = port)
status <- tryCatch(
{
r$EXISTS(key = key)
},
error = function(e){
address <- str_match(e$message,
"[0-9]+.[0-9]+.[0-9]+.[0-9]+:[0-9]+")
host <- str_split(address, ":", simplify = T)[1]
port <- str_split(address, ":", simplify = T)[2]
return(list(host = host, port = port))
}
)
if (is.list(status)) {
r <- redux::hiredis(host = status$host, port = status$port)
}
return(r)
}
It can help to direct to the correct node, but this solution is neither elegant nor efficient. So please advise.

Unix Domain Sockets instead of host/port for TCP-type server

This is for all Node.js versions 6+
Say I have currently have a TCP server with multiple clients:
const server = net.createServer(s => {
});
server.listen(6000);
and I connect to it with clients:
const s1 = net.createConnection({port:6000});
const s2 = net.createConnection({port:6000});
const s3 = net.createConnection({port:6000});
TCP can sometimes be a bit slow on a local machine. I hear that there might be a way to substitute a host/port combination with Unix Domain Sockets, but maintain the TCP server style interface. Is this possible and how?
The Node.js docs mention you can create a server that listens on a path:
https://nodejs.org/api/net.html#net_server_listen_path_backlog_callback
but it doesn't specify what kind of file that needs to be and how to create that file.
It turns out on MacOS/Linux this is easy. You don't need to create the file. You need to make sure the file does not exist, and then point the Node.js core libraries to an empty path.
For the server:
const udsPath = path.resolve('some-path.sock');
const wss = net.createServer(s => {
});
wss.listen(udsPath, () => {
});
For the clients:
const udsPath = path.resolve('some-path.sock'); // same file path as above
const ws = net.createConnection(udsPath, () => {
});

Connecting to socket.io socket with R

I am trying to connect to a socket.io socket in R using the R function socketConnection(). However, although I am able to set up the socket properly, I am not able to read data from it into R.
The javascript code I use to set up the server is:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(8005);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
setInterval(function() {
socket.emit('update', "test")
}, 1000);
});
The code for index.html is:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost:8005');
socket.on('update', function (data) {
console.log(data);
});
</script>
I am able to verify that the socket is indeed working by going to localhost:8005 in my web browser and opening up the Developer's Console, where I can see "test" being logged. However, when I try to connect to the socket in R by:
sock <- socketConnection("localhost", 8005, blocking = FALSE, open = "r")
readLines(sock)
Every time I run readLines(sock) I get an empty character vector back. I have also confirmed I can read from other sockets in R by executing the following and indeed getting a response from readLines(sock):
sock <- socketConnection("rstudio.com", 6789, blocking = FALSE, open = "r")
readLines(sock)
Any help would be greatly appreciated. Thanks!
UPDATE (2015-09-01):
Thanks to the excellent help from Aaron Dufour, I was able to adapt this net server demo to stream data into R. The javascript code I used for the server was
var net = require('net');
var server = net.createServer(function(socket) {
setInterval(function() {
socket.write('Test\r\n');
socket.pipe(socket);
}, 1000)
});
server.listen(1337, '127.0.0.1');
And the R code was:
sock <- socketConnection("localhost", 1337, open = "r")
readLines(sock)
close(sock)
I did get the following warning warning: possible EventEmitter memory leak detected. 11 end listeners added. Use emitter.setMaxListeners() to increase limit. sometimes on the server side when I ran readLines(socket)
Also, when I ran close(socket) in R the server crashed and I get the following error: Error: This socket has been ended by the other party
With additional research, I think both the warning and error are preventable.
As I've described here, the socket.io protocol is much more than a WebSocket. Just opening a WebSocket to it won't work.
But socketConnection appears to not even be a WebSocket, but rather a raw socket. You're getting nothing back because the server is talking HTTP and you haven't finished sending an HTTP request.
You probably need a socket.io library for R, or to switch away from socket.io on the server.

.net micro framework and socket.io

I have 2 questions:
question (1):
I want to connect my Gadgeteer who works on .net micro framework v4.2 via TCP to a server i wrote on node.js, but I am just stuck on
socket.Connect(new IPEndPoint(IPAddress.Parse(ip_address), port));
it's just loading. I have an ethernet module and I read at https://netmf.codeplex.com/releases/view/81000 under the title bug fixes that "Socket.Connect still blocked after reinsert ethernet cable" have this been fixed or not?
The code is:
Connecttoserver(settings.IPAddress, 8000);
void Connecttoserver(string ip_address, int port)
{
try
{
socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Parse(ip_address), port));
Send("HI !");
ReceiveThread = new Thread(Receive);
ReceiveThread.Start();
}
catch (Exception x)
{
}
}
Question (2):
I want to use socket.io who is using websockets instead of TCP/IP but when I try the example from this webside https://github.com/nikkis/SocketIO.NetMF/. I can see in the output that the message has been sent but nothing happens, the server is never connected to my Gadgeteer?
Can somebody help me with a socket.io server who send data to the client directly not to the browser. is that possible with socket.io in node.js?
To your question (2):
Which version of Socket.IO you have for Node.js? I think the library supports version 0.9.x.
Can you tell what your Node.js logs say when you try to connect your Gadgeteer? Does it receive connection event? Bellow an example to set up Node.js socket.io that should work with the library.
var server = APP.listen( config.server.port );
var io = socket.listen( server );
io.sockets.on( 'connection', function( socket ) {
console.log( 'connection' );
socket.on( 'disconnect', function( deviceid ) {
console.log( 'disconnecting ' + socket.id );
} );
socket.on( 'my_own_event', function( param1, param2 ) {
console.log( 'executing my own event' );
} );
}

Resources