views:

100

answers:

3

In Nitrogen, the Erlang web framework, I have the following problem. I have a process that takes care of sending and receiving messages to another process that acts as a hub. This process acts as the comet process to receive the messages and update the page.

The problem is that when the user process a button I get a call to event. How do I get ahold of that Pid at an event.

the code that initiates the communication and sets up the receiving part looks like this, first I have an event which starts the client process by calling wf:comet:

event(start_chat) -> 
  Client = wf:comet(fun() -> chat_client() end);

The code for the client process is the following, which gets and joins a room at the beginning and then goes into a loop sending and receiving messages to/from the room:

chat_client() -> 
  Room = room_provider:get_room(), 
  room:join(Room), 
  chat_client(Room).

chat_client(Room) -> 
  receive
    {send_message, Message} ->
      room:send_message(Room, Message);
    {message, From, Message} -> 
      wf:insert_bottom(messages, [#p{}, #span { text=Message }]), 
      wf:comet_flush()
  end, 
  chat_client(Room).

Now, here's the problem. I have another event, send_message:

event(send_message) ->
  Message = wf:q(message),
  ClientPid ! {send_message, Message}.

except that ClientPid is not defined there, and I can't see how to get ahold of it. Any ideas?

The related threat at the Nitrogen mailing list: http://groups.google.com/group/nitrogenweb/browse_thread/thread/c6d9927467e2a51a

A: 

Have an ets table which maps session id's to client Pid's. Or if nitrogen provides any sort of session management, store the Pid as session data.

Zed
I understand it provides some session management, I haven't used it yet. But I need to track it per window, not per browser. The same session should be able to track various client connections in various windows. I though about generating a big random number and use that as key on top of session and put that key in the HTML and keep track of it. Not sure if it's a good solution though.
J. Pablo Fernández
In this case I can't think of anything else but generating unique keys as you suggest. But then you don't need session id's anymore; those keys should be sufficient.
Zed
A: 

Every thing that needs to be remembered needs a process. It looks like your room provider isn't.

room:join(Room) need to be room:join(Room,self()). The room need to know what your comet-process pid is.

To send a message to a client you first send the message to the room, the room will then send a message to all clients in the room. But for that to work. Every client joining the room need to submit the comet-pid. The room need to keep a list of all pid's in the room.

Flinkman
Room actually is a process. room:join(Room) does gen_server:call(Room, {join, self()}.
J. Pablo Fernández
+1  A: 

Nitrogen provides a key-value storage per page instance called state. From the documentation:

Retrieve a page state value stored under the specified key. Page State is different from Session State in that Page State is scoped to a series of requests by one user to one Nitrogen Page:

wf:state(Key) -> Value

Store a page state variable for the current user. Page State is different from Session State in that Page State is scoped to a series of requests by one user to one Nitrogen Page:

wf:state(Key, Value) -> ok

Clear a user's page state:

wf:clear_state() -> ok
J. Pablo Fernández