示例#1
0
文件: cache.py 项目: fserena/agora-py
    def create(self, conjunctive=False, gid=None, loader=None, format=None):
        try:
            if conjunctive:
                uuid = shortuuid.uuid()
                g = get_triple_store(self.__persist_mode,
                                     base=self.__base_path,
                                     path=uuid)
                return g
            else:
                p = self._r.pipeline(transaction=True)
                p.multi()

                g = Graph(identifier=gid)

                lock = self.uri_lock(gid)
                with lock:
                    uuid = self._r.hget('{}:gids'.format(self.__cache_key),
                                        gid)
                    if not uuid:
                        uuid = shortuuid.uuid()
                        p.hset('{}:gids'.format(self.__cache_key), gid, uuid)

                    gid_key = '{}:{}'.format(self.__cache_key, uuid)

                    ttl_ts = self._r.hget(gid_key, 'ttl')
                    if ttl_ts is not None:
                        ttl_dt = dt.utcfromtimestamp(int(ttl_ts))
                        now = dt.utcnow()
                        if ttl_dt > now:
                            try:
                                g = self.__recall(gid)
                            except KeyError:
                                source_z = self._r.hget(gid_key, 'data')
                                source = zlib.decompress(source_z)
                                g.parse(StringIO(source), format=format)
                                self.__memoize(gid, g)

                            ttl = math.ceil(
                                (ttl_dt - dt.utcnow()).total_seconds())
                            return g, math.ceil(ttl)

                    log.debug('Caching {}'.format(gid))
                    response = loader(gid, format)
                    if response is None and loader != http_get:
                        response = http_get(gid, format)

                    if isinstance(response, bool):
                        return response

                    ttl = self.__min_cache_time
                    source, headers = response
                    if not isinstance(source, Graph) and not isinstance(
                            source, ConjunctiveGraph):
                        parse_rdf(g, source, format, headers)
                        data = g.serialize(format='turtle')
                    else:
                        data = source.serialize(format='turtle')
                        for prefix, ns in source.namespaces():
                            g.bind(prefix, ns)
                        g.__iadd__(source)

                    self.__memoize(gid, g)

                    if not self.__force_cache_time:
                        ttl = extract_ttl(headers) or ttl

                    p.hset(gid_key, 'data', zlib.compress(data))
                    ttl_ts = calendar.timegm(
                        (dt.utcnow() + delta(seconds=ttl)).timetuple())
                    p.hset(gid_key, 'ttl', ttl_ts)
                    p.expire(gid_key, ttl)
                    p.execute()
                return g, int(ttl)
        except ConnectionError as e:
            raise EnvironmentError(e.message)