def get_or_load_name(self, type_, id_, method):
        """
        read-through cache for a type of object's name.

        If we don't have a cached name for this type/id, then we will query the
        live Koji server and store the value before returning.

        :param type_: str, "user" or "tag"
        :param id_: int, eg. 123456
        :param method: function to call if this value is not in the cache.
                       This method must return a deferred that fires with an
                       object with a ".name" attribute.
        :returns: deferred that when fired returns a str, or None
        """
        name = self.get_name(type_, id_)
        if name is not None:
            defer.returnValue(name)
        instance = yield method(id_)
        if instance is None:
            defer.returnValue(None)
        self.put_name(type_, id_, instance.name)
        defer.returnValue(instance.name)
read-through cache for a type of object's name.

        If we don't have a cached name for this type/id, then we will query the
        live Koji server and store the value before returning.

        :param type_: str, "user" or "tag"
        :param id_: int, eg. 123456
        :param method: function to call if this value is not in the cache.
                       This method must return a deferred that fires with an
                       object with a ".name" attribute.
        :returns: deferred that when fired returns a str, or None