Hi Alex, I'd actually say (a) is the way to do it, using the OSGI service dependency mechanism in some way (not *quite* sure how that is done these days!). That would be the more "OSGI native" style of doing it, would it not? Start levels wouldn't be what we want [1] and making all catalog init block until all bundle loaders are started (b) sounds workable but coarse grained. If each bundle specified a dependency on a service that loaded it, then the normal OSGI service mechanism would control the startup order for us very naturally. I share your dislike of options (c) and (e).
What do you think? Geoff [1] https://www.aqute.biz/2017/04/24/aggregate-state.html On Mon, 23 Nov 2020 at 11:12, Alex Heneveld <[email protected]> wrote: > > > Hi Brooklyn devs, > > Regarding the recent addition to allow custom Bundle Resolver OSGi > services [1], we've discovered a bothersome issue with load order at > runtime. It is non-deterministic whether a custom resolver bundle loads > before or after the initial catalog.bom and persisted state. If the > custom resolver loads _after_, then it won't be available to handle the > catalog.bom and persisted state, which means the bundle might be loaded > by the wrong resolver or it might fail to load altogether. > > We want to introduce a mechanism to prevent those errors. There are > several options: > > (a) Specify a dependency on the resolver bundle/service inside the > bundle that needs it > > (b) Specify any resolver OSGi bundle or service names that are required > in brooklyn.cfg, and then wait until they are available before > initializing Brooklyn catalog (eg using BundleListener / ServiceTracker) > > (c) Require the bundle to be explicitly included in the Brooklyn/OSGi > startup sequence (boot bundlers or startup.properties) before the > catalog/rebind initializes > > (d) Wait for "all startup and deploy bundles" to be in their final state > (usually active) or a start level before the catalog/rebind initializes > > (e) Re-install bundles if we've added a new bundle-parser service (so > while it might fail initially, it eventually succeeds) > > > Option (d) would be the nicest I think, simplest for user, leaning on > OSGi "start levels": but Karaf does not seem to respect startlevels. > I'll send an email to the Karaf list to ask. > > Option (c) is quite tricky AFAIK, obscure edits needed to the etc/* > directory and some tricky listeners (OSGi doesn't encourage the notion > of "wait for everything else to be ready", for obvious reasons if two > bundles use that philosophy they will deadlock!). So I don't like it. > > Option (a) makes writing a bundle that uses a custom resolver more > difficult (e.g. requiring an OSGi MANIFEST.MF) so I don't like it either. > > Option (e) is quite hard to code up, and inefficient, and will cause a > lot of warnings in the log as part of the normal case, and potentially > disrupt operations if we re-install bundles whenever a resolver is > added. That said, it is a common pattern in OSGi ... but I don't much > like it. > > > That leaves option (b) which is what I'm leaning towards (unless we get > an answer re (d)). Specifically we'd say something like this in > `brooklyn.cfg`: > > brooklyn.resolvers.require.services = custom.Resolver1,custom.Resolver2 > > and then in catalog/rebind we block (with logging) if those are not yet > available. Possibly we would also have > > brooklyn.resolvers.require.timeout = 5m > > And if not available within that timeframe it logs a warning and proceeds. > > > Note there are potentially similar issues with PlanTransformers but I > think that is simple to solve once we've solved ^. > > Best > Alex > > [1] https://github.com/apache/brooklyn-server/pull/1115 > >
