[zeromq-dev] libzmq v4.0.5

Goswin von Brederlow goswin-v-b at web.de
Fri Sep 26 04:01:56 CEST 2014

On Thu, Sep 25, 2014 at 02:20:07PM +0200, Pieter Hintjens wrote:
> On Thu, Sep 25, 2014 at 1:39 PM, Goswin von Brederlow <goswin-v-b at web.de> wrote:
> > That is fine for major changes where a completly new function makes
> > sense. But not for minor behaviour changes that only conern corner
> > cases. It doesn't make sense to end up with 20 zmq_sock() like
> > functions that all return a slightly differently behaving socket.
> We've already done this, and no-one complains:
> - zmq_send

Lowlevel send

> - zmq_sendmsg
> - zmq_msg_send

Same behaviour with different name. And I would call the msg structure
a major change to the first function.

And since you asked for it let me complain about this here. :) Maybe
http://api.zeromq.org/4-1:zmq-sendmsg could be removed from the table
of contents (or moved to a deprecated section in the table of contents
so it remains for reference).

When I started with zmq I read a few examples and then started to
experiment. For this I keept the API reference open and when I wanted
to do something I would look for a function that sounded right and
open its page. That easily leads to learning deprecated functions
instead of finding the proper ones. Ok, after a while I learned to
first scan for the "this API method is deprecated" boxes. But still,
wasted time.

On the opposite site the new version has some new functions. Somone
coming from an old version might want to read up on the new features.
In the online ocaml reference changes are marked:


That makes it easy to find and read up on changes. Maybe something to
think about too.

> - zmsg_send
> - zstr_send
> - zframe_send
> - zsock_send
> - zactor_send

Different library altogether. :) And czmq has more of an OO design. So
every data object has a send function. One isn't preferable over the
other. They are all ment to coexist.
> All do kind of the same thing. The only time people complained
> (rightly) was when 3.0 changed zmq_send.
> In practice you don't get 20 variations. You get 2 or 3, one for each
> stable generation. Remember we can change draft APIs at will. We make
> a stable release maybe once a year. We save old APIs for a few
> generations, then delete them.
> > HTTP does do exactly that. When you connect you say:
> >
> >     GET /index.html HTTP/1.1
> Yes, except it's used for almost nothing significant, and there was
> never a successful 1.2 or 2.0. That kind of proves my point. (I've
> written many complete HTTP server stacks.)
> > Which is fine if you follow your own contract. Zeromq has broken it 3
> > times now so that isn't the best track record.
> Indeed. However this isn't my project, it's *our* project and we all
> enforce the rules, or we don't. My job has been to define workable
> rules. I'll enforce them on aspects of the project I use and thus care
> about.
> Anyone using those pieces that got broken had the tools to stop that
> happening, and didn't say anything. We can investigate why, and fix
> that, if someone cares.
> > And there are a number
> > of things I would like to change eventually. Like ZMQ_STREAM sockets
> > shouldn't require the MORE flag for every frame, alternating between
> > destination and data frames. Instead they should work like ROUTER
> > sockets and take the first frame of a multi-part message as the
> > destination address and send the rest onwards.
> Indeed. You can already do this in several ways. You don't need to
> expose ABI versions for this. Indeed we have a good, existing
> mechanism for feature updates to socket types. Check the many ROUTER
> socket options.

Two points here:

1) Then why isn't this done for the "now blocks" issue to preserve
API/ABI compatibility? Or for the monitor socket?

2) "Check the *many* ROUTER socket options." That was my point. Over
time such options get more and more and more. So your code gets longer
and longer. You can't just open a socket and get to work anymore. You
have to set 20 options first because the default must remain
compatible with a stoneage version and that for every socket. The idea
was that by specifying an API version the source expects the defaults
could be adjusted accordingly. By setting one version all those 20
options that everyone wants to be changed get set in one go resulting
in improved defaults for all sockets.

> > That I think is the advantage of the FUSE solution. By defining a
> > higher FUSE_USE_VERSION you can not only get new features enabled but
> > also deprecated features removed.
> OK, I do accept the problem statement of multiple versions of an API.
> There are many solutions. Remember our focus is distributed software
> and a distributed community. This is important. It means we work on
> many pieces at the same time, and they evolve independently over a
> long time, and at a distance.
> What this means is that we do not have a single API contract stream.
> Yes, you can say "this is version X" however you cannot use the version
> number as a mechanism for changing semantics.
> Here's the proof: you have piece A and now someone wants to change that
> to A'. New version number. Now, user can choose between A and A' using
> the version number. However now we want to improve A and make A''. This
> is not an improvement of A'. How does this work? New version again?

A  : zmq_send
A' : zmq_sendmsg
A'': zmq_msg_send

Nothing new there. You already do this.
> We've effectively forced an internal fork of the code. Now multiply
> this by the number of aspects we play with.
> This is why I called it "insane".

How does this become more insane? I would say it becomes less so.

Currently you have A and A' and A'' all at the same time. There is no
choice between them. They all exists, all need to be maintained and
all can be used all mixed together in the same source. What you have
is multiple APIs all mixed together. That is what I call "insane".

What the ZMQ_USE_VERSION (lets change that from FUSE) would do for us
in that case is to hide insanity from the user and enforce a
consistent API in the application. For example the library would still
have zmq_sendmsg. That function isn't going away anytime soon. But by
setting ZMQ_USE_VERSION = 4 it wouldn't be exported in the header so
any attempt to still use it would give a compiler error. Or with a
less hard approach it would generate deprecated warnings so you see
where your source needs fixing up. But it wouldn't give warnings with
ZMQ_USE_VERSION = 2. Or maybe just one that version 2 is deprecated
and should be updated soon.
> The sane and simple solution, which we use and which is proven, is to
> use different namespaces that can evolve independently, and never break
> existing code.
> This is how we have lots of socket options, how we have many CZMQ classes,
> and so on, and how this all works with many old versions and in a real
> distributed community, without version madness or internal confusion.
> -Pieter

Internaly nothing would change. Only the external confusion would change.


More information about the zeromq-dev mailing list