clojure.lang.LazySeq нельзя преобразовать в clojure.lang.IFn

Я новичок в Riemann и Clojure. Все, что я хочу сделать, это отправить уведомления по электронной почте трем группам электронной почты, когда истек срок TTL какой-либо службы. Я создал какой-то файл конфигурации, в котором я храню список адресов электронной почты:

{
  :email_group_1 (
                  "[email protected]"
                  "[email protected]"
                 )
  :email_group_2 (
                  "[email protected]"
                 )
}

Моя конфигурация Римана выглядит так:

(logging/init {:console true})
(import org.apache.log4j.Level)
(logging/set-level Level/DEBUG)

(require '[clojure.java.io :as io])
(import '[java.io PushbackReader])

(let [host "0.0.0.0"]
  (tcp-server {:host host :port 60001})
  (udp-server {:host host})
  (ws-server  {:host host :port 60003}))
(repl-server  {:host "127.0.0.1"})

(def cwd (System/getProperty "user.dir"))

(def emails
  (with-open [r (io/reader (str cwd "/etc/emails.clj"))]
             (read (PushbackReader. r))))

(periodically-expire 5)

(def email (mailer))

(defn notify [& egroups]
  (for [egroup egroups]
    (rollup 1 60 (apply email (emails egroup)))))

(let [index (index)]
  (streams
    (default :ttl 60
      index

      (expired
          (where (service "service_connect_active")
                    #(info "expired" %)
                    (notify :email_group_1 :email_group_2))))))

Код выглядит хорошо (для меня), но когда срок действия этой службы истек, я получаю следующую ошибку:

09:45:39 riemann.1      | INFO [2015-05-08 10:45:39,313] Thread-5 - riemann.config - expired {:ttl 60, :time 357766884827/250, :state expired, :service service_connect_active, :host ava.local}
09:45:39 riemann.1      | WARN [2015-05-08 10:45:39,319] Thread-5 - riemann.config - clojure.lang.LazySeq@841649b8 threw
09:45:39 riemann.1      | java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
09:45:39 riemann.1      |   at riemann.config$eval66$stream__70$fn__75.invoke(riemann.development.config:34)
09:45:39 riemann.1      |   at riemann.config$eval66$stream__70.invoke(riemann.development.config:45)
09:45:39 riemann.1      |   at riemann.streams$match$stream__3514$fn__3525.invoke(streams.clj:1209)
09:45:39 riemann.1      |   at riemann.streams$match$stream__3514.invoke(streams.clj:1209)
09:45:39 riemann.1      |   at riemann.streams$default$stream__3731$fn__3742.invoke(streams.clj:1328)
09:45:39 riemann.1      |   at riemann.streams$default$stream__3731.invoke(streams.clj:1328)
09:45:39 riemann.1      |   at riemann.core$stream_BANG_$fn__4415.invoke(core.clj:19)
09:45:39 riemann.1      |   at riemann.core$stream_BANG_.invoke(core.clj:18)
09:45:39 riemann.1      |   at riemann.core$reaper$worker__4529$fn__4539.invoke(core.clj:303)
09:45:39 riemann.1      |   at riemann.core$reaper$worker__4529.invoke(core.clj:297)
09:45:39 riemann.1      |   at riemann.service.ThreadService$thread_service_runner__1973$fn__1974.invoke(service.clj:71)
09:45:39 riemann.1      |   at riemann.service.ThreadService$thread_service_runner__1973.invoke(service.clj:70)
09:45:39 riemann.1      |   at clojure.lang.AFn.run(AFn.java:22)
09:45:39 riemann.1      |   at java.lang.Thread.run(Thread.java:745)

Может ли кто-нибудь помочь мне? Спасибо.


person Alexey Astafyev    schedule 08.05.2015    source источник
comment
Откуда берется почтовая функция вашего римановского конфига?   -  person tnoda    schedule 08.05.2015
comment
@tnoda mailer — открытая переменная Римана. Более подробная информация находится здесь http://riemann.io/api/riemann.email.html#var-mailer   -  person Alexey Astafyev    schedule 13.05.2015


Ответы (1)


Ошибка «не может быть приведена к clojure.lang.IFn» неизменно указывает на то, что ожидает, что функция получит что-то, что нельзя рассматривать как таковое...

(defn notify [& egroups]
  (for [egroup egroups]
    (rollup 1 60 (apply email (emails egroup)))))

Это возвращает сгенерированный LazySeq потоков свертки, а не фактический поток (в Римане поток — это IFn). Поэтому, когда Риман пытается вызвать поток как IFn, возникает ваша ошибка...

Как насчет чего-то вроде:

(defn notify [& egroups]
  (rollup 1 60 (apply email (mapcat emails egroups))))

Здесь мы просто заранее преобразуем список групп в список адресов электронной почты, а затем продолжаем жить дальше.

В качестве альтернативы, если вам действительно нужно несколько потоков (например, избегая общих строк To:), примените их к сведению.

(defn notify [& egroups]
  (apply rollup 1 60 (map email (map emails groups))))

Надеюсь, это поможет, я, очевидно, не реплицирую всю вашу конфигурацию.

person pete23    schedule 09.05.2015
comment
Мне очень жаль :) Я никогда не задавал вопросов в StackOverflow, поэтому не знал некоторых правил. Поскольку у меня слишком низкая репутация сайта, я не могу проголосовать за ваш ответ :( Но я очень ценю вашу помощь! - person Alexey Astafyev; 13.05.2015