[nanomsg] Re: RFC links

  • From: Paul Colomiets <paul@xxxxxxxxxxxxxx>
  • To: nanomsg@xxxxxxxxxxxxx
  • Date: Fri, 16 Aug 2013 18:53:07 +0300

Hi Martin,

On Fri, Aug 9, 2013 at 8:29 AM, Martin Sustrik <sustrik@xxxxxxxxxx> wrote:
>
> https://raw.github.com/250bpm/nanomsg/master/rfc/sp-request-reply-01.txt
>
> This RFC describes the request/reply protocol. It does exactly what you
> would expect it to do -- distributes requests to stateless services and
> routes replies back to the client.
>

Finally found a time to read this one.

> First, by default the priority settings for all channels MUST be
> equal.  Creating a channel with different priority MUST be triggered
> by an explicit action by the user.

I don't think "MUST" is appropriate here. It may be "should",
presumably lowercased. The reason is that the protocol does describe
syntax and semantics, but doesn't describe API. What if API has
connect-by-SRV-record? Does it means priorities are explicitly set by
user? What if API has connect-to-host("foo") with implicitly port
11111 being for high priority channel and 11112 for low priority? What
means "user", does it mean SysOp or programmer?

> Second, if there are several channels with equal priority, the
>  endpoint MUST distribute the messages among them in fair fashion
>   using round-robin algorithm.  The round-robin implementation MUST
>   also take care not to become unfair when new channels are added or
>   old ones are removed on the fly.
> As for incoming messages, i.e. replies, REQ endpoint MUST fair-queues
>  them.  In other words, if there are replies available on several
>  channels, it MUST receive them in a round-robin fashion.  It mast
>  also take care not to compromise the fairness when new channels are
>  added or old ones removed.

"MUST" here is inappropriate because it's impossible to define "fair".
And even more "fair" and "round-robin" are probably conflicting for
some definition of fair. Round-robin definition is mostly clear
usually, but differ in handling various edge cases (and must be
defined in this spec anyway if you insist on being it's semantics the
part of the specification). Same is with fair-queueness. "SHOULD" will
be ok I think.

> First ID assigned MUST be random. Next is computed by adding 1 to
>   the previous one with potential overflow to 0.
> The implementation MUST ensure that the random number is different
>   each time the endpoint is re-started, the process that contains it is
>   restarted or similar.  So, for example, using pseudo-random generator
>   with a constant seed won't do.

The "MUST" here is overkill too. I'd say it's the responsibility of
the library implementer to make channel unique enough. It doesn't
event need to be unique, as wrong replies will be filtered by the
client. And there is a bunch of perfectly good reasons to use
different methods of channel ID generation.

Similar thing with request IDs.

> If the hop-by-hop layer reports pushback condition, the end-to-end
>  layer considers the request unsent and MUST report pushback condition
>  to the user.

Can't always be implemented. "SHOULD" is more appropriate.

> Also note that unlike with the requests there's no pushback applied
>   to the replies.  The replies are simply dropped in the case of
>   pushback

You never say that replies "SHOULD be dropped". You talk about this like a fact.

> The user MUST be allowed to specify the timeout interval.
>   The default timeout interval must be 60 seconds.

Similarly, the API is not specified. And who is a user.

> When a reply is received from the underlying hop-by-hop
>   implementation, the endpoint *should* strip off first 32 bits from the
>   reply to check whether it is a valid reply.

And this one should be "MUST" (for what reason user may get unstripped reply?)

> If the ID in the reply matches one of the requests in progress, the
>  reply *MUST be* passed to the user (with the 32-bit prefix stripped
>   off).  At the same time the stored copy of the original request as
>   well as re-transmission timer *must be* deallocated.

And these two "must be" should probably be just "is". No need to
REQUIRE reply to be passed to user as it's the aim of the protocol.

> Finally, REQ endpoint MUST make it possible for the user to cancel a
>   particular request in progress.  What it means technically is
>   deleting the stored copy of the request and cancelling the associated
>   timer.  Thus, once the reply arrives, it will be discarded by the
>   algorithm above.

It's the API issue too. IIRC neither zeromq nor libxs nor nanomsg has
this functionality. Why do you specify it at all?

> At that point the stored traceback stack MUST be deallocated.

Don't specify when anything must be deallocated, please :)

>  Additionally, REP endpoint MUST support cancelling any request being
>   processed at the moment.  What it means, technically, is that state
>   associated with the request, i.e. the traceback stack stored by the
>   endpoint is deleted and reply to that particular request is never
>   sent.

Again. The API issue. It can be written but with "should" instead of "MUST".

>   To deal with the problem REQ endpoints MUST check the depth of the
>   traceback stack for every outgoing request and discard any requests
>   where it exceeds certain threshold.  The threshold should be defined
>   by the user.  The default value is suggested to be 8.

Does the minimum supported stack size needs to be specified? Does this
size include request ID?

P.S.: The reason I care a lot about this "MUST"s is because the
implementation of the protocol is considered conformant only if it
obeys all MUSTs, even if there is a reason for not being to do so, and
even if it's fully interoperable with other implementations. While
"SHOULD" allow to ignore the rule if there is a good reason to do so.
So "MUST" should be used only for things that are valuable for
interoperation between implementations.

-- 
Paul

Other related posts: