Replication race
У нас недавно в процессе тестовых прогонов одного проекта нашёлся удивительного свойства баг, такой очень хитрый race. Race этот прожил в глубинах CloudWall-а два года никак не проявляясь ни в тестах, ни в реальной жизни.
Вернее, он, вероятно, проявлялся, но этот race до определённых условий имеет тенденцию саморассасываться, и поэтому может быть незаметен.
История такая.
Мы гоняли репликацию тестового working set-а с бэкэнда на клиент, проверяя как это работает при разных условиях сети и как нагружается бэкэнд фильтрацией потока репликации.
И я внезапно заметил, что на медленной сети как-то непропорционально долго всё. А приглядевшись, увидел что и данных передаётся кратно больше чем нужно – причём чем медленнее сеть, тем больше кратность. И на совсем-совсем медленной сети процесс вообще никогда не заканчивается.
Никаких 4хх, 5хх или обрывов по пути нет, то есть оно не рестартует на ошибку, оно просто много раз качает одно и то же.
Дело оказалось вот в чём.
CloudWall устроен так, что не даёт никакой репликации длиться дольше определённого промежутка времени, если она вышла за таймслот, она завершается на той точке, до куда дошла, и через некоторое время рестартует.
Это сделано для того, чтобы ни один процесс репликации не мог надолго монопольно захватить каналы передачи. Типичный браузер не поддерживает больше 10 одновременно открытых XHR-соединений на вкладку, остальные стоЯт и ждут освобождения слота.
Так как CloudWall партиционирует локальную базу и может поддерживать связь сразу с несколькими удалёнными БД, такой подход оправдан. Беда только, что он даёт race на медленных каналах – потому что PouchDB старой версии, что используется, иногда не закрывает соединение при отмене репликации.
То-есть оно продолжает качать себе дальше, если там что-то длинное.
И когда этого длинного сразу много одновременно, сразу во всех слотах соединений браузера, на момент начала следующего цикла репликации эти недокаченные в предыдущем цикле чанки снова ставятся в подмороженную очередь и всё повторяется.
Пока не наступает одно из пограничных условий (а они довольно искуственные), рэйс так или иначе рассасывается – потому и не заметно было. Тесты то проходят.
Интересно, что починилось в ~10 строк кода, но доставило невообразимо, да.
no subject