Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Lots of long-standing bugfixes and small updates. #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
May 26, 2015
Merged

Conversation

bombela
Copy link
Member

@bombela bombela commented May 26, 2015

No description provided.

bombela and others added 28 commits September 9, 2014 00:09
One can set the env variable ZPC_TEST_TIME_FACTOR to something smaller
than 1.0 in order to speedup testing. At some really small values, unit
tests about timeouts are likely to fail!

Example:
$ ZPC_TEST_TIME_FACTOR=0.01 nosetests
After all, we are dealing with an abstract channel, no need to know if
its buffered or not in the patterns.
We are in python so it's merely a way to document the code.

 - requires a channel to accept timeouts on operations directly
 - expose few useful properties
Instead of doing horrible __del__ stuff and freezing everything in the gc,
and sometimes getting totally absurd errors:
 -> lets cleanly and explicitly close our channels all the way down.
This mostly for pretty symmetry with the ReqStream.
 - Bump timouts value to avoid false unit test errors: Basically, some
   timeouts are a little bit to short for fast testing.

 - Fix transiant unit test failure on pubsub.
     - you log all msgs
     - you send one msg
     - heartbeat msgs are logged
     - you check for only one msg: bad
     - you check if your msg appars among the heartbeats: good

    This was a beautiful race condition, since most of the time, the
    heartbeat is slower than how fast you send and test your msg.

 -  Wrap in coroutines.

    HeartbeatOnChannel can raises to its parent at any time.
    Encapsulating the code in its own coroutine will reduce race
    conditions.
Simply avoid binding to an already used port.
HeartBeatOnChannel raises exceptions directly to its parent's coroutine
so it needs to run in the same coroutine as the test server/client.
 - server side, you accept a new channel
 - you stack an heartbeatonchannel on top
 - you slow everything enough so the client already sent some heartbeat
   msgs before you could read the first msg (cpu intensive task,
   time.sleep...)
 - you send back the response
 - you close the heartbeatonchannel
 - this kills the coroutine handling the heartbeat
 - this action eventually switch to the hearbeat coroutine to raise
   GreenletExit in it.
 - which after might ends up to the recver coroutine (not yet killed)
 - the recever coroutine gets the heartbeat msg from the client
 - and stupidly process to spawn a new heartbeat coroutine!
 - this eventually switch back to the close()
 - which set the self._heartbeat to None (so potentially another
   heartbeat msg could spawn another heartbeat coroutine!)
 - after enough back and forth, self._channel is set to None
 - one or more of the heartbeat coroutines is trying to access
   self._channel.emit... and BOOM, you get (an harmless) stacktrace in
   the logs.

The solution is to set a flag when close() is called: self._close =
True.

_start_hearbeat() called from the recver coroutine can then check this
flag.

Last but not least, the heartbeat coroutine checks this flag before
killing the parent coroutine. This is not strictly necessary, but if in
the future the code in close() eventually yields back to gevent (for
example, by trying to kill another coroutine before the heartbeat's
one), this will prevent a LostRemote to be raised on close().

And finally, a forgotten variable was removed (in channel.py).
 - zerorpc cli accepts --debug or -d, this turn on DEBUG level logging
   and active low level events debugging on the zerorpc object.
 - a zerorpc.SocketBase exposes a new boolean property debug
Instead of hashing the function object, hash its name instead. There is
no particular reason to consider a function instance and its name as two
independent entities in the context of the same object.

As a bonus, this means you can now replace your methods on the fly and
the next call will reach the new one. I am not sure why you would want
to do that though.
bombela added a commit that referenced this pull request May 26, 2015
Lots of long-standing bugfixes and small updates.
@bombela bombela merged commit 6e3b122 into 0rpc:master May 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant