def handle_request(layer_id, redis_conn): '''handler for any item pulled from worker job queue This handler is called every time the worker is able to pop a message from the job queue filled by the registry. The worker blocks until a message is available. This handler will then attempt to aquire a lock for the provided layer_id and if successful, process a diff for the layer. If the lock for this layer_id has already been aquired for this layer the worker will immediately timeout to block for another request. ''' try: # this with-context will attempt to establish a 5 minute lock # on the key for this layer, immediately passing on LockTimeout # if one isn't availble with rlock.Lock(redis_conn, "diff-worker-lock", layer_id, expires=60 * 5): # first check if a cached result is already available. The registry # already does this, but hey. diff_data = layers.get_image_diff_cache(layer_id) if not diff_data: log.info("Processing diff for %s" % layer_id) layers.get_image_diff_json(layer_id) except rlock.LockTimeout: log.info("Another worker is processing %s. Skipping." % layer_id)
def get_image_diff(image_id, headers): try: repository = toolkit.get_repository() if repository and store.is_private(*repository): return toolkit.api_error('Image not found', 404) # first try the cache diff_json = layers.get_image_diff_cache(image_id) # it the cache misses, request a diff from a worker if not diff_json: layers.diff_queue.push(image_id) # empty response diff_json = "" return toolkit.response(diff_json, headers=headers, raw=True) except IOError: return toolkit.api_error('Image not found', 404) except tarfile.TarError: return toolkit.api_error('Layer format not supported', 400)
def test_image_diff_cache(self): layer_id = rndstr(16) layers.set_image_diff_cache(layer_id, layer_id) diff_json = layers.get_image_diff_cache(layer_id) self.assertTrue(layer_id == diff_json)