← Back to team overview

nova team mailing list archive

Re: How best to implement a synchronous interface method with an asynchronous implementation?

 

Yes you do, although it looks like the only thing calling info is
update_state and virtually all of the methods that call update state are
already deferreds, so it isn't really that big of a change for this one.
 Ultimately i suppose all of the calls into the virt layer should be using
maybeDeferred so that calls can potentially be async.

Vish

On Mon, Aug 2, 2010 at 5:53 PM, Justin Santa Barbara <justin@xxxxxxxxxxxx>wrote:

> But then haven't we also converted info() from returning a value to
> returning a deferred?  So then don't we have to do this to all the callers
> of info()?  And then all their callers? etc
>
>
> On Mon, Aug 2, 2010 at 4:59 PM, Vishvananda Ishaya <vishvananda@xxxxxxxxx>wrote:
>
>> I'm thinking something like this should work
>>
>>     @defer.inlineCallbacks
>>     def info(self):
>>         result = yield defer.maybeDeferred(self._conn.get_info, self.name
>> )
>>         result['node_name'] = FLAGS.node_name
>>         defer.returnValue(result)
>>
>> Then in your conn get_info can return a deferred?
>>
>> Vish
>>
>> On Mon, Aug 2, 2010 at 4:36 PM, Justin Santa Barbara <justin@xxxxxxxxxxxx
>> > wrote:
>>
>>> Thanks... my understanding is that maybeDeferred makes everything async,
>>> which means that I then have to make all the calling methods async, etc
>>> until the async 'virus' has infected every method :-)  Ideally, I'd like to
>>> contain the change so that the calling methods can remain synchronous and I
>>> don't have to rewrite the callers simply because the implementation of the
>>> interface changed.  This is sort of option B.
>>>
>>> Alternatively, I bite the bullet and convert this method and all its
>>> callers (and their callers, recursively) to be async.  Just for this one
>>> method, I think that means changing:
>>>
>>> fake::get_info, xenapi::get_info, libvirt::get_info to be async (so
>>> callers aren't forced to use maybeDeferred)
>>> And then the callers and their callers:
>>> monitoring.Instance::fetch_cpu_stats => monitoring.Instance::update =>
>>> monitoring.InstanceMonitor.updateInstances_ =>
>>> monitoring.InstanceMonitor.updateInstances
>>> service.Instance::info => service.Instance::update_state
>>> => ComputeService::adopt_instances (reboot and spawn are already async),
>>> VirtualBoxConnection::destroy (reboot and spawn are already async here also)
>>>
>>> And then because VirtualBoxConnection::destroy has now gone sync->async,
>>> then I would need to follow that chain.
>>>
>>> So I guess >20 functions will need conversion of sync -> async just for
>>> this one change.  Obviously, before I try submitting that patch, I want to
>>> know that this is the right thing to do!
>>>
>>> Justin
>>>
>>>
>>>
>>> On Mon, Aug 2, 2010 at 4:09 PM, Vishvananda Ishaya <
>>> vishvananda@xxxxxxxxx> wrote:
>>>
>>>>   show details 4:08 PM (0 minutes ago)
>>>>  I believe Twisted's maybeDefferred is for this purpose.  If you use
>>>> that for the calls into virt, each provider can used deferreds or not vor
>>>> the various methods.  We use it from api.py to call the endpoint methods
>>>>
>>>> Vish
>>>>
>>>> On Mon, Aug 2, 2010 at 1:19 PM, Justin Santa Barbara <
>>>> justin@xxxxxxxxxxxx> wrote:
>>>>
>>>>> I'm hacking on adding VirtualBox support (to allow native Mac
>>>>> development, more than as a serious production target).  This means adding
>>>>> another virt provider (I'm trying without libvirt for now, because libvirt
>>>>> VirtualBox support seems a little flaky, and I'm not sure about libvirt on
>>>>> the mac)  However one of the methods (get_info) is synchronous on the
>>>>> interface, but the VirtualBox implementation is asynchronous (it gets its
>>>>> results from spawning a process).  How do I handle this?
>>>>>
>>>>> A) Do I change the interface so that the method returns a deferred even
>>>>> in the providers that are synchronous?  If so, we should just have all
>>>>> interfaces return a deferred on all methods, so that the interface doesn't
>>>>> expose the implementation.  However, this would make everything messy...
>>>>>
>>>>> B) Should I type-check the result of the call and synchronously wait on
>>>>> it if it is deferred?  (And can anyone point me at some code that can do a
>>>>> sync-wait?)
>>>>>
>>>>> As an aside, and to borrow from the Wizard of Oz, "Twisted, I've a
>>>>> feeling we're not in Python any more".  Every method is preceded by
>>>>> @defer.inlineCallbacks, return x becomes returnValue(x), and there are
>>>>> yields scattered throughout the code based on whether the called method
>>>>> returns a deferred or not.  Perhaps we can clarify the Twisted vs Eventlet
>>>>> discussion: would Eventlet solve this particular problem?
>>>>>
>>>>> Justin
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Mailing list: https://launchpad.net/~nova
>>>>> Post to     : nova@xxxxxxxxxxxxxxxxxxx
>>>>> Unsubscribe : https://launchpad.net/~nova
>>>>> More help   : https://help.launchpad.net/ListHelp
>>>>>
>>>>>
>>>>
>>>
>>
>

References