Server side processing

58 views
Skip to first unread message

Vasaka Funarg

unread,
Mar 17, 2015, 9:27:53 AM3/17/15
to rever...@googlegroups.com
I am setting server side processing close to this tutorial and struggling with setting event handlers.

I am supposed to add handlers like this:
W = Worker()
W
.run({"srw_app@srw_example_function" : srw_example_function})

in this case I can call worker the same way it is called in tutorial:
from cocaine.services import Service
app
= Service("srw_app")
app
.enqueue("srw_app@srw_example_function", "HELLO\n")

but if I want to send a message through elliptics it won't work with message that handler for event could not be found, I can go different way:
W.run({"srw_example_function" : srw_example_function})
in this case handler would be found, but first way to call it will fail, also I am getting error message:
failed to process: "Invalid exec_context size: 8, must be more than sph: 128: Invalid argument: -22": -22

Am I doing something terribly wrong here? what is a correct way to set handlers, and how fix error with context size?

Vasaka Funarg

unread,
Mar 18, 2015, 12:38:08 PM3/18/15
to rever...@googlegroups.com
Missed the comand how I test it with elliptics.

dnet_ioclient -r localhost:1025:2 -g 1 -c "srw_app@srw_example_function"

I got the reason for the error I get, but still do not see valid way to form the answer in python. also inconsistency with handlers bugs me alot.

Evgeniy Polyakov

unread,
Mar 18, 2015, 1:20:44 PM3/18/15
to Vasaka Funarg, rever...@googlegroups.com
Hi

18.03.2015, 19:38, "Vasaka Funarg" <vas...@gmail.com>:
> Missed the comand how I test it with elliptics.
>
> dnet_ioclient -r localhost:1025:2 -g 1 -c "srw_app@srw_example_function"
>
> I got the reason for the error I get, but still do not see valid way to form the answer in python. also inconsistency with handlers bugs me alot.

SRW in elliptics is a layer over cocaine core, it uses own protocol on top of the cocaine one.
In particular, it carries a control structure which contains among others ID of the node which received the request from the client.
In your example this will be one of the IDs from localhost:1025:2, group 1 node.

This is needed for the cases when your application (srw_app) forwards data further away from the original node which
received client request. Somewhere in the chain node has to send a reply back to client, and this control structure provides
all needed info.

Elliptics itself creates it and fills with all needed info when you invoke exec command as you have shown above.
This means if you send data from other cocaine node elliptics srw application will not understand it until you fill srw header manually.

This also means that srw application has to reply via its own protocol to elliptics, in particular, there is 'reply' method in elliptics service.

Vasaka Funarg

unread,
Mar 23, 2015, 2:05:55 PM3/23/15
to rever...@googlegroups.com, vas...@gmail.com, z...@ioremap.net
It looks I am a bit stuck here, digging through bindings I think I managed to find out 2/3 of how to form a reply in python

session.reply(context, data, elliptics.core.exec_context_final_states.final)

But how do I get a context? All parameters I get in the event handler are cocaine objects, it has to be build from request data then and I do not see how.

Evgeniy Polyakov

unread,
Mar 23, 2015, 5:29:22 PM3/23/15
to Vasaka Funarg, rever...@googlegroups.com
Hi

23.03.2015, 21:05, "Vasaka Funarg" <vas...@gmail.com>:
> It looks I am a bit stuck here, digging through bindings I think I managed to find out 2/3 of how to form a reply in python
>
> session.reply(context, data, elliptics.core.exec_context_final_states.final)
>
> But how do I get a context? All parameters I get in the event handler are cocaine objects, it has to be build from request data then and I do not see how.

Context are the first 128 bytes of received data, *if* it was received via dnet_ioclient or through elliptics - server adds context header by itself.
If it was cocaine induced message, there will be only data sent by your code, thus you may need to setup it manually.

Evgeniy Polyakov

unread,
Mar 23, 2015, 6:59:58 PM3/23/15
to Vasaka Funarg, rever...@googlegroups.com
24.03.2015, 00:29, "Evgeniy Polyakov" <z...@ioremap.net>:
>>  session.reply(context, data, elliptics.core.exec_context_final_states.final)
>>
>>  But how do I get a context? All parameters I get in the event handler are cocaine objects, it has to be build from request data then and I do not see how.
>
> Context are the first 128 bytes of received data, *if* it was received via dnet_ioclient or through elliptics - server adds context header by itself.
> If it was cocaine induced message, there will be only data sent by your code, thus you may need to setup it manually.

These must be struct sph packed into the string + even + data
Unfortunately I do not see any helper to build it, so I will cook up a test code.

Basically it will be
x = struct.pack(format string, whatever is needed for struct sph) + "srw_app@srw_example_function" + "some reply data"
response.write(x)
response.close()

Vasaka Funarg

unread,
Mar 24, 2015, 12:49:29 AM3/24/15
to rever...@googlegroups.com, vas...@gmail.com, z...@ioremap.net
In C++ example in elliptics project you use session to post reply

elliptics::exec_context context = elliptics::exec_context::from_raw(chunks[0].c_str(), chunks[0].size());

COCAINE_LOG_INFO(log, "echo: event: %s, data-size: %ld", event.c_str(), context.data().size());

elliptics::async_reply_result result = reply_client->reply(context, context.data(), elliptics::exec_context::final);
result.connect(std::bind(noop_function, response));

what you suggest here is sending reply with response object, what is the difference between approaches?

Evgeniy Polyakov

unread,
Mar 26, 2015, 4:14:03 PM3/26/15
to Vasaka Funarg, rever...@googlegroups.com
Hi

24.03.2015, 07:49, "Vasaka Funarg" <vas...@gmail.com>:
> In C++ example in elliptics project you use session to post reply
>
> elliptics::exec_context context = elliptics::exec_context::from_raw(chunks[0].c_str(), chunks[0].size());
>
> COCAINE_LOG_INFO(log, "echo: event: %s, data-size: %ld", event.c_str(), context.data().size());
>
> elliptics::async_reply_result result = reply_client->reply(context, context.data(), elliptics::exec_context::final);
> result.connect(std::bind(noop_function, response));
>
> what you suggest here is sending reply with response object, what is the difference between approaches?

Apparently python code doesn't work out of the box.
C++ code sends reply not via cocaine object, but via elliptics - it is required to build a chain of handlers,
consider the case when you send event 'event@app1', its handler sends event to 'event@app2' it sends
event to 'final@app3' and you want original client to get all results from all handlers.

Since handlers may not know about the chain, I introduced sph header, it contains 'address' (ID actually)
of the first node in the chain ('event@app1' in our example), you can only send data to elliptics via elliptics protocol,
hence there is elliptics_client->reply(sph, some data).

Cocaine protocol only allows you to implement request-response scheme without event chaining.

I will this about python reply implementation, it is broken now, so you can only use C++ to send replies back to client from event handlers.
Reply all
Reply to author
Forward
0 new messages