2017-02-18 11 views
2

У меня есть хранимая процедура DocumentDB, которая вставляет или обновляет (не заменяет, а скорее считывает и обновляет существующий документ). Хранимая процедура делает не более двух операций:DocumentDB - Определить ограниченное выполнение в хранимой процедуре

  1. запроса по Id и
  2. либо вставить или обновить

документ также не особенно велика. Однако время от времени я получаю либо тайм-аут (вызванный ограниченным исполнением), либо 449 (ресурсы для устранения конфликтов, которые являются временной ошибкой).

IMO это не особенно облагаемая хранимая процедура, но кажется, что я уже бегу к ограничениям. Я мог бы сделать больше работы на стороне клиента, но мне нравится гарантия ACID в хранимой процедуре.

Есть ли количественная мера при ограниченном выполнении? Мне интересно, я просто делаю что-то неправильно, или я действительно ударил лимит DocumentDB.

Моя хранимая процедура является модифицированной https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/update.js, которая принимает документ вместо идентификатора. Я использую «$ addToSet», в частности, и код выглядит

function unique(arr) { 
    var uniqueArr = [], map = {}; 

    for (var i = 0; i < arr.length; i++) { 
     var exists = map[arr[i]]; 

     if (!exists) { 
      uniqueArr.push(arr[i]); 
      map[arr[i]] = true; 
     } 
    } 

    return uniqueArr; 
} 

// The $addToSet operator adds elements to an array only if they do not already exist in the set. 
function addToSet(document, update) { 
    var fields, i; 

    if (update.$addToSet) { 
     console.log(">addToSet"); 
     fields = Object.keys(update.$addToSet); 

     for (i = 0; i < fields.length; i++) { 
      if (!Array.isArray(document[fields[i]])) { 
       // Validate the document field; throw an exception if it is not an array. 
       throw new Error("Bad $addToSet parameter - field in document must be an array."); 
      } 

      // convert to array if input is not an array 
      var newIds = Array.isArray(update.$addToSet[fields[i]]) 
       ? update.$addToSet[fields[i]] 
       : [update.$addToSet[fields[i]]]; 

      var finalIds = unique(document[fields[i]].concat(newIds)); 
      document[fields[i]] = finalIds; 
     } 
    } 
} 

ответ

1

DocumentDB хранимые процедуры должны завершить в течение 5 секунд. Они также ограничены предоставленной пропускной способностью коллекции. Если у вас имеется 5000 RU/s, то хранимая процедура не может потреблять более 5000 * 5 RU в общей сложности.

Когда хранимая процедура достигает своего времени выполнения или предела ее пропускной способности, любой запрос на выполнение операции с базой данных (чтение, запись, запрос) получит сигнал предварительного выделения, т. Е. Запрос не будет приниматься в качестве сигнала для хранимую процедуру для завершения выполнения и возврата к вызывающему. Если вы проверите код возврата с каждого вызова, ваша хранимая процедура никогда не будет таймаутом. Вот отрывок, показывающий, как это сделать (полные образцы доступны в https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/):

var isAccepted = collection.replaceDocument(...) { 
    // additional logic in callback 
}); 

if (!isAccepted) { 
    // wrap up execution and return   
} 

Что касается 449, это ошибка параллелизма, который может быть возвращен, если хранимая процедура пытается выполнить противоречивую запись. Это побочный эффект, свободный и безопасный, чтобы повторить попытку от клиента. Вы можете реализовать повторную попытку до тех пор, пока она не будет выполнена с ошибкой.

+0

Должны ли они преодолеть ограниченные пределы выполнения всего двумя операциями? Я знаю, что он потребляет RU, но может ли быть так, что все RU потребляются другими операциями, когда это работает? –

+0

@Aravind благодарит за дополнительную информацию, но что-то не складывается. Некоторая дополнительная справочная информация 1) Окружающая среда - это наша среда разработки, и эта функция еще не включена, поэтому я ожидаю практически нулевой трафик в стороне от разработчиков. 2) Коллекция представляет собой секционированную коллекцию с 2500 RU. Наконец, я обнаружил, что таймаут - это выбор, который запрашивает ключ id и раздел. Это совершенно неожиданно –

+0

Просто отметим, что с тех пор мы вернулись к 2 вызовам REST на клиенте. # 1 Запрос по id + ключ раздела # 2 Upsert Для # 2 мы полагаемся на оптимистичный параллелизм, поскольку мы не ожидаем, что много столкновений (это пакетный процесс). Рад сказать, что он кажется очень надежным и намного быстрее, чем выполнение обоих операций в хранимой процедуре. Тем не менее, все еще любопытно, почему я так рано попадал в пределы. –

Смежные вопросы