Hi Derek,

b - In the Atom syndication format, UUIDs are necessary for two things. One, the overall feed has a UUID. This is easy - I'm storing them in a site-local named utility, indexed by the feed annotation object.
What do yuo mean "indexed by"?

Hand the utility a feed annotation, get back a uuid for the feed.

Also, is this UUID not just another aspect of feed "metadata" and thus a
candidate for the container annotation?

This was the original plan, but I was convinced to go with the more
generalized solution of a uuid utility. I guess I can cache it in the
container annotation, but that's an optimization and tangential to this

I don't think it's tangental. When we discussed this before, I was under the impression you wanted to have automatically assigned UUIDs to content objects. That sounded like something which should (a) be external to that object and (b) be centralised, with a key-reference type functionality in the same way as zope.app.intid, to allow semantics like "I have a UUID, now where is the object that it belongs to".

I still thing this sounds like useful, general behaviour.

However, now we are also talking about UUIDs of "feeds", which are implemented as views. I'm assuming the same feed gets the same UUID each time (if it does not, then you just generate it in the view, dynamically, which is simple).

If the feed needs metadata, and this metadata is context-specific, then storing that metadata in an annotation on the feed source (the container) seems sensible. However, the feed UUID is then just another part of that metadata.

The advantage of the utility approach is that it can generalised a lot. You can index based on generic container events, for example. If the feed/annotation is being managed explicitly, then why bother trying to fire "contentish" events and dealing with things like key-references for something which is in an annotation of an object?

The only reason I'd see for a central utility keeping track of UUIDs and feeds would be if you needed some kind of global UUID-to-feed lookup service.

If you do choose to just treat the feed UUID as metadata, there is of course no reason why you can't share the UUID-generating code between the feed annotation and the more general global UUID registry/id utility.

each entry in a feed has a UUID. A content item that is an entry (a file, in the current case) can, however, be in multiple feeds and needs a different UUID in each. Thus, I need to be able to look up UUIDs by the content object that will be rendered as a feed entry and look them up relative to the feed, rather than globally.

That sounds to me like you want a composite UUID - a UUID utility gives each
content item a UUID (which is not feed-specific, and stays in line with the
general concept of a content object UUID). The one you put in the feed is
the feed's UUID and the object's UUID are combined. You could possibly use
some kind of hash if you needed to.

I considered this. I have a certain understanding of what I'm doing that
precludes the combinatorial UUID approach, but no one I talk to seems to
grasp it, so I think I will air it here so we can discuss it.

I am using RFC 4122 type 1 UUIDs. These are (practically) guaranteed
universally unique, as they are based on spatial (MAC address) and
temporal (CPU clock time) location. They have safeguards built in for
things like multiple CPUs and resetting the CPU clock.

However, they are only (practically) guaranteed universally unique if
*everyone* follows the same algorithm. If you use a different algorithm
for computing your UUIDs, then they may collide with my RFC 4122 ones,
since your algorithm doesn't compute them the same way and thus may use
different, supposedly unique information included in a different way
that results in the same UUID that I generate. Highly unlikely, but
vastly more likely than if we all follow the RFC. Thus, to me, part of
being a good citizen of the UUID world is to follow the exact RFC 4122
algorithm, so we can all get along without collisions.

There is no provision in RFC 4122 for combining two UUIDs to generate a
third, still unique, UUID. So, in my mind, combining two UUIDs, by
whatever method, results in a relative UID, not a UUID.

Granted, I live in a fantasy world where everyone plays by the same RFC
4122 rules. Still, it's a nice world and I want to do what I can to
encourage others to join me in it. So, I want to generate
strictly-compliant RFC 4122 UUIDs for use in my product (and my utility
makes it easy for others to use them elsewhere in Zope).

Thus I take the hard road, here. Is there a flaw in my reasoning?

I understand this problem, and it makes sense. I think it's a good line to take. However, does the spec say the UUID *has* to be RFC 4122 type 1? If not, then a plain concatenation (no hash) of a UUID, with some separator that's not going to be output by the UUID seems valid enough to me. If you have two universally unique ids, then a combination of them must also be universally unique.

If the spec says it must be that exact format, or you're religiously bent on them, you'll need a different approach. You then essentially need a UUID that doesn't describe an object, but which describes an (object, feed) combination.

Are the *only* inputs to the RFC 4122 algorithm MAC address and system clock? If there are more inputs, e.g. an arbitrary object id, you could use them, I think.

You could of course annotate each and every item in the container with a list of FeedIdentity objects or something like that and let each one of those have a UUID, but that seems lame, inefficient and difficult to keep up-to-date and in sync.

You could have a different approach, whereby you have a utility like:

class IFeedUUIDContainer(Interface):

    def register(feed, obj):
        """Register the given object for the given feed, return a UUID

    def get_object(feed, uuid):
        """Find an object given a feed and an object UUID

    def get_uuid(feed, obj):
        """Find an object's UUID in the given feed

The idea here is that each time you look up an object or register it with the utility to obtain a UUID, you pass the object *and* the feed. Internally, this utility would need to store something like a dict (with keys for each feed) of dicts (with keys for object UUIDs) of keyrefs. This is a different API to zope.app.intid, and quite feed-specific but would work.

Now, notice each method here basically takes a feed as a key. That smells annotation/adaptation to me. So you could do this:

class IFeed(Interface):

    feed_uuid = Attribute("Feed's UUID")

    title = Attribute("Feed title")

class Feed(Persistent):
    implements(IFeed, IAttributeAnnotatable)

    feed_uuid = None
    title = u""

let's say we have a container 'parent', and we need a new feed configured for this:

  >>> KEY = 'vice.feed.metadata'
  >>> annotations = IAnnotations(parent)
  >>> feed = annotations.setdefault(KEY, Feed())

Now, 'feed' is a persistent object in an annotation on 'parent'. If you need to keep feeds in a PersistentList or OOBTree under that key, do that instead.

Then you can store object UUIDs for a feed in annotations on that object.

  >>> feed_annotations = IAnnotations(feed)

The problem is how to register all necessary objects with the feed_annations. You could do this lazily (create a new UUID only when needed, and flush old ones sometimes) or try to keep it all up to date with events (in which case look at the events zope.app.intid needs to keep track of).


Zope3-users mailing list

Reply via email to