Last active
August 29, 2015 14:04
-
-
Save jcromartie/23f0bf7c3956172169b6 to your computer and use it in GitHub Desktop.
Totally naive event based system in Clojure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defonce handlers (atom {})) | |
(defn- install-handler! | |
[topic-key f] | |
(swap! handlers assoc topic-key f)) | |
(defmacro on | |
"Registers a global message handler for the given topic keyword. A | |
single handler can be registered at a time for a given topic | |
keyword. Handlers are dispatched based on the name portion of the | |
topic keyword, so you may register multiple handlers for the same | |
message topic by namespacing the keyword." | |
[topic binding & body] | |
`(install-handler! ~topic (fn ~binding ~@body))) | |
(defn raise! | |
"Raise an event with a given topic keyword and data. Data will be | |
passed to any registered handlers in parallel." | |
[topic data] | |
(doseq [[handler-topic handler-fn] @handlers] | |
(when (= (name topic) (name handler-topic)) | |
(future | |
(try | |
(handler-fn data) | |
(catch Throwable t | |
(println "Error in handler" handler-topic "-" (.getMessage t)))))))) | |
;; example use | |
(comment | |
;;; a business logic namespace | |
(ns business.users ...) | |
(defn register-user! | |
[info] | |
(when (get-user (:username info)) | |
(throw (IllegalArgumentException. "A user with this name already exists"))) | |
(raise! :user-registered (assoc info :time (Date.)))) | |
;;; an email notification | |
(ns services.email) | |
(on ::user-registered | |
[user] | |
(let [message "Thanks for signing up!"] | |
(send-email! (:email user) message) | |
(raise! :user-notified (assoc user :message message :time (Date.))))) | |
;;; a data model | |
(ns model.users ...) | |
(defonce users (atom nil)) | |
(on ::user-registered | |
[{:keys [username time] :as user}] | |
(swap! users assoc username (assoc user :registered time)) | |
(raise! :user-updated username)) | |
(on ::user-notified | |
[{:keys [username message time]}] | |
(swap! users update-in [username])) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment