[TransWarp] Peer service discovery in PEAK
Phillip J. Eby
pje at telecommunity.com
Wed Jul 23 17:56:19 EDT 2003
There is an interesting commonality between 1) the problem of mapping pure
domain components to absolute URLs in a web application, and 2) the problem
of finding a DM for a class, or finding a particular kind of DM in relation
to another DM.
In both cases we can view this as an issue of "service discovery". In
existing PEAK architecture, services are registered as providers within a
certain hierarchy of components, using interfaces or property names as
keys. This registration is generally done either through configuration
files, or by classes defining bindings with 'offerAs' settings.
This approach works well for services that need to be "broadcast" to an
"area" of components, the component doing the offering knows that its
children need it, and there is a "natural" key shared by the offering
component and the client components. For services like
storage.ITransactionService, the interface itself is such a natural key,
because transaction services are implicitly singletons within their
offering scope. (IOW, no component reasonably needs to "acquire" more than
one transaction service.)
For other services, such as DMs, there is no "natural" key available,
forcing one to create various "artificial" keys, either by using component
paths (and thus forcing a particular shape on the component hierarchy) or
creating new interfaces and/or property names. These artificial keys are
awkward, because they are a convention that must be understood and used by
both the supplier and client.
In very early versions of PEAK and TransWarp, there was a mechanism whereby
components automatically offered themselves as a provider of any interface
they implemented. This wasn't a good idea, because in effect, the keys
used were too generic. Interfaces by themselves aren't that useful in the
general case of service discovery. For example, knowing that you have a
storage.IEntityDM doesn't tell you much. What class(es) does it serve?
In essence, the issue is one of service "parameters". We need to be able
to identify a service in terms of (for example) an interface and a class,
or an interface and a class and a flag, or who knows what else,
exactly. We also probably need to be able to search for a service without
necessarily having an exact key match. For example, maybe searching for a
I_DM for class Foo, should be able to return an IWritableDM for class Bar,
if IWritableDM subclasses I_DM and Foo subclasses Bar. (It's not
immediately clear to me if this is literally the case.)
Another issue with the current mechanism is that it's strictly a
centralized mechanism. That is, peer components can't find each other
unless mediated by one of their parents. And components don't offer
services to their parents, unless the parent specifically commissioned them
for a particular task.
But if we did allow components to broadcast suitably parameterized
"offerings", how far should they be broadcast? Does a component register
with all its parents? What if more than one component exists for the
function within the same "scope"?
Some forces in play:
* Laziness: we don't want components to have to exist from the start of an
application; this could potentially be expensive. But, for DMs this may
not be *too* expensive, since mere instantiation of a DM isn't that
expensive. We also don't want to have to import all an application's
domain classes at startup, since importing a module is even more
expensive. We can probably work around this latter issue using
'whenImported()' to do registrations once the domain-class modules are
imported.
* Composability: we want to be able to build new applications from pieces
of the old. Thus, even when determining "absolute" locations of things, we
don't want this hardcoded in the components. Also, if we have things like
a peer service location system, we need to avoid "pollution" between
contexts. So how high up do you send a notification of service availability?
After talking this over with Ty a bit, it seems to us that what we should
do for now is implement specific "discovery" services for specific tasks,
and not try to create a general mechanism yet. We need to implement a few
of these before we'll know the general scope of them.
The two specific discovery services we need at present are discovery of
certain kinds of DM by the class(es) they serve, and the discovery of
specialists, also by a class served. A third kind we've tentatively
identified is peer DOMlet discovery, to allow DOMlets in a page to
advertise services to each other. But we don't have enough specific
details yet, just some vague scenarios we thought of while going through
our existing apps with interesting forms. (E.g. forms that let you move
items between two lists, that let you edit an outline, etc.)
None of these services is critical right now; they are just
ease-of-development issues. This e-mail is just to keep a record of the
concepts for when we get to implementing them.
More information about the PEAK
mailing list