Code Monkey home page Code Monkey logo

gazeta's Introduction

Current semantic version:

[gazeta "0.2.0-SNAPSHOT"]

gazeta

A publish-subscribe (PubSub) framework for Clojure and ClojureScript, based on core.async.
Has Lamina and RxJava integration.

Usage

Basics

(ns app
  (:require [gazeta.core :as gazeta :refer [pub! sub!]]))

(sub! :posts
  (fn [{:keys [user text]}]
    (println (str user " posted: " text))))

(pub! :posts {:user "myfreeweb", :text "PubSub is magic!"})

;;;; Asynchronously printed to console:
; myfreeweb posted: PubSub is magic!

You can publish before there are any subscribers -- in that case, the message will be lost.
The subscriber function is executed in a core.async go block.

Error handling

When an exception is thrown in a subscriber function, a map with :error, :topic and :message is published to :errors and :errors-{{topic}}.
There are shorthand functions sub-all-errors! and sub-errors! to subscribe.
They accept functions that take the error, the topic and the message as separate args.

(ns app
  (:require [gazeta.core :as gazeta :refer [sub-all-errors! sub-errors! sub! pub!]]))

(sub-all-errors!
  (fn [error topic message]
    (println (str error " happened with message " message " on topic " topic))))

;; Same as:
; (sub! :errors (fn [{:keys [error topic message]}] ...))

(sub-errors! :actions
  (fn [error topic message]
    (println (str error " happened with message " message " on topic :actions"))))

;; Same as:
; (sub! :errors-actions (fn [{:keys [error topic message]}] ...))

(sub! :actions
  (fn [x] (throw (Exception. "I am an error!"))))

(sub! :actions
  (fn [x] (println (str x " happened!"))))

(pub! :actions "something")

;;;; Asynchronously printed to console:
; something happened!
; java.lang.Exception: I am an error! happened with message something on topic :actions
; java.lang.Exception: I am an error! happened with message something on topic :actions

try+ from slingshot is used in Clojure, so any object can be caught.
If you want to use slingshot's advanced matching though, use try+ explicitly in the subscriber :-)

Unsubscribing

Just pass the same args to unsub! for regular subscriptions:

(let [cb (fn [msg] (println (str "Message: " msg)))]
  (sub! :messages cb)
  (pub! :messages "Hello!")
  (unsub! :messages cb))

For error subscriptions, use the returned function instead:

(let [new-cb (sub-errors! :topic (fn [err topic msg] (prn err topic msg)))]
  (unsub-errors! :topic new-cb))

To destroy all the subscriptions, simply (unsub-all-the-things!).

Chains

Interesingly, pub!, sub!, unsub! and sub-errors! return the topic name, so you can chain them with ->:

(-> :thingy
    (sub-errors! (fn [err topic msg] (prn err topic msg)))
    (sub! println)
    (pub! "test one")
    (pub! "test two"))

;;;; Asynchronously printed to console:
; test one
; test two

You'll usually use pub! and sub! in separate functions. Often even in separate namespaces.

But the topic name is the only thing that makes sense as a return value :-)

Lamina integration

You can pipe gazeta topics with lamina channels using pub-lamina-channel! and sub-lamina-channel! from gazeta.lamina and use pub-on-realized! to publish when async-promises are realized:

(ns app
  (:use [gazeta core lamina])
  (:require [lamina.core :as lamina]
            [lamina.executor :as executor]))

(sub! :from-lamina (fn [r] (println (str "From lamina: " r))))
(def lamina-publisher (lamina/channel))
(pub-lamina-channel! :from-lamina lamina-publisher)
(lamina/enqueue lamina-publisher 1)
(lamina/enqueue lamina-publisher 2)

;;;; Asynchronously printed to console:
; From lamina: 1
; From lamina: 2


(def lamina-receiver (lamina/channel))
(sub-lamina-channel! :messages lamina-receiver)
(pub! :messages "hello")
(lamina/read-channel lamina-receiver)

; "hello"

(def lamina-receiver-2 (lamina-channel-for-topic :messages))
(pub! :messages "hello")
(lamina/read-channel lamina-receiver-2)

; "hello"


(sub! :results (fn [r] (println (str "Result: " r))))
(pub-on-realized! :results (executor/task (+ 1 2)))

;;;; Asynchronously printed to console:
; Result: 3

Note: gazeta does not depend on lamina.

RxJava integration

You can subscribe to topics as Observables using observable-for-topic and pipe Observables into topics using observable-to-topic! from gazeta.rx:

(ns app
  (:use [gazeta core rx])
  (:import rx.Observable))

(sub! :from-rx (fn [msg] (println (str "From rx: " msg))))
(observable-to-topic! :from-rx (Observable/from ["hello" "world"]))

;;;; Asynchronously printed to console:
; From rx: world
; From rx: hello

(-> (observable-for-topic :to-rx)
    (.subscribe (fn [msg] (println (str "To rx: " msg)))))
(pub! :to-rx "hi")

;;;; Asynchronously printed to console:
; To rx: hi

Note: gazeta does not depend on rxjava-core nor rxjava-clojure.

Gazeta also exposes RxJava integration as a class to use from other JVM languages. Here's a Scala example:

import gazeta.RxGazeta
import rx.Observable

RxGazeta.observableForTopic("to-scala")
  .subscribe((message: String) => {
    println("Scala got: " + message)
    RxGazeta.observableToTopic("from-scala", Observable.just("Got a message"))
  })

License

Copyright © 2013 Greg V [email protected]
This work is free. You can redistribute it and/or modify it under the
terms of the Do What The Fuck You Want To Public License, Version 2,
as published by Sam Hocevar. See the COPYING file for more details.

gazeta's People

Contributors

valpackett avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.