The reason why gRPC streaming services can only have a single parameter - stream

At the moment, gRPC service definitions can only have a single parameter even if it’s a streaming service which makes challenging to represent the “initial” request. For instance, consider a chat app in which a user can join a chat room.
In this case, the domain can be modelled as follows.
message JoinRoomRequest {
required string room = 1;
}
message ChatMessage {
required string content = 2;
}
A consumer of the chat app would send a join request and start a bi-directional stream of messages, so the service can be described in this way.
service SimpleChat {
rpc joinChatRoom (JoinRoomRequest, stream ChatMessage) returns (stream ChatMessage);
}
However, in gRPC the above syntax is not valid. The only way to represent the described chat service is
service SimpleChat {
rpc joinChatRoom (stream ChatMessage) returns (stream ChatMessage);
}
What is the reason behind this decision, and how a similar domain can be modelled in gRPC?

Simplicity. It is much easier to model a request/response as a single payload rather than varadic, especially in your case, where you want the multiplicity to be different - what, for example, would it mean to take
(A, stream B, C, stream D)
And... if you can take multiple elements, can you return multiple too? Many languages support that concept, after all.
No, it is much easier to receive (as either input it output) either a request or a stream of requests of a single type.
In your scenario, perhaps consider the request type being a thing wrapper over a oneof (discriminated union) of all the actual expected messages, and just have your code enforce that the first one is a "join":
message ChatRequest {
oneof RequestType {
JoinRoomRequest join = 1;
ChatMessage message = 2;
}
}
And take a stream of ChatRequest

Related

Nexmo - Select from number based on location of destination to number

In Twilio there's an concept of phone # pools. A txt message can be sent using this Pools Id value and Twilio will select the best FROM number to send with. I've looked around Nexmos API's and I don't see similar capabilities, is this possible?
The only other option I've found is something call applications but I can't send messages without manually selecting the from numbers instead of automating it via application Id, I assume that would be one of the 'use cases'
There's a document from Nexmo https://help.nexmo.com/hc/en-us/articles/217571017-What-is-a-Sender-ID- that has the following
Random Numeric - Nexmo will apply a random number to comply with local regulations (usually taken from a pool of numbers we have access to from the relevant destination market).
Problem is how do I configure Random Numeric? It doesn't really explain and I might have missed those docs. Any suggestion help.
Random numeric is not something you set, is something the Nexmo API does in order to ensure delivery in certain parts of the world, in order to conform with local regulations.
There is no Pools concept in Nexmo at the moment, so if you want the same functionality you'd have to build it in your code. Rent a bunch of Nexmo phone numbers, and then apply a random algorithm of choice in your code before sending each message to select your phone number. Something like:
let myNexmoNumbers = [447481234567, 447481234568, 447481234569]
nexmo.message.sendSms(myNexmoNumbers[Math.floor(Math.random() * myNexmoNumbers.length)], TO_NUMBER, TEXT_MESAGE, (err, responseData) => {
if (err) {
console.log(err);
} else {
if(responseData.messages[0]['status'] === "0") {
console.log("Message sent successfully.");
} else {
console.log(`Message failed with error: ${responseData.messages[0]['error-text']}`);
}
}
})

How to call xml-rpc webservice using objective c

Suppose, the webservice provider's server exposing the webservice in the form http://example.com:8000/api
What is best framework or library to access the webservice in ios 7 project
There are a few marshaling frameworks that support generating an object-graph from XML, however I would simply go for the following:
Invoke the service endpoint. My favorite library is BBHTTP, however you could use AFNetworking, NSURLConnection with gcd or whatever you prefer for asynch network calls.
Extract the relevant contents of the XML payload onto your use-case specific payload object using RaptureXML
I recommend having use-case specific payload objects because they model exactly what is needed for a given service invocation - supporting the notion of contract-first development. This allows you to change you internal model without effecting the integration to external systems. Similarly the external API can change without effecting your model.
You can create a category method on RXMLElement to return the element mapped to a use-case-specific object. A typical mapping usually takes just a handful of lines of code to marshal from wire-format to your payload object for the service invocation.
Here's an example (the code that I took it from wanted the payload wrapped in a SOAP envelope - just ignore that bit).
- (void)request:(MyUseCaseRequstPayload*)request onComplete:(void (^)(MyResponsePayload*))onSuccess
onError:(void (^)(NSError*))onError;
{
//Even more XML! You can stick your payload inside an envelope if you want
SoapEnvelope* envelope = [SoapEnvelope envelopeWithContent:[request xmlString]];
[[BBHTTPRequest postToURL:_serviceUrl data:[envelope data] contentType:#"text/xml"] execute:^(BBHTTPResponse* response)
{
RXMLElement* element = [RXMLElement elementFromXMLData:[response content]];
MyResponsePayload* response = [[element child:#"elementToBeMapped"] asMyObjectType];
if (onSuccess)
{
onSuccess(response);
}
} error:^(NSError* error)
{
LogDebug(#"Got error: %#", error);
if (onError)
{
onError(error);
}
}];
}

How to design a connector in go

I am building a simple connector component in go, with these responsibilities:
Open, keep & manage connection to an external service (i.e. run in background).
Parse incoming data into logical messages and pass these messages to business logic component.
Send logical messages from business logic to external service.
I am undecided how to design the interface of the connector in go.
Variant A) Channel for inbound, function call for outbound messages
// Listen for inbound messages.
// Inbound messages are delivered to the provided channel.
func Listen(msg chan *Message) {...}
// Deliver msg to service
func Send(msg *Message) {...}
Variant B) Channel for inbound and outbound messages
// Listen for inbound messages + send outbound messages.
// Inbound messages are delivered to the provided msgIn channel.
// To send a message, put a message into the msgOut channel.
func ListenAndSend(msgIn chan *Message, msgOut chan *Message) {...}
Variant B seems cleaner and more "go-like" to me, but I am looking for answers to:
Is there an "idiomatic" way to do this in go?
alternatively, in which cases should variant A or B be preferred?
any other notable variants for this kind of problem?
Both approaches allow for only one listener (unless you keep track of the amount of listeners, which is a somewhat fragile approach), which is a limitation. It all depends on your programmatic preferences but I'd probably go with callbacks for incoming messages and a send method:
func OnReceive(func(*Message) bool) // If callback returns false, unregister it.
func Send(*Message)
Other than that, both of your proposed models are completely valid. The second seems more "orthogonal". An advantage of using a send method is that you can make sure it never blocks, as opposed to a "bare" channel.

How to send and receive domain objects with rabbitMQ plugin and grails

I've went over the excellent documentation for the rabbitMQ plugin. However, I am still confused about a few things.
Scenario
My application will take a file upload from the user, do various things to the file and accordingly set certain properties on the domain object. Some of this work can be labor intensive so I am using a queue. I envision requests being queued and the consumer picking up the requests from the queue and consuming them.
Questions
I want to store a domain object in the queue. I do this by: rabbitSend 'myqueue', colorObj. colorObjis an object of domain class Color
However, in the ColorService handleMessage(...) When I fetch the item from the queue, the item is not of type Color. Please note that on the rabbitMQ dashboard I can see the items being inserted in the queue, so my queue initiation in config.groovy is fine (I am using amq.direct)
How can I send and fetch a domain object from the queue?
From the behavior I've seen thus far, the handleMessage does not need to be instantiated. Even if I don't call the ColorService it still executes handleMessage by itself. Is that a normal behavior?
Below is the code:
controller
Color colorObj = colorService.newRequest(params, request.getFile('color.filename')
if (colorObj.validate)
rabbitSend 'myqueue', colorObj
...
service
class ColorService {
static rabbitQueue = 'myqueue'
void handleMessage(message) {
println "came in message: " + message instanceof Color //this prints false
}
}
As Tim says, if you can get by with just passing the domain instance ID that is simplest. You do need to be careful of changes to the domain instance while the message is in transit though.
Alternatively, if it's the data you're interested in, I prefer to serialise the objects as JSON using something like
rabbitSend 'myqueue', (colorObj as JSON).toString()
Of course, now your listener is receiving a string, so you'll have to convert it back:
void handleMessage(String message) {
def color = new Color(JSON.parse(message))
println "came in message: " + color instanceof Color
}
There is a little bit of discussion around this on the GPRABBITMQ-15 issue.
As it shows in the documentation, you can either send a String or a Map
Why not send the id of your domain object:
rabbitSend 'myqueue', colorObj.id
Then, load it back in when the message is processed:
void handleMessage(message) {
println "Got ${Color.get( message )}"
}
Or, if you don't need the domain object until the message is processed, send a map of all the required data, and have the service create the domain object after it is processed successfully?

Communicating between (chat) server and client

just to clarify certain questions.
Let's say I'm making a chat application. Most of the online tutorials are basic server-client programs that send the chat message directly as strings.
So what if there is someone that came online, or offline. How would the client notify the server of such changes? What I came up with is to use flags {online}User, {offline}user, {privatechat}blabla.
What if someone knew how your code and that would allow them to sabotage by keep sending {online}blabla.
This would work, but has some flaws that I could think of as well. What would be the correct or better way to do this?
Can someone point me in the right direction? Thanks.
Or another example, in games. To tell the unit to move right, does it send a string back to the server {unit}{move right}? Something along those lines.
I kinda got the logic on how to make the chat server. If I just prefix a "{chat}" to the textbox. As long as I read this command "{chat}" I'll just ignore whichever commands which comes along.
How about in an RTS (not that I'm gonna make one, just curious), you mean there's literally 50 over strings telling how units move, attack, take damage, actions etc? Will all these commands be done on one thread? or multi-threaded?
Well you have to implement session-handling and send sessionToken with your order to move a unit in game. So server will be able to check whether pointed user have rights to order the pointed unit etc. Same things with chats.
In my chat, every client sends some PING message to server every two minutes. So if 5 minutes passed and no PING is received, server counts the user as [offline].
If you are afraid of cheating users who reverse engineer your client and can make serious troubles to the system with cheats, you have to do two things:
make server to check if given
user order is valid
implement bot-detection. check if
user makes some actions with some
constant time interval or if user
uses some limited amount of words in
chat etc.
I hope this post at least gives you some point.
The example of server logic is following:
[WebMethod]
string LoginUser(string login, string pwd)
{
if( dal.IsCorrectUser(login,pwd) )
{
string token = dal.MakeSession(login);
return string;
}
return "-1";
}
[WebMethod]
bool UserOrder(string token, string order)
{
if( !dal.SessionExist(token) )
{
return false;
}
int userId = dal.GetUserBySession(token);
if(! dal.ValidOrderForUser(userId,order) )
{
dal.RegisterWrongOrder(userid,order); // For cheaters-detecting purposes
return false;
}
return dal.ExecuteUserOrder(userId, order);
}
In fact you can send string or any serializable objects as an user-order.
[Serializable]
struct UserOrder
{
int unitId;
int Order;
}
All samples are for c#. Just to demonstrate logic.

Resources