> On 11 Oct 2016, at 15:18, Simon Chemouil <ecli...@mithrandir.net> wrote: > > Hey Timothy, > > Thanks for your answer! Final(?) comments inside :-) > > >> It sounds as though you’re making pretty heavy use of Promises, which is >> great to hear! I agree that an external method can be used to provide >> timeouts, but the fact that users (including me) have felt it necessary >> to create the method indicates that it should probably be part of the >> core API. In general we have tried to keep the Promise >> well-encapsulated, so adding timeout to the Promise interface felt most >> consistent. > > Well, I can certainly understand your point of view, and I'm grateful > that you explained how you came to that solution. > > As the ad said, "APIs are forever", and there's also this quote from Ben > Franklin obviously referring to API design that comes to mind: "Those > who sacrifice purity for practicality deserve neither" ;) > > Jokes aside, a *big* selling point from the Promises API was the > fluent/monadic writing style, especially over Guava's futures that are > clumsy to code with in comparison. The fluent side of the Promises API > is a big enabler and allows us to write non-blocking code almost > transparently, so I understand why it is appealing to go that route for > timeouting, which is also very much necessary. > > I just wonder if there would not be a way to get the better of both > worlds, for instance by keeping Promises as is with respect to threading > (e.g, the new callback is not a problem), but having the timeout/delay > facilities in a subtype, with its own deferred variant that takes a > scheduler. > > >> At the moment the behaviour of the OSGi-provided implementation works >> well for you, as it creates no threads at all, however as of Promises >> 1.1 this is likely to no longer be the case. This leaves you with a >> decision point: >> >> * Stick with Promises 1.0 - if the new functionality is not needed in >> your system then it is not mandatory to upgrade. >> * Use/Embed a specific implementation that gives you sufficient >> control of the threading. If you couple to a specific implementation >> (e.g. Apache Aries) then you can supply the Executor/Scheduler when >> you instantiate the Promise >> * Write your own promise implementation to get the finest possible >> control of the Promise lifecycle >> * Upgrade to the standard Promises 1.1, accepting that there will be >> some threads created > > Yep, I have to think it through. Back when I chose to go for OSGi > Promises, I was ready to roll my own implementation/API but I found that > it suited me. I wrote this mail today because I thought it was not too > late for that feedback, thinking that if I have these requirements, > others are bound to have the same eventually, especially as people are > moving to non-blocking, message-based architectures, and try to optimize > resource utilisation.
It’s definitely not too late for feedback - it’s one of the reasons that we try to keep RFC work out in the open (https://github.com/osgi/design <https://github.com/osgi/design>) and to release draft specifications. I’m certain that this feedback will get discussed at the next OSGi meeting, and you should feel free to raise a bug against the draft specification in the OSGi bugzilla. > >> As someone also uses Promises quite a lot in infrastructure services, I >> can wholeheartedly recommend embedding a specific implementation if it >> gives you the control that you need. OSGi is very good at handling >> “substitutable” packages, i.e. providers that also import the API. An >> example would be the Aries Async Service implementation - the Async >> Service repackages the Aries Promise implementation, but imports the >> Promise API. This means that whichever way round bundles resolve they >> share the API packages, but it still allows Aries Async to use the Aries >> Promise implementation, avoiding excessive thread creation. This is the >> mechanism by which Felix SCR can use promises and co-exist in the same >> runtime as another promises provider. > > Do you mean rolling my own API that implements OSGi's Promise interface > for compatibility, but exclusively using my variants of > Deferred/Promises#resolved/Promises#failed to ensure I instantiate my > own PromiseImpl? What you’ve described is how you would provide your own Promises implementation (see also the Aries Promise implementation: https://github.com/apache/aries/tree/trunk/async/promise-api/src/main/java/org <https://github.com/apache/aries/tree/trunk/async/promise-api/src/main/java/org>), and could be what you choose to do. I would, however, consider attempting to reuse the Aries implementation first (or even contributing to it). The Aries implementation is somewhat different from the default OSGi implementation, as it also provides org.apache.aries.async.promise.PromiseImpl as an exported type. This gives you the ability to directly control which executor is going to be used if you call new PromiseImpl(executor) instead of new Deferred(). Note that you could do this inside your Execution Service without requiring that anyone else use Aries Promises, it is simply an implementation detail of the internals of your service. The model that OSGi tries to promote is one of maximum sharing within a given set of constraints. It is therefore possible for lots of people to use, and implement, promises simultaneously within the framework. The important things are: Anyone who wants to use or implement the API must import it Anyone who wants to provide the API must export it The OSGi framework will then determine the best wiring that it can by dropping either the import or the export from each of the bundles. In the typical case (i.e. in the absence of constraints to the contrary) you will end up with one bundle exporting the Promises API and all of the others using it. That means that new Deferred() will create the Promise type from the “winning” bundle, but anyone calling new PromiseImpl(executor) will still get the Aries implementation and they can still share it with people who aren’t using the Aries implementation. The Aries Async bundle does exactly this, it already has an internal threadpool and so it passes it to an Aries PromiseImpl to avoid creating more threads. It does this even when the Async bundle is wired to the default OSGi Promise implementation, at which point the Promise interface (and the Deferred class) are loaded by the OSGi implementation, but the Async service still returns Aries Promise implementations when you call it. I hope that makes sense - it can be a little brain-bending when you first think about it! Best Regards, Tim > > > Thanks again, > Simon > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev