Не всегда резолвится промис
monolithed opened this issue · 28 comments
При невыясненных обстоятельствах у меня бывают случаи когда промис не резолвится.
tarantool.insert(...)
.then(result => { /* Не вызывается */ })
.catch(error => { /* Не вызывается */ })При этом, записи в базу добавляются.
Бегло нашел множество мест где как мне кажется такое возможно, например
Возможно из-за того, что условие в этом месте может не выполниться
PS: Кстати, почему бы не заменить vow на стандартные Promise, которые уже есть в ноде?
Понял, гляну.
PS: Перепишу.
Нету еще каких-то подробностей новых?
Повторяется стабильно.
У меня вызов операции insert завернут в десяток других промисов, но как они могут влиять на поведение не понимаю.
Весь код транслируется из ES6 через babel-node
// ... Куча промисов
// .. Тут стоит метка профайлера с логом
tarantool.insert(...)
.then(result => { /* Не вызывается */ })
.catch(error => { /* Не вызывается */ })
// .. Тут стоит метка профайлера с логом
// Данные в базу добавляются, 100%Операцию insert выполняю в цикле из более чем 3000 итераций без каких-либо задержек (хотя я пробовал добавлять один элемент, колбек также не сработал).
Если вызвать insert отдельно от моего кода, то все работает.
Структура индексов такая:
return function (space)
local name, city, host, rank, rate =
1, 2, 3, 4, 5
space:create_index('primary', {
parts = {
name, 'str',
city, 'str'
}
})
space:create_index('secondary', {
type = 'tree',
unique = false,
parts = {
host, 'str',
rank, 'num',
rate, 'num',
}
})
endПример массива данных:
[
'google.com',
'Mountain View',
'google.com',
100,
2000,
[
'YouTube',
'Nest Labs',
'FeedBurner',
'Songza'
],
'Technologies'
]@monolithed а что значит 3000 операций? Ты их паралельно записываешь через Promise.all или последовательно?
Понял ща проверю 10к записей подобных что будет.
Я получаю данные, затем в Promise.all мне приходит массив из 3000 элементов, затем в цикле я последовательно выполняю операцию вставки.
Все элементы попадают в базу, но зарезолвить их не получается (
Дебажить мне это дело очень проблематично, потому что код сперва транслируется препроцессором и брейкпоинты теряются.
@monolithed а эти данные совпадают для #11 ?
Данные те же, но там проблема пока ушла.
Вот часть кода, который отвечает за вставку данных:
/**
* Устанавливает соединение с сервером приложения Tarantool
*
* @return {Promise}
*/
get connection () {
return new Promise((resolve, reject) => {
this.config.then(({ host, port, user, space_id }) => {
let tarantool = new Tarantool({ host, port });
// Прокидываем space_id в инстансе для комфортного доступа
tarantool.space_id = space_id;
tarantool.connect()
.then(status => {
return tarantool.auth(user.name, user.password);
})
.then(status => {
resolve(tarantool);
})
.catch(error => {
reject('Failed to connect with Tarantool');
})
;
}, reject);
});
}
/**
* Записывает переданные данные в базу
*
* @param {Object} tarantool — Ссылка на открытое соединение
* @param {Object} data — Данные фермы
* @param {boolean} replace — Использовать операцию "replace"
* @see normalize
* @return {Promise}
*/
insert (tarantool, data, replace) {
let tuple = this.normalize(data);
return new Promise((resolve, reject) => {
this.validate(tuple)
.then(status => {
let operation = replace ? 'replace' : 'insert';
tarantool[operation](tarantool.space_id, tuple)
.then(resolve, error => {
Log.error('Insert operation error:',
error.message, '\n', tuple);
reject(error);
})
;
})
.catch(error => {
Log.error('Validation error:',
error.message, '\n', tuple);
reject(error);
})
;
});
}[
'google.com',
'Mountain View',
'google.com',
100,
2000,
[
'YouTube',
'Nest Labs',
'FeedBurner',
'Songza'
],
'Technologies'
]
вот конкретно этот кусок данных 10к раз вставленных отрабатывает но видимо там есть куски гораздо больше или как-то msgpack не справляется с дешифровкой или я где-то не правильно мержу куски данных или неправильно читаю их.
А сам по себе тарантул об ошибках не сообщает?
@monolithed хотя я не правильно сделал ща еще раз поправлю.
Вот когда поправил такая же байда. Это хорошо, теперь поисследую что там.
Хотя все равно не воспроизвелось просто оно 11 секунд у меня вставляется :( может и там у тебя где-то стоит таймаут?
А сам по себе тарантул об ошибках не сообщает?
Тарантул молчит.
msgpack не справляется с дешифровкой
Хм, а как это должно влиять на резолвинг промиса?
Вот когда поправил такая же байда. Это хорошо, теперь поисследую что там.
Это хорошая новость!
@monolithed так не воспроизвелось все таки. Просто у меня тупит машина, на ней еще всякое веселье крутится ._.
Если msgpack не справится то он не поймет к какому промису оно относится. Там оно по requestId расшифровывает ответ.
var dataSample = function(_, x){
return [
'google.com'+x,
'Mountain View'+x,
'google.com',
100,
2000,
[
'YouTube',
'Nest Labs',
'FeedBurner',
'Songza'
],
'Technologies'
];
};
var arr =[];
for (var i=0; i<10000; i++)
arr.push(dataSample(i, i));
Таким образом формирую данные для вставки.
Из-за того что msgpack синхронный?
@monolithed не из-за того что msgpack синхронный, а из-за того что данные какие-то не те вернулись. Ну или просто данные не правильно пришли, к примеру один пакет потерялся в процессе и все считай вся линия чтения в этом потоке нарушена.
Надо бы тоже покрыть этот сценарий какими-нибудь тестами, пока такого варианта не получал потому как в среде с плохой связью и потерянными пакетам не тестировал.
Я пробовал выводить данные, который приходят, они все стандартные, отличий вообще нет, разве что могут быть какие-то юникод-символы.
@monolithed а вот функция this.validate она всегда resolve/reject кидает?
Все данные что собираются сохраняются? Можешь провести какой-то анализ типа стадия сбора, а потом стадия сравнения того что собрано с тем что по итогу вставлено в базу.
Да, я же говорю, что в ее колбек я всегда попадаю:
/**
* Валидация данных кортежа
*
* @param {Array}
* @return {Promise}
*/
validate (data) {
return new Promise((resolve, reject) => {
try {
let validate = jsen(this.schema);
validate(data);
if (validate.errors.length) {
reject(validate.errors);
}
else {
resolve(validate);
}
}
catch (error) {
reject(error.message);
}
})
}@monolithed ща в мастер патч накатаю и попробуй с ним посмотреть что тебе в консоле выдастся. Ну или как время удобное будет. Где-то через полчаса залью его.
Слушай, похоже проблема действительно может быть в юникод-символах (тарантул их выводит как знаки вопроса в треугольнике), сейчас в базе таких нет и все промисы зарезолвились!
@monolithed ну давай ща проверю что там с unicode'ом. Просто русских символов хватит?
Эти символы приходят мне "извне", письмо парсится
@monolithed тогда скорее всего проблема в msgpack энкодинге/декодинге тогда лучше посмотреть просто обычный лог ошибок. Он куда-то должен был выкинуть ее по идеи, т.к. сам я ее не перехватываю. Сейчас накатаю чтобы оно в мастере пока писало куда-нибудь в диск ошибки эти кодирования декодирования.
Вот пример битой строки
��рилль
Но я это скопировал из базы, как-то же он туда попал
А вот сейчас даже этими символами все нормализовалось, уже раз 10 сделал экспорт и все Ок!
@monolithed я посмотрел вообщем-то в msgpack5 он String просто по сути как bytearray хранит, а читает его исключительно как utf-8 потом, так что желательно все привести к utf-8 перед тем как ложить в базу.
Хотя я чот сам туплю он по дефолту тоже пишет utf-8 для string, который write to buffer.
Кажется я нашел в чем проблема. Скоро все переделаю и будет новая версия с другими багами ._.