Где разместить соединение с Монгером в приложении 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 во время выполнения.

Другие вопросы по тегам