Как изменение двух строк кода может занять несколько дней

Интересно верит ли кто-либо еще что работу разработчика можно измерить количеством строк кода? Попробуем вместе развенчать этот старый, как мир, миф своими красными глазами.

q3auxqqio0qjycw3hfjixtdwms8.jpeg


Сложно ли изменить две строчки кода?

Герой этой истории — open source проект H2 database популярной реляционной базы данных для тестов, веб консоли для SQL и даже содержит внутри себя аналог LevelDB/Berkeley DB Java Edition/SQLite 3. Отличный проект, много раз использовал за свою практику и не было проблем. До тех пор пока не попытался использовать его совместно с redshift jdbc driver.

Есть такая база данных в AWS, Redshift — форк времен PostgreSQL 8.0.2. Где-то в том же десятилетии появился и его конкурент greenplum-db… Несмотря на то что эта БД имеет массово-параллельную архитектуру, и прочие «плюшки» column-oriented DBMS, при работе с ней не покидает ощущение что ты в музее компьютерной истории. Понял, что это ощущение было неспроста, когда обнаружил что в приложении конфликтуют драйвера современного PostgreSQL 9.6 и Redshift драйвер ископаемого wire протокола postgresql 8.x.

Обнаружил что используется PG wire protocol 8.x, когда подключался к PostgreSQL 9.6 в H2 web консоли. Результаты меня огорчили и я начал разбираться как же такое может происходить. Отладка привела в строчку получения соединения:

 DriverManager.getConnection(url, prop);


Вроде бы все выглядит по спецификации, так как это не JNDI и не javax.sql.DataSource.

Спускаемся глубже в DriverManager. Там все и так известно и ожидаемо. В его блоке статической инициализации используется ServiceLoader для загрузки реализующих java.sql.Driver и заявляющих об этом с помощью записи о реализации META-INF/services/java.sql.Driver в своем jar. Это достаточно давно отменило использование Class.forName (driver) — так все современные драйверы загружаются без этого ископаемого вызова. Ничего нового для меня тут нет.

Драйверы при запросе соединения перебираются в порядке, как они зарегистрировались в поле registeredDrivers. DriverManager для каждого из них по цепочке вызывает driver.connect (url, info). Если конкретный драйвер вернул объект соединения с базой данных, возвращаем его из функции. Первый кто обработал connection URL из цепочки драйверов побеждает!

Драйвер сам анализирует может ли он обработать подпротокол jdbc: subprotocol. На мою беду redshift jdbc драйвер обрабатывал кроме своего «redshift» еще и «postgresql», но с помощью древнего кода эпохи середины 2000х. Ясно, что connection url запрос никогда не дойдет до драйвера postgres 9.6.

Один плюс в карму разработчикам redshift jdbc — спасибо хоть классы древней реализации PG в отдельный пакет спрятали, а не оставили конфликтовать с org.postgresql.Driver в jar hell. Попробовал использовать более «свежий» их драйвер, но он не работал внутри spring boot executable jar, так как в нем зависимости упаковали «матрешкой» — jar’ы зависимостей внутри jar драйвера.

При этом пул соединений HikariCP правильно создает новый драйвер postgresql, в отличии от консоли H2. Раз уж пользователь указал driverClass, то он на нем и вызывает connect не полагаясь на DriverManager. Это работает в аду, учиненном redshift jdbc. Причина была найдена быстро и стало ясно как решать проблему.

Патч был создан в выходной и отправлен как pull request в репозитарий проекта, заодно создал заявку об ошибке. После этого началась переписка и аргументация изменения контрибьютором, вторым по активности в репозитарии h2database. Я выполнил все его требования и замечания для этого pull request и изменения приняли в основной код проекта. Ушло много свободного времени из-за двух строчек изменений и драйвера redshift. Но тут уже был азарт и дело принципа — выжить в мире где ископаемый протокол перекрывает современный. Спасибо ему за уделенное время, за то что вник в эту проблему. Верю что дотошность при приеме pull request в популярном open source проекте идет на пользу качеству. Чтобы две моих строчки исправления бага появились в проекте, заняло почти два выходных дня.

Другой pull request в schemaspy висит уже больше недели, но тут проблема с тем что разрабатывал его на linux, а не работает на windows системе. Каюсь — не дотестировал.

Делитесь про то, как несколько строк кода поглощали время. Есть интригующие истории и рассказы детективного жанра?

© Habrahabr.ru