Hi,

Thanks for taking this up again.

But I have some concerns about the proposed implementation:

 * Returning a formatted string sounds wrong
 * We have to define public API, which is not used all
   outside of Engine, except for registering something
 * We have an issue of where to implement this thing..

I am considering the following issues:

 * The decision of whether a system is to be considered
   ready or not is mainly an administrative task
   (rather than a development time decision), we should place
   the administrator into a position to be able to configure
   this thing.
 * The SlingMainServlet is -- inside of Sling -- the only
   party really intereted in some state. Thus introduction of
   an externally visible API should probably be prevented
 * The parameters to the proposed addRequiredServices method
   makes up for a configuration. The method may be called
   multiple times with different values.
 * We may choose to provide data stored in the repository.

So, here is my proposal:

 * The configuration is provided by the Configuration Admin
   service as a factory configuration with the following
   properties:

         bundle.symbolic.name
         bundle.version (optional, defaults to any version)
         count (optional, defaults to 1)
         clazz (required)
         filter (optional, defaults to "no filter")

 * The SlingMainServlet registers a ManagedServiceFactory
   listening for these configurations and maintains an
   internal "state machine". This registration can be done
   in the SlingMainServlet.activate method (and deregistration
   in the SlingMainServlet.deactivate method).

 * The implementation is part of the Sling Engine bundle
   and is private to the Engine bundle.

 * The SlingMainServlet uses a simple method:
       boolean isSystemReady()
   conveying the state. The method should a non-readyness
   reason. The SlingMainServlet will just send back 503
   (or 404 ?) if not ready.

 * The internal implementation may be registered as a
   Web Console plugin (or Configuration Printer) to provide
   administrators with:

      * details about the system status
      * configuration form to easily manage the
        configuration (maybe leveraging the Configuration
        Admin support of the Web Console similar to how
        the Commons Log bundle does it on the "Sling Log
        Support" page.

 * Using JCR Install, FileInstall, the Web Console, or other
   means of providing configuraiton, administrators may "fill"
   the requirements list

Finally the SystemStatus interface is deprecated and the systemstatus
bundle is removed (or moved to some attic location).

WDYT ?

Regards
Felix

On 15.02.2010 17:01, Bertrand Delacretaz wrote:
> Hi,
> 
> Here's a new proposal for SLING-490, for a service that helps find out
> when a Sling system is ready to accept requests after startup.
> 
> Last discussion (http://markmail.org/thread/4bwmuwj6qnytmrfw) provided
> some good ideas, but I think this is much better, with low coupling
> and a possibility for bundles to declare additional required services
> before they become active, making it easier to have a well defined
> startup behavior.
> 
> The idea is to add an implementation of the ServiceWatchdog interface
> shown below, to the sling engine bundle.
> See details of the ServiceWatchdog interface below.
> 
> The sling engine bundle activator calls
> ServiceWatchdog.addRequiredServices based on configuration values read
> from BundleContext.getProperty, useful for repository-less setups.
> 
> The SlingMainServlet calls ServiceWatchdog.getMissingServices(), and
> returns HTTP status 503 if that's not null. That's the only place
> where this info is used by Sling itself.
> 
> As soon as the repository becomes available, before making it
> available as a SlingRepository service, the AbstractSlingRepository
> reads an optional list of additional required services from a
> well-known location in the repository, under /system/required-services
> for example,
> 
> I think this solves our previous concerns w.r.t possible race
> conditions at startup depending on which configuration mechanisms are
> used: client bundles are free to get the "required services" info from
> wherever makes sense for them, and the ServiceWatchdog reacts
> immediately to addRequiredServices calls, by clearing its internal
> state to force it to be recomputed on the next getMissingServices
> call.
> 
> The ServiceWatchdog implementation listens to service events and
> bundle events, to recompute the list of missing services when needed,
> and caches that info as long as no such events are received.
> 
> WDYT?
> 
> -Bertrand
> 
> 
> 
> /** Service that watches a specified set of services,
>  *  to check that they are all present.
>  */
> public interface ServiceWatchdog {
>       /**     True if all specified services are present.
>        *      That info is cached, so calling this is cheap
>        *      unless relevant services and/or bundles events
>        *      have been received, causing this to be recomputed.
>        *
>        *      @return null if all required services are present.
>        *              If services are missing, returns a formatted
>        *              string like
>        *              <pre>
>        *              ID:COUNT:CLAZZ:FILTER
>        *              ID:COUNT:CLAZZ:FILTER
>        *              ...
>        *              </pre>
>        *              Where each ID:CLAZZ:FILTER line indicates a set of
>        *              services registered with {...@link addRequiredServices)
>        *              for which BundleContext.getServiceReferences does not
>        *              return the expected number of services.
>        *              
>        */
>       String getMissingServices();
>       
>       /**     Add one or several services to the list of services to watch.
>        *      The watchdog calls BundleContext.getServiceReferences with
>        *      the specified parameters to find out if the corresponding
>        *      services are present.
>        *
>        *      @param bundleId clazz and filter are tied to this bundle,
>        *              if it is stopped or uninstalled, the corresponding
>        *              clazz/filter values are removed from our list.
>        *      @param count expected size of the array returned by
>        *              BundleContext.getServiceReferences
>        *      @param clazz used to call BundleContext.getServiceReferences
>        *      @param filter used to call BundleContext.getServiceReferences
>        */
>       void addRequiredServices(long bundleId, int count, String clazz,
> String filter);
> }
> 

Reply via email to