Решил я прикрутить к боту погодный интерфейс.
С погодой у меня давнишнее общение: давно тому назад я вытаскивал из яндексов температуру и складывал её в munin для мониторинга, графички рисовать. Было прикольно. Но долго эта история продолжаться не могла и погоду "на грепах" разнесло к чертям, так как яндекс изменил вёрстку. Естественным образом, я тогда забил на вопрос сбора статистики.

Вернулся я к нему полгода назад, когда снова возникла идея оживить этот сервис. Решил изучить коньюнктуру. Кто что предлагает. Естественно, для некоммерческого использования - проект-то любительский и сделан не для денег. Игроков не так-то уж и много - это яха и openweathermap. В принципе, даже при такой мизерной конкуренции можно как-то жить - хоть не страницы gismeteo или yandex-а разбирать и на том спасибо...

Тогда я поленился дожать вопрос, связанный с погодным api, и осатновился на том, что качнул json-чик со списком городов и кое-как json::pp-шкой его распарсил, вынул id и сделал запрос в апи.

Мне запомнилось, что на тот момент owm просили пользоваться id-шниками городов из файлика, но можно было сделать выборку и так. А в файлике города расположены массивом, в каждом элементе которого есть имя города, его id, страна, координаты и ещё что-то. Первое, что напрашивается сделать при таком раскладе - это разложить всё это в многомерный хэш. И при первой же проверке я обнаруживаю задваивание некоторых городов. Как-то: две Москвы в России и 5 Лондонов в Штатах. У некоторых городов более точные координаты. И ладно бы разнились только координаты, но разнятся ещё и показания погоды. Конечно, это можно списать на несколько метеостанций.

Хорошо, мы выяснили, что искомый город может быть не один в регионе, но что делать с разными показаниями температуры, влажности и тд? да и вообще мы получили маппинг id-город, но ищем-то мы наоборот! сколько занимает выборка по 209+ тысячам городов по времени на таком маппинге? ~6 секунд, на том железе, которое у меня под эти нужды есть. Это явно не фонтан.

Сделаю небольшое отступлене: дело в том, что я не люблю реляционные бд, так как во многих случаях это перебор. У меня в этой задаче все выборки сводятся к выбору значения по ключу, ничего хитрого. SQL в данном случае не нужен - он просто осложняет логику как выборки, так и обработки полученных данных. А в перле уже есть встроенный механизм привязывания хэшей к некоторым видам k-v баз, в частности к Berkeley DB и к LevelDB, если надо. Данных у меня немного так что Berkeley DB, по идее, справляется неплохо, поэтому я решил остановиться на ней, тем более, что она идёт в штатной поставке перла.

Давай, зайдём на эту проблему с другой стороны - построим карту город->список id. Зашёл я на эту задачу изначально не с той стороны - то есть я строил id->город, а затем из неё делал выборку и строил город->id-list. Получалось настолько медленно, что ожидаемое время построения - несколько суток - получалось неподходящим. Однако, нам же никто не мешает изначально при разборе входных данных строить таблицу как прямого, так и обратного маппинга, чтобы не делать поиска по непроиндексированному полю. Сказано - сделано. База построилась, выборка происходит за полсекунды, при этом выбираются сразу несколько типов данных - не только города и id, но и страны, в которых эти города засели, и координаты.

Всё бы хорошо, но сколько занимает в памяти процесс, который сливает, молотит данные и строит эти базы? А каких-то 230-240 мегабайт. А на виртуалке всего гигабайт. Из них уже занято более 330 мегабайт. Это не то чтобы проблема, но лишний раз не хотелось бы съедать память. Просто на всякий случай. Да и потом - есть ограничение - название города надо указывать на латинице, причём часть названий с юникодными символами, их не то что угадать, а записать-то сложно. Это (виртуально) проблема. Аудитория-то у сервиса не располагает к тому, чтобы писать названия на латинице, да ещё и с диакритическими и не только символами.

Решил почитать что пишут авторы api про языковые варианты своего поделия, а то ходить в переводчики и транслировать названия городов bulk или on demand, с кэшированием - это тоже такое себе удовольствие.

Пишут - вы можете делать запрос в api с названием города и получать некоторые описания на родном языке, поддерживаемые языки... вуаля помимо английского, китайского и прочих... ещё и русский. Проверил - работает.

Значит, первомайские праздники пошли коту под хвост: нам не нужно запрашивать города по id, их система вполне может выдать информацию и по городу со страной и даже без страны. При условии, что городов не один, выбирается город с наивысшим приоритетом (который считается, вероятно, по населению/географическим размерам и ещё каким-то дополнительным параметрам).

Зато 9-е мая не прошло даром, к телеграмному боту за полдня багополучно прикрутилась эта погодка.

По пути выяснилось, что сервис сбоит чаще, чем хотелось бы, поэтому кэш его всё-таки спасает.

В бэклоге остаётся ещё джабберный бот и, когда появится более-менее приличный, ирк-бот, их тоже надо "окучить". Но предварительно надо дать коду отлежаться (всё-таки параллельно было немножко прибрано в коде бота) чтобы какие-то недочёты всплыли, после этого его можно будет коммитить и выкладывать в публику.

Next Post