Skip to content

Instantly share code, notes, and snippets.

View ptaoussanis's full-sized avatar
👋
Hey! Hope you're having an awesome day :-)

Peter Taoussanis ptaoussanis

👋
Hey! Hope you're having an awesome day :-)
View GitHub Profile
@ptaoussanis
ptaoussanis / smart_memoize.clj
Created June 14, 2012 11:19
More powerful memoize for Clojure
(def ^:private gc-sm-cache!
"Maintains maximum cache size by intelligently pruning less valuable items."
(let [gc-running? (atom false)]
(fn [cache ttl max-items now]
(when-not @gc-running?
(reset! gc-running? true)
(let [snapshot @cache
@ptaoussanis
ptaoussanis / resource_modified.clj
Created June 15, 2012 11:48
Fn to check for modified resource files
(def some-file-resources-modified?
"Returns true iff any of the files backing given resources have changed
since this function was last called."
(let [times (atom {})]
(fn modified?
([resource-name & more] (some modified? (cons resource-name more)))
([resource-name]
(when-let [^File file (try (->> resource-name io/resource io/file)
(catch Exception _ nil))]
(let [last-modified (.lastModified file)]
@ptaoussanis
ptaoussanis / gist:3045473
Created July 4, 2012 05:10
Change standard Timbre appenders to use println instead of atomic (buffering) printer
(let [new-fn (ƒ [{:keys [more] :as args}]
(apply println (prefixed-message args) more))]
(set-config! [:appenders :standard-out :fn] new-fn)
(set-config! [:appenders :standard-out-or-err :fn] new-fn))
@ptaoussanis
ptaoussanis / free-port.clj
Created December 14, 2012 06:28
A little utility to allow simple redeployment of Clojure web servers with zero downtime, and without the need for a proxy or load balancer. Just wrap any port-binding calls, and the utility will auto kill pre-existing servers as necessary. *nix only. Based on the blog post by Feng Shen, http://shenfeng.me/fast-restart-clojure-webapp.html
;; (require '[clojure.string :as str] '[clojure.java.shell :as shell] '[taoensso.timbre :as timbre])
(defn with-free-port!
"Attempts to kill any current port-binding process, then repeatedly executes
nullary `bind-port!-fn` (which must return logical true on successful
binding). Returns the function's result when successful, else throws an
exception. *nix only.
This idea courtesy of Feng Shen, Ref. http://goo.gl/kEolu."
[port bind-port!-fn & {:keys [max-attempts sleep-ms]
@ptaoussanis
ptaoussanis / declare-remote.clj
Created December 31, 2012 09:21
Make forward declarations in any namespace to circumvent circular dependency limitations.
(defmacro declare-remote
"Declares the given ns-qualified names, preserving symbol metadata. Useful for
circular dependencies."
[& names]
`(do ~@(map (fn [n]
(let [ns (namespace n)
v (name n)
m (meta n)]
`(do (in-ns '~(symbol ns))
(declare ~(with-meta (symbol v) m))))) names)
;;; 13 June 2013: Clojure 1.5.1, Nippy mpenet/2.0.0-alpha3 (nio)
{:reader {:freeze 23491, :thaw 26074, :round 49720, :data-size 22956}}
{:defaults {:freeze 4080, :thaw 2432, :round 5961, :data-size 12403}}
{:encrypted {:freeze 5725, :thaw 3791, :round 9310, :data-size 12421}}
{:fast {:freeze 3479, :thaw 1981, :round 5462, :data-size 13343}}
;;; 13 June 2013: Clojure 1.5.1, Nippy 2.0.0-alpha1
{:reader {:freeze 23124, :thaw 26469, :round 47674, :data-size 22923}}
{:defaults {:freeze 4007, :thaw 2520, :round 6038, :data-size 12387}}
{:encrypted {:freeze 5560, :thaw 3867, :round 9157, :data-size 12405}}
(ns n01se.externs-for-cljs
(:require [clojure.java.io :as io]
[cljs.compiler :as comp]
[cljs.analyzer :as ana]))
(defn read-file [file]
(let [eof (Object.)]
(with-open [stream (clojure.lang.LineNumberingPushbackReader. (io/reader file))]
(vec (take-while #(not= % eof)
(repeatedly #(read stream false eof)))))))
;;; First we'll define a new kind of (degenerate) connection pool to encapsulate the behavior you want:
(defrecord SingletonPool [conn] ; Keeps a single connection atom
IConnectionPool
(get-conn [_ spec]
(or (when-let [c @conn] (when (conn-alive? c) c)) ; Aliveness check may not be necessary
(println "making a new conn!")
(reset! conn (make-new-connection spec))))
(release-conn [_ _] nil)
(release-conn [this _ _] nil)
@ptaoussanis
ptaoussanis / more-ifs.clj
Created July 31, 2013 11:22
Some `if`/`when` helpers. Don't need these often (and avoid them whenever possible), but they're occasionally handy when dealing with particularly hairy code.
(defmacro iff [test & {:keys [then else]}] `(if ~test ~then ~else))
(comment (iff false
:then (println "true")
:else (println "false")))
(defmacro iff-let [bindings & {:keys [then else]}] `(if-let ~bindings ~then ~else))
(comment (iff-let [x true] :else "false" :then x))
(defmacro if-lets
"Like `if-let` but binds multiple values iff all tests are true."
(ns n01se.externs-for-cljs
(:require [clojure.java.io :as io]
[cljs.compiler :as comp]
[cljs.analyzer :as ana]))
(defn read-file [file]
(let [eof (Object.)]
(with-open [stream (clojure.lang.LineNumberingPushbackReader. (io/reader file))]
(vec (take-while #(not= % eof)
(repeatedly #(read stream false eof)))))))