이 클로 잘 호출을 게으른 순서로 변환하십시오
-
06-07-2019 - |
문제
메시징 툴킷으로 작업하고 있습니다 ( 확산 그러나 나는 세부 사항이 중요하다는 것을 모른다). 이 툴킷에서 메시지를 받으면 일부 보일러 플레이트가 필요합니다.
- 데몬에 대한 연결을 만듭니다.
- 그룹에 가입하십시오.
- 하나 이상의 메시지를받습니다.
- 그룹을 떠나십시오.
- 데몬에서 분리하십시오.
내가 본 몇 가지 관용구를 따라 사용했습니다 다른 곳, 나는 Spread의 Java API 및 Clojure의 Interop 양식을 사용하여 일부 작업 기능을 요리 할 수있었습니다.
(defn connect-to-daemon
"Open a connection"
[daemon-spec]
(let [connection (SpreadConnection.)
{:keys [host port user]} daemon-spec]
(doto connection
(.connect (InetAddress/getByName host) port user false false))))
(defn join-group
"Join a group on a connection"
[cxn group-name]
(doto (SpreadGroup.)
(.join cxn group-name)))
(defn with-daemon*
"Execute a function with a connection to the specified daemon"
[daemon-spec func]
(let [daemon (merge *spread-daemon* daemon-spec)
cxn (connect-to-daemon daemon-spec)]
(try
(binding [*spread-daemon* (assoc daemon :connection cxn)]
(func))
(finally
(.disconnect cxn)))))
(defn with-group*
"Execute a function while joined to a group"
[group-name func]
(let [cxn (:connection *spread-daemon*)
grp (join-group cxn group-name)]
(try
(binding [*spread-group* grp]
(func))
(finally
(.leave grp)))))
(defn receive-message
"Receive a single message. If none are available, this will block indefinitely."
[]
(let [cxn (:connection *spread-daemon*)]
(.receive cxn)))
(기본적으로 같은 관용구 with-open
, 그냥 SpreadConnection
클래스 사용 disconnect
대신에 close
. Grr. 또한, 나는 여기서 구조적 질문과 관련이없는 매크로를 제외했습니다.)
이것은 충분히 잘 작동합니다. 나는 다음과 같은 구조 내부에서 수신 메시지를 호출 할 수 있습니다.
(with-daemon {:host "localhost" :port 4803}
(with-group "aGroup"
(... looping ...
(let [msg (receive-message)]
...))))
그것은 나에게 일어난다 receive-message
메시지를 생성하는 무한한 게으른 시퀀스 인 경우 사용하기에 더 깨끗합니다. 따라서 그룹에 가입하고 메시지를 받고 싶다면 호출 코드는 다음과 같은 것 같습니다.
(def message-seq (messages-from {:host "localhost" :port 4803} "aGroup"))
(take 5 message-seq)
나는 정리없이 게으른 시퀀스의 많은 예를 보았습니다. 너무 어렵지는 않습니다. 캐치는 위에서 4 단계와 5 단계입니다. 그룹을 떠나고 데몬에서 분리합니다. 연결 상태와 그룹을 시퀀스에 어떻게 바인딩 할 수 있습니까? 그리고 시퀀스가 더 이상 필요하지 않을 때 필요한 정리 코드를 실행합니까?
해결책
이것 기사는 Clojure-Contrib Fill-Veue를 사용하여 정확히 수행하는 방법을 설명합니다. 정리와 관련하여 - 필적 큐에 대한 깔끔한 점은 오류가 있거나 일부 조건이 도달하면 스스로를 정리하는 차단 기능을 제공 할 수 있다는 것입니다. 외부에서 제어하기 위해 리소스에 대한 참조를 보유 할 수도 있습니다. 시퀀스는 단지 종료됩니다. 따라서 시맨틱 요구 사항에 따라 적합한 전략을 선택해야합니다.
다른 팁
이 시도:
(ns your-namespace
(:use clojure.contrib.seq-utils))
(defn messages-from [daemon-spec group-name]
(let [cnx (connect-to-deamon daemon-spec))
group (connect-to-group cnx group-name)]
(fill-queue (fn [fill]
(if done?
(do
(.leave group)
(.disconnect cnx)
(throw (RuntimeException. "Finished messages"))
(fill (.receive cnx))))))
설정 완료? 목록을 끝내고 싶을 때 사실입니다. 또한 (.receive cnx)에 던져진 모든 예외도 목록을 종료합니다.