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)