How can I get the tcp socket in a process that started a redix connection?

Hi,

The question I tried a lot and have got no idea.

After

{:ok, conn} = Redix.start_link(host: "127.0.0.1", port: 6379) 

conn is PID like #PID<0.554.0>

Then I send some special command to redis server:

{:ok, OK} = Redix.start_link(conn, [...some special command...]) 

The special redis server may then further push a series responses to conn separately and constantly.

I want to use :

:gen_tcp.recv(socket, 0)

to receive data from redis server in process #PID<0.554.0>

But conn is a PID (etc. TCP Client) not a socket, So how can I get socket from the PID.

Anyone can give me a glue?

Thanks

:wave:

Maybe there is a way to do it via redix? Either way, redix probably keeps the socket in it’s state, you can try a hack like :sys.get_state(redix_conn) to find out.

:gen_tcp.recv(socket, 0) might not work if the socket is started in active: true mode. Seems like it is started with active: :once. And is reset to that mode after each received packet. So you might try something like

%{socket: socket} = :sys.get_state(redix_conn)
:gen_tcp.recv(socket, 0)

But a more correct approach is most likely possible, since you might receive the data you don’t need, which would in turn make other queued requests fail.

I’d probably fork redix and add a way to subscribe for updates, especially if it’s some special redis server.

2 Likes

I got the socket after following your instruction.

:sys.get_state(conn)

returned the following:

{:connected, 
    %Redix.Connection{
        backoff_current: nil, 
        client_reply: :on, 
        connected_address: "127.0.0.1:6379", 
        counter: 0, 
        opts: [
                socket_opts: [], 
                ssl: false, 
                sync_connect: false, 
                backoff_initial: 500, 
                backoff_max: 30000, 
                log: [
                    disconnection: :error, 
                    failed_connection: :error,
                    reconnection: :info
                    ], 
                exit_on_disconnection: false, 
                timeout: 5000, 
                host: '127.0.0.1', 
                port: 6379
            ], 
        socket: #Port<0.9>, 
        socket_owner: #PID<0.180.0>, 
        table: #Reference<0.3121165064.4228775937.104953>, 
        transport: :gen_tcp
    }
}

socket is a Port<0.9>
Then after

:gen_tcp.recv(socket, 0)

It get a error, the socket did not work

{:error, :einval}

But you figured me out, it is not the right way. It should be done in the redis lib.

I should fork Redix or find other redis lib.
(similar to redigo lib in golang, there is a Receive function in such situation.)

Thank you very much.

1 Like