def METHOD_NAME(pipes, session_factory, executor_factory, retry):
    client = local_session(session_factory).client('datapipeline')
    def process_tags(pipe_set):
        pipe_map = {pipe['id']: pipe for pipe in pipe_set}
        while True:
            try:
                results = retry(
                    client.describe_pipelines,
                    pipelineIds=list(pipe_map.keys()))
                break
            except ClientError as e:
                if e.response['Error']['Code'] != 'PipelineNotFound':
                    raise
                msg = e.response['Error']['Message']
                _, lb_name = msg.strip().rsplit(' ', 1)
                pipe_map.pop(lb_name)
                if not pipe_map:
                    results = {'TagDescriptions': []}
                    break
                continue
        for pipe_desc in results['pipelineDescriptionList']:
            pipe = pipe_map[pipe_desc['pipelineId']]
            pipe['pipelineId'] = pipe_desc['pipelineId']
            pipe['Tags'] = [
                {'Key': t['key'], 'Value': t['value']}
                for t in pipe_desc['tags']]
            for field in pipe_desc['fields']:
                key = field['key']
                if not key.startswith('@'):
                    continue
                pipe[key[1:]] = field['stringValue']
    with executor_factory(max_workers=2) as w:
        return list(w.map(process_tags, chunks(pipes, 20)))