Frage

ich mit einem Messaging-Toolkit gerade arbeitete (es passiert Verbreiten sein, aber ich weiß nicht, dass die Details ankommt). Empfangen von Nachrichten von diesem Toolkit erfordert einigen Textvorschlag:

  1. Erstellen Sie eine Verbindung mit dem Dämon.
  2. Schließen Sie sich einer Gruppe.
  3. Erhalten Sie eine oder mehrere Nachrichten.
  4. Lassen Sie die Gruppe.
  5. Trennen vom Dämon.

Im Anschluss an einige Idiome, die ich verwendet habe gesehen anderswo , ich war in der Lage zu kochen einige Funktionen Arbeits der Spread-Java-API und Clojure der Interop-Formulare mit:

(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)))

(Im Grunde das gleiche Idiom wie with-open, nur, dass die SpreadConnection Klasse verwendet disconnect statt close. Grr. Außerdem habe ich einige Makros weggelassen, die hier nicht relevant für die strukturelle Frage sind.)

Das funktioniert gut genug. Ich nenne kann-Nachricht empfängt, die von innen von einer Struktur wie:

(with-daemon {:host "localhost" :port 4803}
  (with-group "aGroup"
    (... looping ...
      (let [msg (receive-message)] 
        ...))))

Es fällt mir ein, würde das receive-message Reiniger zu verwenden, wenn es eine unendliche faul Sequenz waren die Nachrichten produziert. Also, wenn ich aussehen sollte etwas eine Gruppe und erhalten Nachrichten, die anrufende Code beitreten wollten:

(def message-seq (messages-from {:host "localhost" :port 4803} "aGroup"))
(take 5 message-seq)

Ich habe viele Beispiele für faule Sequenzen ohne Bereinigung gesehen, das ist nicht zu hart. Der Haken ist, Schritte # 4 und 5 von oben: die Gruppe verlassen und vom Dämon trennen. Wie kann ich binde den Zustand der Verbindung und die Gruppe in die Sequenz und den notwendigen Bereinigungscode ausgeführt werden, wenn die Sequenz nicht mehr benötigt wird?

War es hilfreich?

Lösung

Dieser Artikel beschreibt wie genau das zu tun, Clojure-contrib Fill-Warteschlange verwendet wird. In Bezug auf Cleanup - die nette Sache über Fill-Warteschlange ist, dass Sie eine Sperrfunktion, die selbst aufräumt liefern können, wenn ein Fehler auftritt oder ein Zustand erreicht. Sie können auch einen Verweis auf die Ressource halten, um sie extern zu steuern. Die Sequenz wird nur beenden. Also je nach semantischer Anforderung Sie die Strategie wählen, das paßt.

Andere Tipps

Versuchen Sie folgendes:

(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))))))

Set getan? true, wenn Sie die Liste zu beenden. Außerdem werden alle Ausnahmen in (.receive CNX) geworfen wird auch die Liste beenden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top