Skip to content

Instantly share code, notes, and snippets.

@mszajna
mszajna / record-fn.clj
Last active February 22, 2018 01:37
Clojure record that is also a function
(defrecord Foo [state]
clojure.lang.IFn
(invoke [this]
(println "my state is" state)))
;; Try it out!
((->Foo "foo"))
my state is foo
@mszajna
mszajna / look_ma_no_frameworks.clj
Last active March 15, 2018 07:15
Clojure reloaded workflow without libraries
(extend-type Object
Closable
(.close [o] o))
(defn closable-jetty [server]
(reify Closable (close [_] (.stop server))))
(defn start []
(let [system (promise)]
(future
@mszajna
mszajna / migration.clj
Last active September 23, 2018 09:58
Datomic transaction function for migration
(def run-once
(d/function '{:lang "clojure"
:requires [[datomic.api :as d]]
:params [db db-fn]
:code (when-not (d/pull db [:data.migration/done] db-fn)
[[db-fn]
[:db/add db-fn :data.migration/done "datomic.tx"]])}))
(def schema-tx
[{:db/ident :data.migration/run-once
(defmacro either-try
([body] `(try [~body] (catch Throwable e# [nil e#])))
([body pred]
`(try [~body] (catch Throwable e# (if (~pred e#) [nil e#] (throw e#))))))
(defn risky-op [] (throw (ex-info "Oops" {:error-type :my-specific-error})))
(let [[result error] (either-try (risky-op) #(-> % ex-data :error-type (= :my-specific-error)))]
(if error
(println "got" error)
(ns executor)
(defrecord GraphqlResult [errors data])
(defn result
([v] (result nil v))
([e v] (->GraphqlResult e v)))
(defn result? [v] (instance? GraphqlResult v))
@mszajna
mszajna / core_async_bug.clj
Created July 9, 2019 20:26
Core async bug
(go (try (<! (throw (ex-info "a" {}))) (catch Exception e nil) (finally (println "here") (throw (ex-info "b" {})))))
=>
here
here
Exception b {}
(require '[datomic.api :as d])
; Datomic transaction are ACID which is achieved processing only one at a time.
; For certain workloads it's a good enough model. The built in transaction functions
; offer enforcing uniqueness and a compare-and-swap operation. They work great but
; are often too little for expressing more complex business rules.
; For those, datomic offers transaction functions, that you can install storing the
; source code in the DB.
(def conn (let [url "datomic:mem:call"] (d/create-database url) (d/connect url)))
(require 'ring.middleware.cookies)
(defn echo-handler
([request] request)
([request respond raise] (future (respond request)) nil))
(def handler
(ring.middleware.cookies/wrap-cookies
echo-handler
{:encoder (fn [_] (throw (ex-info "encoder error" {})))}))
(defn- ^Function java-fn [f]
(reify java.util.function.Function
(apply [_ x] (f x))))
(defn- to-completion-stage [response]
(if (instance? CompletionStage response)
response
(CompletableFuture/completedFuture response)))
(defn bind-response
(defn async? [response]
(instance? java.util.concurrent.CompletionStage response))
(defn- cs-handle [cs f]
(.handle ^java.util.concurrent.CompletionStage cs
(reify java.util.function.BiFunction
(apply [_ v t] (f v t)))))
(defn wrap-completable-future
"Adapts a 1-arity handler, returning either a response map or one wrapped