![](https://secure.gravatar.com/avatar/173371753ea2206b9934a9be1bdce423.jpg?s=120&d=mm&r=g)
On Jul 12, 2012, at 11:39 AM, Richard Wackerbarth wrote:
If I understand you, we both envision a distributed database whereby any of the components might actually provide the data storage for some specific class of information. For example, without specifying where in the system it will reside, there is a "UserManager" that maintains information about the users. It would also be responsible for registering ALL user instances and providing lists of users that meet certain constraints. In addition, it provides an access mechanism for properties associated with particular users.
However, I think that we differ in terms of the public interface specifications.
Actually, I wouldn't say that IUserManager is a public interface specification. It's an internal implementation specification meaning, it's exactly the API - no more, no less - that the core requires from the "user manager service".
The specification that you suggest produces a particular python object.
The specification that I suggest contains only those characteristics which are exposed on the REST interface. It does not specify the exact format in which those characteristics are presented, but only what characteristics are available and what operations can be performed. In this form, no component external to the UserManager is permitted to rely on any aspect of the representation which falls outside of the available public characteristics.
Sure, and if this independent user manager service existed, then the IUserManager implementation inside the core would have to map the attributes and actions it requires to this external service via REST calls.
The place where I am unclear of your intentions concerns this python object. In theory, it may have characteristics that are not exposed to the REST interface. Do you permit your functional modules, (the message handler or the administration interface, for example) to rely on any characteristics that are not properly exposed by the REST interface. If so, why?
The core's current REST API has grown organically, and has been filled out only to the extent that it provides information other services (like Postorius) have needed. We've never yet needed, let alone figured out, what the REST API for the "user manager service" would look like. I guess that's what we're doing here in this thread! :)
Some of the IUserManager API has been implicitly exposed on the REST API, e.g. creating users, searching for users, and accessing properties of those individual users. But the IUserManager API hasn't yet been fully necessary.
I don't see any reason why it couldn't be mapped to a REST API; it's just a lack of need, and nobody's written it yet. The question is whether IUserManager is actually the right API for a REST interface - in general I don't think you need a 1-to-1 mapping of internal model or APIs to REST.
What would a specification of a RESTful user manager look like?
OK, I think we are in agreement WRT this concept. You seem to have taken "foreign key" to imply a specific implementation of the concept to which I was referring, namely some key which designates a unique instance in the referenced table.
Yep, because I was talking about the implementation of the relationships in the core's current table layout.
Doing that would, I think, prevent you from putting the mailinglist table in one database and the member table in another. It makes the associated queries less efficient, but provides for a useful measure of flexibility.
Were this not Python, but C++, I would suggest that we consider offering multiple signatures for the exposed functionality. For example, it the function were to deliver a list of MLs to which an Address is subscribed, the address might be provided as a string (the email address in canonical form), the pk of the entry in the underlying Address database, or as an object of the Address class.
What I described above though is at the database/sql layer, below any language mappings. If Mailman's database maintained the mailinglist table, but the user table lived in some external Postgres databases, you couldn't use foreign key constraints to express the relationship of those two in the member table. We've just planned ahead and made the relationship between members and the mailing lists based on the fqdn_listname of the mailing list[*].
Although the same could be done in python through introspection, or similar techniques, I don't know to what extent doing so would introduce inefficiencies.
P.S. FWIW, I think this separate "user database" component with REST calls in the IUserManager (et al) implementation would not actually be difficult to mock up. I don't have the time to do the coding, but would be happy to discuss details if someone wanted to take a crack at it.
I definitely will take a crack at it since I suspect that doing so would allow Postorius to have all of its user information handled in one place and still provide the "admin by mail" to work with its restricted expectations.
Excellent! What I'd recommend is starting by looking at the following zope.interfaces in the core, and thinking about how the "user manager service" (or whatever it's called[**]) could provide the necessary functionality. Of course this service will probably be a superset of what the core needs, which is fine, since the core will just ignore the parts of the REST resource tree it doesn't care about. This service also doesn't have to directly express the zope.interfaces, just that we have to be able to implement the methods and properties defined in these interfaces using REST calls.
Probably a good start would be:
- IAddress
- IMember
- IRegistrar
- IRoster
- ISubscriptionService
- IUser
- IUserManager
Cheers, -Barry
[*] Of course, now that I think about it, this will probably cause us problems later when we support list renaming. The relationship should probably be between the List-ID and the user, since the former won't change even if the mailing list is renamed. Sigh.
[**] Hey Florian, continuing on a theme, maybe "Vicious". Get it? :)