Akka-websocket and Akka-http, emit to stream and produce one actor per request

99 views
Skip to first unread message

User 48

unread,
May 31, 2016, 7:09:43 AM5/31/16
to Akka User List
I there,

I would like to create a service who acts as a relay between plain Http POST and WebSocket. The idea is to have this service who forward any POST requests body to a Websocket channel and use the Websocket response as Http response or send it to another server if the Websocket response arrive after a given delay.


    [Bot]          [Relay]             [Client]
     
|               |                    .
     
|--ws:connect-->|                    .
     
|               |<--HTTP/POST (Cmd)--|
     
|<--- (Cmd) ----|                    |
     
|---- (Resp) -->|                    |
                   
[ if duration<delay]
     
|               |------ (Resp) ----->|
                   
[ else ]
     
|               |--HTTP/PUT (Resp)-->|
                   
[ /if ]

Command handling sequence diagram


It seems feasible but I would like to use Akka and being a beginner I have some questions :

**1/** I can't find anything explaining how to create a Socket where I can write at any time.
The Bot must be "always" connected so that the webscoket channel will be always opened. I have to write on it only when receiving an Http POST request. But in the samples it is a request-response flow.

**2/** Each incoming Cmd must have his own actor to be linked to the orginal Client and decide if the response can be sent to the Http flow or must be send via a new Http/PUT if the delay is expired.
The actor-per-request pattern seems to be the perfect candidate. But I would like to create a Relay actor for each request and let this one handle the request and send the response (`RequestContext.complete`) but when doing that I cannot create the Route because I don't have any return type.

    path("test") {
     
(post & entity(as[Command])) { (ctx, cmd) =>
        serve
(ctx, cmd) // Produce a Relay actor for `ctx` and `? cmd` to it
     
}
   
}


The NET-A-PORTER sample is using Spray which seems to allow direct use of actors as route element but I cannot find the equivalent for Akka-http.


Can someone help me or point me to the documentation part ?

Thanks a lot




Viktor Klang

unread,
Jun 1, 2016, 3:27:03 AM6/1/16
to Akka User List

Hi! :)

On May 31, 2016 1:09 PM, "User 48" <gerv...@gmail.com> wrote:
>
> I there,
>
> I would like to create a service who acts as a relay between plain Http POST and WebSocket. The idea is to have this service who forward any POST requests body to a Websocket channel and use the Websocket response as Http response or send it to another server if the Websocket response arrive after a given delay.
>
>
>     [Bot]          [Relay]             [Client]
>       |               |                    .
>       |--ws:connect-->|                    .
>       |               |<--HTTP/POST (Cmd)--|
>       |<--- (Cmd) ----|                    |
>       |---- (Resp) -->|                    |
>                    [ if duration<delay]
>       |               |------ (Resp) ----->|
>                    [ else ]
>       |               |--HTTP/PUT (Resp)-->|
>                    [ /if ]
>
> Command handling sequence diagram
>
>
> It seems feasible but I would like to use Akka and being a beginner I have some questions :
>
> **1/** I can't find anything explaining how to create a Socket where I can write at any time.

This "unfortunately" doesn't exist. (Not as in Akka Http, but as in Reality)

Relying on such an assumption will lead to subtly (or not so subtly) broken systems.

What are the requirements, implementation aside?

> The Bot must be "always" connected so that the webscoket channel will be always opened. I have to write on it only when receiving an Http POST request. But in the samples it is a request-response flow.

See above.

>
> **2/** Each incoming Cmd must have his own actor to be linked to the orginal Client and decide if the response can be sent to the Http flow or must be send via a new Http/PUT if the delay is expired.

How do you identify the "original Client"?

> The actor-per-request pattern seems to be the perfect candidate. But I would like to create a Relay actor for each request and let this one handle the request and send the response (`RequestContext.complete`) but when doing that I cannot create the Route because I don't have any return type.
>
>     path("test") {
>       (post & entity(as[Command])) { (ctx, cmd) =>
>         serve(ctx, cmd) // Produce a Relay actor for `ctx` and `? cmd` to it
>       }
>     }

Hmmm, does this section of the documentation help?

http://doc.akka.io/docs/akka/2.4.6/scala/http/routing-dsl/index.html

>
>
> The NET-A-PORTER sample is using Spray which seems to allow direct use of actors as route element but I cannot find the equivalent for Akka-http.
>
>
> Can someone help me or point me to the documentation part ?
>
> Thanks a lot

I hope I was of *some* help,
let the group know if you made progress!

Cheers,

> --
> >>>>>>>>>> Read the docs: http://akka.io/docs/
> >>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
> ---
> You received this message because you are subscribed to the Google Groups "Akka User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
> To post to this group, send email to akka...@googlegroups.com.
> Visit this group at https://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.

User 48

unread,
Jun 1, 2016, 6:32:31 AM6/1/16
to Akka User List
Of course it helps, if I understand, Im' trying to something that cannot be done..

But let's say I have the following problem :
An app allow customisation via commands sent to a fixed URL via HTTP POST. But I don't have a fixed url or cannot allow any incoming connexion. 
That's why I would ike to create this relay that can be deployed on any PaaS. So that in one side it receive commands and in the other side it publish them so that the bot can receive, process and reply to them.

In other words : I would like to create something that is started for each new HTTP POST request, send it to a "channel" , wait for the response and return the response to the HTTP reuqest.

Each commands has one unique id that can be used to route a response to the original HTTP request.

User 48

unread,
Jun 2, 2016, 8:41:31 AM6/2/16
to Akka User List
I was able to build a thing that does what I need but with akka-http and crappy Java code for the WebSocket part with Jetty.

- The Relay uses an HttpReceiver and WebSocketEmitter.
1) When the WebsocketEmiter receive a WebSocket connection, it store it in a Map[TeamId, WebSocketConnection].
2) When the HttpReceiver receive a Command it create a Request(Command) and execute a callback method on the relay that start a new Handler(Request, Emitter)
3) The Handler :
   3.1) forward the request to WebSocketEmitter that send it on the WebSocketConnection and wait for a response* (blocking).
   3.2) send the response to the Request which success a Promise
4) The HttpReceiver complete the request by wirting the response.


* The WebSocketConnection don't really wait for a reponse, it send the Command to the remote and set itslef in waiting state (Object.wait). When the WebSocketConnection receive a message he parse and store the result and notify itself to return the result :

Result send(final Command command) {
  write
(command);
  wait
();
 
return this.result;
}

void onWebSocketText(String message) {
 
this.result = parse(message);
  notify
();
}

I really would like to replace this part with akka-websocket but definitively lacks of knowledge on this subject.

Reply all
Reply to author
Forward
0 new messages