tim-group/Tucker — pull request #7 by Grundlefleck (2014-08-01 15:28:50+00:00)
Title: Allow components that will check their status asynchronously

It's preferable to serve a status page quickly. If the status of components are generated synchronously, during a request, it can cause the entire request to hang or be expensive. This pull request allows wrapping normal, written-as-synchronous components to be wrapped in an `AsyncComponent`, that will check the status periodically, and serve the current status very quickly.

Features of `AsyncComponent`:
* runs synchronous status check within threads from a given `Executor`
* can supply a different `Executor` per component, to prevent backups of one component causing other components to hang
* automatically reports warning if a status has not been successfully updated recently enough
* provides a hook for when a status is updated (to allow e.g. custom logging)
* almost all parameters are configurable, with sensible defaults

Example usage (shown with defaults):

AsyncComponent asyncComponent = AsyncComponent.wrapping(myPreexistingNormalComponent)
.withExecutor(Executors.newScheduledThreadPool(1))
.withRepeatSchedule(30, TimeUnit.SECONDS)
.withStalenessLimit(5, TimeUnit.MINUTES)
.withInitialDelay(0, TimeUnit.SECONDS)
.withUpdateHook(AsyncComponent.Consumer.NOOP)
.build();

(equivalent to):

AsyncComponent asyncComponent = AsyncComponent.wrapping(myPreexistingNormalComponent).build();

This should then be given to an instance of `AsyncStatusPageGenerator`, similar to before:

List myAsyncComponents = ...
AsyncStatusPageGenerator generator = new AsyncStatusPageGenerator("my-application-id", new JarVersionComponent(this.getClass()), myAsyncComponents)
generator.start(); // tells all AsyncComponents to begin periodically scheduling their checks

The instance of `AsyncStatusPageGenerator` can then be given wherever `StatusPageGenerator` was previously given.