def acquire_by_items(self, items: List[str], ttl: Optional[float]=None) -> str:
    '\n        Acquire lock by list of items\n        '
    lock_id = ObjectId()
    ttl = (ttl or self.ttl or DEFAULT_TTL)
    metrics[f'lock_{self.category}_requests'] += 1
    logger.debug('[%s|%s] Acquiring lock for %s (%s seconds)', self.category, self.owner, ', '.join(items), ttl)
    while True:
        try:
            self.collection.insert_one({'_id': lock_id, 'items': items, 'owner': self.owner, 'expire': (datetime.datetime.now() + datetime.timedelta(seconds=ttl))})
            return str(lock_id)
        except pymongo.errors.DuplicateKeyError:
            metrics[f'lock_{self.category}_misses'] += 1
            jitter = ((random.random() * DEFAULT_LOCK_WAIT_JITTER) * DEFAULT_LOCK_WAIT)
            timeout = (DEFAULT_LOCK_WAIT + jitter)
            logger.debug('[%s|%s] Cannnot get lock. Waiting %s seconds', self.category, self.owner, timeout)
            time.sleep(timeout)
Acquire lock by list of items
def acquire_by_items(self, items: List[str], ttl: Optional[float]=None) -> str:
    '\n        \n        '
    lock_id = ObjectId()
    ttl = (ttl or self.ttl or DEFAULT_TTL)
    metrics[f'lock_{self.category}_requests'] += 1
    logger.debug('[%s|%s] Acquiring lock for %s (%s seconds)', self.category, self.owner, ', '.join(items), ttl)
    while True:
        try:
            self.collection.insert_one({'_id': lock_id, 'items': items, 'owner': self.owner, 'expire': (datetime.datetime.now() + datetime.timedelta(seconds=ttl))})
            return str(lock_id)
        except pymongo.errors.DuplicateKeyError:
            metrics[f'lock_{self.category}_misses'] += 1
            jitter = ((random.random() * DEFAULT_LOCK_WAIT_JITTER) * DEFAULT_LOCK_WAIT)
            timeout = (DEFAULT_LOCK_WAIT + jitter)
            logger.debug('[%s|%s] Cannnot get lock. Waiting %s seconds', self.category, self.owner, timeout)
            time.sleep(timeout)