<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def __get_or_create_app(self, url, cache_key):
 """ Get the app from cache or generate a new one if required Because app object doesn't have etag/expiry, we have to make

        headers = {"Accept": "application/json"}
        app_url = '%s?datasource=%s' % (url, self.datasource)

        cached = self.cache.get(cache_key, (None, None, 0))
        if cached is None or len(cached) != 3:
            self.cache.invalidate(cache_key)
            cached_app, cached_headers, cached_expiry = (cached, None, 0)
        else:
            cached_app, cached_headers, cached_expiry = cached

        if cached_app is not None and cached_headers is not None:
            # we didn't set custom expire, use header expiry
            expires = cached_headers.get('expires', None)
            cache_timeout = -1
            if self.expire is None and expires is not None:
                cache_timeout = get_cache_time_left(
                    cached_headers['expires']
                )
                if cache_timeout >= 0:
                    return cached_app

            # we set custom expire, check this instead
            else:
                if self.expire == 0 or cached_expiry >= time.time():
                    return cached_app

            # if we have etags, add the header to use them
            etag = cached_headers.get('etag', None)
            if etag is not None:
                headers['If-None-Match'] = etag

            # if nothing makes us use the cache, invalidate it
            if ((expires is None or cache_timeout < 0 or
                 cached_expiry < time.time()) and etag is None):
                self.cache.invalidate(cache_key)

        # set timeout value in case we have to cache it later
        timeout = 0
        if self.expire is not None and self.expire > 0:
            timeout = time.time() + self.expire

        # we are here, we know we have to make a head call...
        res = requests.head(app_url, headers=headers)
        if res.status_code == 304 and cached_app is not None:
            self.cache.set(
                cache_key,
                (cached_app, res.headers, timeout)
            )
            return cached_app

        # ok, cache is not accurate, make the full stuff
        app = App.create(app_url)
        if self.caching:
            self.cache.set(cache_key, (app, res.headers, timeout))

        return app