Окончание истории с PouchDB
Jun. 16th, 2015 04:14 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Последнюю неделю я практически рыл носом землю, чтобы понять точно, что же вызвало потерю данных. Нашёл и зафайлил кучу багов разной степени тяжести в PouchDB, но ручное прикрытие каждого так и не давало ответа, в чём же в самом деле причина.
Апофеоз истории вот тут https://github.com/pouchdb/pouchdb/issues/3961. В результате я написал тест, который имитирует, что происходит в cloudwall без запуска cloudwall – но оказалось, что этот тест никто кроме меня не может воспроизвести. А у меня он железно воспроизводился на двух моих Маках в 100% случаев – но только для двух доменов, для остальных доменов всё было ок. Я даже стал подозревать в какой-то момент, что зелёные человечки – не выдумка (шучу :)
Ключик в решению проблемы увиделся, когда я слил свои файлы IndexedDB из Хрома разработчику PouchDB, и он не смог воспроизвести баг даже с ними. Просто ничего больше не осталось, как грешить на файловую систему – всё остальное было к тому моменту тщательнейшим образом проверено и отброшено.
Так и оказалось – на обоих Маках у меня были сбои на FS. На эйре, видимо, деградировал SSD, а на iMac – HDD, который часть Fusion Drive. Именно поэтому баг и не проявлялся, пока не закроешь вкладку в Хроме – браузер закрывал файл, а файловая система его обнуляла из-за ошибок в бинарном дереве каталога.
Любопытно, что проверка при запущенных ОС не показывала мне никаких проблем с дисками. Для обнаружения проблем надо было перезагрузить обе машины и запустить проверку диска по-холодному. После исправления дисков и удаления вручную каталогов с базами данных баг перестал воспроизводиться.
Из этого надо вынести несколько уроков:
Апофеоз истории вот тут https://github.com/pouchdb/pouchdb/issues/3961. В результате я написал тест, который имитирует, что происходит в cloudwall без запуска cloudwall – но оказалось, что этот тест никто кроме меня не может воспроизвести. А у меня он железно воспроизводился на двух моих Маках в 100% случаев – но только для двух доменов, для остальных доменов всё было ок. Я даже стал подозревать в какой-то момент, что зелёные человечки – не выдумка (шучу :)
Ключик в решению проблемы увиделся, когда я слил свои файлы IndexedDB из Хрома разработчику PouchDB, и он не смог воспроизвести баг даже с ними. Просто ничего больше не осталось, как грешить на файловую систему – всё остальное было к тому моменту тщательнейшим образом проверено и отброшено.
Так и оказалось – на обоих Маках у меня были сбои на FS. На эйре, видимо, деградировал SSD, а на iMac – HDD, который часть Fusion Drive. Именно поэтому баг и не проявлялся, пока не закроешь вкладку в Хроме – браузер закрывал файл, а файловая система его обнуляла из-за ошибок в бинарном дереве каталога.
Любопытно, что проверка при запущенных ОС не показывала мне никаких проблем с дисками. Для обнаружения проблем надо было перезагрузить обе машины и запустить проверку диска по-холодному. После исправления дисков и удаления вручную каталогов с базами данных баг перестал воспроизводиться.
Из этого надо вынести несколько уроков:
- БД ни при каких обстоятельствах не должна считать нижележащую технологию надёжной. А так считают и PouchDB, и IndexedDB и, увы мне, CloudWall.
- При обнаружении багов с потерей данных идти надо начинать снизу вверх, а не сверху вниз. Это тот-же ровно принцип, как и в случае с проверкой розетки, питания и предохранителей в первую очередь, когда «компьютер сломался». Я как-то не соотносил эту народную мудрость с высокими технологиями, а напрасно.
- Баг – лучший учитель. Я за последнюю неделю досконально разобрался, как устроен PouchDB в части репликации, внешних ajаx-запросов и взаимодействия с IndexedDB. Попутно разобрался со схемой запросов к IDB по-хорошему (ну и гадость, доложу я вам), с производительностью IDB, с тем, как устроены файлы каталогов в HFS+, и много ещё чего попутного по мелочи.
no subject
Date: 2015-06-16 01:54 pm (UTC)Устанавливаю обновления Windows. Перегружаю ноут. Логинюсь. Через несколько секунд падает Explorer.exe, и так по кругу. Гружусь в Safe Mode. Всё нормуль. Ну, думаю, нифига себе обновился. Сношу обновление. Перегружаюсь обратно. Не помогает. Долго чешу репу и матерюсь. Иду читать логи в Event Viewer'е. В какой-то момент обнаруживаю записи о свежепоявившихся ошибках. А ошибки, оказывается, возникают при чтении какой-то там системной DLL, не супер важной, но тем не менее. Открываю её в FAR'е по F3, она пролистывается до какого-то места и натурально далее не читается.
Что это было? Ноут в тот день ранее упал с коленей на пол. DLL была в памяти и её порча на диске была не заметна до перезагрузки.
no subject
Date: 2015-06-16 08:24 pm (UTC)> Извинился перед чуваками за наезд – хотя он бесспорно был небесполезен.
Из упоминавшихся тобой косяков, которые мне реально бросились в глаза - это то, что они вычисляют хэш данных, но не проверяют его. Они это починили, или ты, хотя бы, зафайлил баг? Это помогло бы обнаружить проблему на более ранних стадиях и избежать сorruption of replicated data.
Ещё замечание - чисто для тебя, может, я не так понял, но у меня сложилось впечатление, что твой "бэкап" это latest snapshot. Если это так, сonsider держать много snapshot'ов. Нужны месяцы, недели, дни. Дело в том, что есть куча failure modes, и software и hardware, которые могут вызвать silent data corruption. Ты узнаешь об этом только через неделю, и если у тебя нет недельной давности снапшотов, то прилетает птица обломинго.
no subject
Date: 2015-06-16 10:22 pm (UTC)Да, я предложил как минимум проверять на нулевые блобы, но всё оказалось не так просто (хотя не так и сложно). https://github.com/pouchdb/pouchdb/issues/3961#issuecomment-112405686, думаю, сделают.
По всем аттачам каждый раз это делать неэффективно, надо понимать, что лучшие реализации MD5 в браузере на i7 дают производительность в районе 20-30Мб/с, а на моб. устройствах – и вовсе в районе 0.5–1Мб/с.
> но у меня сложилось впечатление, что твой "бэкап" это latest snapshot
Не, оно круто поглубже, конечно – бóльшую часть я всё же выколупал. Тут просто сочетание факторов случилось, против которого эшелон снапшотов оказался в единичных случаях бессилен и даже тайм-машин не помогла – потому что в неё тоже писались нулевые базы. Самое новое (в пределах суток с небольшим) потерялось, потому что оно в первую очередь уходит на тайм-машин и резервный комп, с которым тоже внезапно оказалась жопа.
Как-бы не ждёшь со всех сторон то жопу, да одновременно ещё. Но урок был хороший, я же сам все условия создал – типа аптайма бытовых по сути компутеров по несколько месяцев без проверок.
no subject
Date: 2015-06-17 10:33 am (UTC)Про бэкапы понятно. Одновременная жопа с разных сторон - это знакомо, но тут, скорее, наложился эффект накопления жоп из-за затруднённого жопо-detection-а.
На днях разговаривал с папой и предложил ему обновить кучу мелких старых дисков, консолидировав, заодно решив проблему и с дополнительным местом, и с бэкапами. Предложил купить 3+4+4 или 4+5+5 (внутренний диск на 4 и два внешних для бэкапов на 5). Он (вообще-то, инженер по образованию) всерьёз спросил, зачем два диска для бэкапов. Facepalm. Но я терпеливо объяснил :)
no subject
Date: 2015-06-17 10:55 am (UTC)Задумался вчера кста, что если я позиционирую CloudWall пусть как хоть и игрушечную, но ОС – в ней должен быть чекдиск. Стало быть, будет.
> Он (вообще-то, инженер по образованию) всерьёз спросил
Это неудивительно.
Я вот недавно узнал, что в советских баллистических ракетах при минимум трёхкратном резервировании почти всего околоэлектронного при самотестировании перед пуском кабельные системы предполагались абсолютно надёжными.
Весьма странное на мой вкус допущение – но его как-то ведь обосновывали. Думаю, что понятие плавной деградации просто не было популярным в советской инженерной практике.
Кстати, по этой же причине я бы делал 3+4+5.
no subject
Date: 2016-01-07 12:49 pm (UTC)На клиенте (мобильный зоопарк из ойфонов и ондроидов разных версий) нужно логировать перемещения клиента (HTML5 geolocation, в foreground конечно). Записей может быть непойми сколько, соединение с интернет есть не везде. При появлении связи инициируется синхронизация с сервером.
Правильно ли выбрана PouchDB для этой цели? Ключевой параметр — совместимость со всем зоопарком.
Спасибо.
no subject
Date: 2016-01-07 01:01 pm (UTC)Тем не менее, в вашем случае я бы не советовал PouchDB. Вам, видимо, нужна не репликация даже, и точно не мастер-мастер, а просто выгрузка в одну сторону.
Я не знаю всех ваших вводных, тем не менее, кажется куда более рациональным хранить в localStorage до выгрузки, а по успешной выгрузке ls очищать.
no subject
Date: 2016-01-07 01:22 pm (UTC)Мне показалось, что с localStorage я замучаюсь: он позволяет только ключ-значение, а у меня для каждой точки их целый набор: широта, долгота, id юзера, id трека, токен для связанного функционала... возможно что-то еще по ходу дела добавится — я еще только структуру продумываю.
То есть получается либо пишем все в файл (который впоследствии загоняем на сервер и парсим там), либо база... С первого взгляда indexedDB/webSQL идеально подходит. А pouchDB это же только обертка для лучшей совместимости.
Или я что-то упускаю?
no subject
Date: 2016-01-07 01:33 pm (UTC)Пишите в ls JSON.stringify(yourObject), причём для экономии места лучше заранее известные поля писать как массив значений, чтобы названия свойств oбъекта не сохранять в ls.
> Или я что-то упускаю?
Минусы:
1. Репликация – как протокол – штука довольно дорогая.
2. Вы будет привязаны навсегда к этому протоколу (то-есть к CouchDB | BarrelDB | PouchDB на севере) – хотя для вашей задачи он круто избыточен
3. Вы будете вынуждены хранить на клиентах данные, которые там уже не нужны – вы не сможете по-простому удалить документы после репликации, следующая репликация удалит их и на сервере. Метод .purge есчо пока в PouchDB довольно коряво реализован.
Преимущество одно – с PouchDB проще.