문제

메시징 툴킷으로 작업하고 있습니다 ( 확산 그러나 나는 세부 사항이 중요하다는 것을 모른다). 이 툴킷에서 메시지를 받으면 일부 보일러 플레이트가 필요합니다.

  1. 데몬에 대한 연결을 만듭니다.
  2. 그룹에 가입하십시오.
  3. 하나 이상의 메시지를받습니다.
  4. 그룹을 떠나십시오.
  5. 데몬에서 분리하십시오.

내가 본 몇 가지 관용구를 따라 사용했습니다 다른 곳, 나는 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)에 던져진 모든 예외도 목록을 종료합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top