Где разместить соединение с Монгером в приложении Compojure для Heroku?
Я создал приложение compojure, используя lein new compojure mongotest
с lein 2.0 и Procfile web: lein ring server-headless $PORT
, Это работало нормально, но теперь, когда я добавляю
(def mongolab-url (System/getenv "MONGOLAB_URI"))
(println "mongolab-url")
(println mongolab-url)
(mg/connect-via-uri! mongolab-url)
когда я пытаюсь git push heroku master
Героку в конце концов дает мне
Compiling mongotest.handler
mongolab-url
nil
Exception in thread "main" java.lang.NullPointerException, compiling:(handler.clj:13:1)
... 25 more
Compilation failed: Subprocess failed
Error encountered performing task 'compile' with profile(s): 'production'
Suppressed exit
! Failed to build.
! Push rejected, failed to compile Clojure (Leiningen 2) app
Я добавил эти строки на верхнем уровне handler.clj
, Часть старой документации, которую я вижу, создана в main
, но это должно было быть для старых версий compojure, так как нет main
больше (что я нашел) в сгенерированном приложении. Где должно быть установлено соединение в текущей версии? (Или мой Procfile не прав?)
(Да, MONGOLAB_URI
определяется в heroku config
)
2 ответа
Ответ, который сработал для меня и кажется наиболее идиоматичным, состоит в том, чтобы поместить вышеуказанное соединение в функцию init
в том же файле (myproject/handler.clj
)
(defn init[] (mg/connect-via-uri! (System/getenv "MONGOLAB_URI")))
и обновить project.clj
строка дескриптора кольца файла из
:ring {:handler myproject.handler/app}
в
:ring {:handler myproject.handler/app :init myproject.handler/init}
Вы не хотите, чтобы побочные эффекты (такие как открытие соединения с базой данных) возникали во время загрузки пространства имен, что фактически является временем компиляции. Зачастую такие вещи могут сойти с рук, когда вы компилируете свой код при запуске clojure, но в этом случае heroku предварительно компилирует ваше приложение в jar-файл, чтобы оно могло быстрее его обрабатывать. Теперь, во время компиляции, вы пытаетесь прочитать PORT
переменная окружения; но он не установлен, пока heroku не попытается запустить ваше приложение.
Решение состоит в том, чтобы создать его только во время выполнения, например, путем -main
или в какой-то другой функции, или определяя ее как delay
который ты только force
во время выполнения.