diff --git a/README.md b/README.md index 6743f91..b59c6bc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Current [semantic](http://semver.org/) version: ```clojure -[com.taoensso/touchstone "0.13.1"] +[com.taoensso/touchstone "0.14.0"] ``` # Touchstone, a Clojure split-testing library @@ -26,7 +26,7 @@ Touchstone is an attempt to bring **dead-simple, high-power split-testing** to a Depend on Touchstone in your `project.clj`: ```clojure -[com.taoensso/touchstone "0.13.1"] +[com.taoensso/touchstone "0.14.0"] ``` and `require` the library: @@ -49,7 +49,7 @@ Traditional split-testing consists of 4 steps: The particular multi-armed bandit technique used by Touchstone means that we only concern ourselves with steps 1 and 3. Steps 2 and 4 are handled automatically by the algorithm. -**To optimize a Ring web application**, start by adding `(taoensso.touchstone.ring/make-wrap-random-test-subject-id)` to your middleware stack. +**To optimize a Ring web application**, start by adding `(taoensso.touchstone.ring/wrap-random-test-subject-id)` to your middleware stack. One or more named-test selectors can then be used as part of your page content: diff --git a/project.clj b/project.clj index 7df52d0..40b9dea 100644 --- a/project.clj +++ b/project.clj @@ -1,10 +1,10 @@ -(defproject com.taoensso/touchstone "0.13.1" +(defproject com.taoensso/touchstone "0.14.0" :description "Clojure split-testing library" :url "https://github.com/ptaoussanis/touchstone" :license {:name "Eclipse Public License"} :dependencies [[org.clojure/clojure "1.3.0"] [org.clojure/tools.macro "0.1.1"] - [com.taoensso/carmine "1.1.0"] + [com.taoensso/carmine "1.6.0"] [org.clojure/math.combinatorics "0.0.3"]] :profiles {:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]} :1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} diff --git a/src/taoensso/touchstone.clj b/src/taoensso/touchstone.clj index 74680a9..3f5d8cb 100644 --- a/src/taoensso/touchstone.clj +++ b/src/taoensso/touchstone.clj @@ -26,17 +26,16 @@ ;;;; Config & bindings (utils/defonce* config - "This map atom controls everything about the way Touchstone operates. - See source code for details. - - WARNING: per-test config API very likely to change before 1.x release." + "Alpha - subject to change. + This map atom controls everything about the way Touchstone operates. + See source code for details." (atom {:carmine {:pool (car/make-conn-pool) :spec (car/make-conn-spec)} :tests {:default {:test-session-ttl 7200 ; Last activity +2hrs ;; Turn on for engagement testing: :count-duplicate-activity? false}}})) -(defn set-config! [[k & ks] val] (swap! config assoc-in (cons k ks) val)) +(defn set-config! [ks val] (swap! config assoc-in ks val)) (defn test-config "Returns per-test config, merged over defaults." [test-name] diff --git a/src/taoensso/touchstone/ring.clj b/src/taoensso/touchstone/ring.clj index b3dcb65..a36cb9a 100644 --- a/src/taoensso/touchstone/ring.clj +++ b/src/taoensso/touchstone/ring.clj @@ -14,21 +14,25 @@ (comment (bot-user-agent? {"user-agent" "GoogleBot"})) -(defn make-wrap-random-test-subject-id - "Returns Ring middleware that generates, sessionizes, and binds a test-subject - id for requests eligible for split-testing (by default this excludes clients - that report themselves as bots)." - [& {:keys [eligible?-fn] +(defn wrap-random-test-subject-id + "Ring middleware that generates, sessionizes, and binds a test-subject id for + requests eligible for split-testing (by default this excludes clients that + report themselves as bots)." + [handler + & {:keys [eligible?-fn] :or {eligible?-fn (fn [request] (not (bot-user-agent? (:headers request))))}}] - (fn [handler] - (fn [request] - (if-not (eligible?-fn request) - (handler request) + (fn [request] + (if-not (eligible?-fn request) + (handler request) + + (if (contains? (:session request) :mab-subject-id) + (let [sessionized-id (get-in request [:session :mab-subject-id])] + (touchstone/with-test-subject sessionized-id (handler request))) - (if (contains? (:session request) :mab-subject-id) - (let [sessionized-id (get-in request [:session :mab-subject-id])] - (touchstone/with-test-subject sessionized-id (handler request))) + (let [new-id (str (rand-int 2147483647)) + response (touchstone/with-test-subject new-id (handler request))] + (assoc-in response [:session :mab-subject-id] new-id)))))) - (let [new-id (str (rand-int 2147483647)) - response (touchstone/with-test-subject new-id (handler request))] - (assoc-in response [:session :mab-subject-id] new-id))))))) \ No newline at end of file +(defn make-wrap-random-test-subject-id + "DEPRECATED. Please use `wrap-random-test-subject-id." + [& args] (fn [handler] (apply wrap-random-test-subject-id handler args))) \ No newline at end of file diff --git a/src/taoensso/touchstone/utils.clj b/src/taoensso/touchstone/utils.clj index d963a13..5c6274e 100644 --- a/src/taoensso/touchstone/utils.clj +++ b/src/taoensso/touchstone/utils.clj @@ -52,7 +52,5 @@ (time (dotimes [_ 10000] (name :foo))) (time (dotimes [_ 10000] (scoped-name :foo)))) -(defn approx= - [x y & {:keys [significance] - :or {significance 0.001}}] - (< (- x y) significance)) \ No newline at end of file +(defn approx= [x y & [signf]] + (< (Math/abs (double (- x y))) (or signf 0.001))) \ No newline at end of file