A Twisted Design Decision

Jean-Paul Calderone exarkun at divmod.com
Tue Jan 27 08:57:22 EST 2009


On Tue, 27 Jan 2009 05:46:25 -0800 (PST), koranthala <koranthala at gmail.com> wrote:
>Twisted, being twisted in its behavior is causing quite a lot of
>confusion in design decisions.

I'm not sure I agree with your premise. ;)

>I will put forward a comparison of reactor and non-reactor patterns.
>The code is not exact - whatever is shown is the gist of it.
>
>For example, a message handler - in a usual scenario:
>class messageHandler:
>   def run():
>         msg = self.get_next_msg()
>         if not msg.send():
>             self.handle_failure()
>
>To handle parallel execution, we will have to use threads, but the
>code flow is similar.
>
>How do we do the same in a reactor pattern (Twisted)?
>msg.send will cause a deferred to be raised - the failure, if it
>happens will happen much later.
>i.e. other than sending messageHandler object in msg.send(), I cannot
>see any mechanism of running handle_failure.
>
>In Twisted:
>class messageHandler:
>   def run():
>         msg = self.get_next_msg()
>         msg.send(self):
>
>class msgClass:
>    def send(o):
>        d = deferred.addCallBack(success_handler, o).addErrBack
>(failure_handler, o)
>
>    def failure_handler(o):
>        o.handle_failure()

This doesn't look like a correct or faithful translation of the original.
Here are two possibilities.  First:

    class messageHandler:
        def run():
            msg = self.get_next_msg()
            d = msg.send()
            def cbSendFailed(result):
                if not result:
                    self.handle_failure()
            d.addErrback(cbSendFailed)
            return d

Next:

    class messageHandler:
        @inlineCallbacks
        def run():
            msg = self.get_next_msg()
            if not (yield msg.send()):
                self.handle_failure()

These are both just straight translations from your version so as to
be able to handle a Deferred from `msg.send´.

>Basically, what I find is that a lot of functional encapsulation is
>now lost by following reactor pattern. handle_failure is
>messageHandlers code and makes for pretty viewing if called from
>inside messageHandler itself. But, due to the twisted nature of
>reactor pattern, the msg Class - who is functionally a lower class to
>messageHandler invoking messageHandler's code.

You don't need to lose anything.  I don't know what your motivation was
for re-arranging the code when you wrote the Twisted version, but it doesn't
appear to have been necessary.

>Is there a way to solve this in a more beautiful way? Am I missing
>something here?
>

Hope this helps,

Jean-Paul



More information about the Python-list mailing list