From 11842ae332d16478c4ea85306211348bb33a30fd Mon Sep 17 00:00:00 2001 From: seki Date: Fri, 9 Sep 2016 01:15:50 +0900 Subject: [PATCH 01/14] enable to recieve JSON to create job --- src/clj/job_streamer/control_bus/util.clj | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/clj/job_streamer/control_bus/util.clj b/src/clj/job_streamer/control_bus/util.clj index 1a8b706..4efcdd5 100644 --- a/src/clj/job_streamer/control_bus/util.clj +++ b/src/clj/job_streamer/control_bus/util.clj @@ -3,7 +3,8 @@ [clojure.edn :as edn] [clojure.java.io :as io] [datomic.api :as d] - [ring.util.request :refer [content-type]]) + [ring.util.request :refer [content-type]] + [clojure.data.json :as json]) (:import [org.jsoup Jsoup])) (defn to-int [n default-value] @@ -126,6 +127,11 @@ java.lang.String body (slurp (io/reader body))))) +(defn json->edn + "Convert a format from JSON to edn" + [json] + (json/read-str json :key-fn keyword)) + (defn parse-body [context] (when (#{:put :post} (get-in context [:request :request-method])) (try @@ -133,6 +139,7 @@ (case (or (content-type (:request context)) (get-in context [:request :content-type])) "application/edn" [false {:edn (edn/read-string body)}] "application/xml" [false {:edn (xml->edn body)}] + "application/json" [false {:edn (json->edn body)}] false) false) (catch Exception e From c3816e6bfcdcbbdff1cb70720556a4cfa13b0062 Mon Sep 17 00:00:00 2001 From: seki Date: Fri, 9 Sep 2016 23:56:32 +0900 Subject: [PATCH 02/14] enable convert --- project.clj | 1 + src/clj/job_streamer/control_bus/component/agents.clj | 4 ++-- src/clj/job_streamer/control_bus/component/apps.clj | 6 +++--- .../job_streamer/control_bus/component/calendar.clj | 7 ++++--- src/clj/job_streamer/control_bus/component/jobs.clj | 10 +++++----- .../job_streamer/control_bus/component/scheduler.clj | 2 +- src/clj/job_streamer/control_bus/util.clj | 9 ++++++++- 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/project.clj b/project.clj index 629ce65..0a585a1 100644 --- a/project.clj +++ b/project.clj @@ -15,6 +15,7 @@ [com.datomic/datomic-free "0.9.5372" :exclusions [org.slf4j/slf4j-api org.slf4j/slf4j-nop com.amazonaws/aws-java-sdk]] [org.jsoup/jsoup "1.9.2"] + [org.clojure/data.json "0.2.6"] [datomic-schema "1.3.0"] [liberator "0.14.1"] [compojure "1.5.1"] diff --git a/src/clj/job_streamer/control_bus/component/agents.clj b/src/clj/job_streamer/control_bus/component/agents.clj index 48fa0be..aaafe42 100644 --- a/src/clj/job_streamer/control_bus/component/agents.clj +++ b/src/clj/job_streamer/control_bus/component/agents.clj @@ -14,7 +14,7 @@ (defn list-resource [{:keys [agents]}] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get] :handle-ok (fn [ctx] (->> (vals @agents) @@ -35,7 +35,7 @@ (defn entry-resource [{:keys [agents datomic]} instance-id & [cmd]] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :put] :put! (fn [ctx] (when-let [uuid (UUID/fromString instance-id)] diff --git a/src/clj/job_streamer/control_bus/component/apps.clj b/src/clj/job_streamer/control_bus/component/apps.clj index a4f7891..58d959e 100644 --- a/src/clj/job_streamer/control_bus/component/apps.clj +++ b/src/clj/job_streamer/control_bus/component/apps.clj @@ -71,7 +71,7 @@ (defn list-resource [{:keys [datomic applications]}] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :post] :malformed? #(validate (parse-body %) :application/name v/required @@ -106,7 +106,7 @@ (defn batch-components-resource [{:keys [datomic]} app-name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get] :handle-ok (fn [ctx] (let [in-app (->> (d/query datomic @@ -126,7 +126,7 @@ (defn stats-resource [{:keys [datomic agents]} app-name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get] :handle-ok (fn [ctx] {:agents (count (ag/available-agents agents)) diff --git a/src/clj/job_streamer/control_bus/component/calendar.clj b/src/clj/job_streamer/control_bus/component/calendar.clj index daee994..a2a65b1 100644 --- a/src/clj/job_streamer/control_bus/component/calendar.clj +++ b/src/clj/job_streamer/control_bus/component/calendar.clj @@ -20,7 +20,7 @@ (defn list-resource [{:keys [datomic scheduler]}] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :post] :malformed? #(validate (parse-body %) :calendar/name v/required) @@ -35,6 +35,7 @@ true)) :post! (fn [{cal :edn}] + (println cal) (let [id (or (:db/id cal) (d/tempid :db.part/user))] (if-let [old-id (d/query datomic '{:find [?calendar .] @@ -64,7 +65,7 @@ (defn entry-resource [{:keys [datomic scheduler]} name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :put :delete] :malformed? (fn [ctx] (or (validate (parse-body ctx) @@ -77,7 +78,7 @@ '{:find [(pull ?e [:*]) .] :in [$ ?n] :where [[?e :calendar/name ?n]]} name) - + :put! (fn [{cal :edn}] (d/transact datomic [{:db/id (:db/id cal) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index 0e9108f..e8e029b 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -212,7 +212,7 @@ (defn list-resource [{:keys [datomic scheduler] :as jobs} app-name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :post] :malformed? (fn [ctx] (validate (parse-body ctx) @@ -273,7 +273,7 @@ (defn entry-resource [{:keys [datomic scheduler] :as jobs} app-name job-name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :put :delete] :malformed? #(parse-body %) :exists? (when-let [[app-id job-id] (find-by-name jobs app-name job-name)] @@ -325,7 +325,7 @@ (defn job-settings-resource [{:keys [datomic] :as jobs} app-name job-name & [cmd]] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :delete :put] :malformed? #(parse-body %) :exists? (when-let [[app-id job-id] (find-by-name jobs app-name job-name)] @@ -426,7 +426,7 @@ (defn executions-resource [{:keys [datomic] :as jobs} app-name job-name] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :post] :malformed? #(parse-body %) :exists? (when-let [[app-id job-id] (find-by-name jobs app-name job-name)] @@ -460,7 +460,7 @@ (defn execution-resource [{:keys [agents scheduler datomic] :as jobs} id & [cmd]] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:get :put] :malformed? #(parse-body %) :exists? (fn [ctx] diff --git a/src/clj/job_streamer/control_bus/component/scheduler.clj b/src/clj/job_streamer/control_bus/component/scheduler.clj index 639d8a7..714876f 100644 --- a/src/clj/job_streamer/control_bus/component/scheduler.clj +++ b/src/clj/job_streamer/control_bus/component/scheduler.clj @@ -134,7 +134,7 @@ (defn entry-resource [{:keys [datomic] :as scheduler} job-id & [cmd]] (liberator/resource - :available-media-types ["application/edn"] + :available-media-types ["application/edn" "application/json"] :allowed-methods [:post :put :delete] :malformed? #(parse-body %) :exists? (fn [ctx] diff --git a/src/clj/job_streamer/control_bus/util.clj b/src/clj/job_streamer/control_bus/util.clj index 4efcdd5..4de0728 100644 --- a/src/clj/job_streamer/control_bus/util.clj +++ b/src/clj/job_streamer/control_bus/util.clj @@ -127,10 +127,17 @@ java.lang.String body (slurp (io/reader body))))) +(defn json-value-reader [key value] + (if (= key :calendar/holidays) + (java.sql.Date/valueOf value) + value)) + (defn json->edn "Convert a format from JSON to edn" [json] - (json/read-str json :key-fn keyword)) + (json/read-str json + :key-fn keyword + :value-fn json-value-reader)) (defn parse-body [context] (when (#{:put :post} (get-in context [:request :request-method])) From 98446008bd1fc18cf3900e8fb45cb79c080a9855 Mon Sep 17 00:00:00 2001 From: seki Date: Mon, 12 Sep 2016 18:28:29 +0900 Subject: [PATCH 03/14] make json->edn parser accept Date --- src/clj/job_streamer/control_bus/util.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clj/job_streamer/control_bus/util.clj b/src/clj/job_streamer/control_bus/util.clj index 4de0728..d51a8de 100644 --- a/src/clj/job_streamer/control_bus/util.clj +++ b/src/clj/job_streamer/control_bus/util.clj @@ -129,7 +129,7 @@ (defn json-value-reader [key value] (if (= key :calendar/holidays) - (java.sql.Date/valueOf value) + (for [date value] (java.sql.Date/valueOf date)) value)) (defn json->edn From 6ebc8c28b0da06a10527b2632cd5448fd43633e7 Mon Sep 17 00:00:00 2001 From: seki Date: Wed, 14 Sep 2016 22:16:00 +0900 Subject: [PATCH 04/14] add version api --- VERSION | 2 +- src/clj/job_streamer/control_bus/endpoint/api.clj | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b336edf..978ba2b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0-SNAPSHOT +0.7.0-SNAPSHOT diff --git a/src/clj/job_streamer/control_bus/endpoint/api.clj b/src/clj/job_streamer/control_bus/endpoint/api.clj index d25c7a6..cea1cc8 100644 --- a/src/clj/job_streamer/control_bus/endpoint/api.clj +++ b/src/clj/job_streamer/control_bus/endpoint/api.clj @@ -5,6 +5,7 @@ [clojure.tools.logging :as log] [compojure.core :refer [ANY GET routes]] [bouncer.validators :as v] + [ring.util.response :refer [content-type]] (job-streamer.control-bus.component [apps :as apps] [jobs :as jobs] @@ -75,6 +76,8 @@ (apps/batch-components-resource apps app-name)) (ANY "/:app-name/stats" [app-name] (apps/stats-resource apps app-name)) + (GET "/version" [] (-> {:body (clojure.string/replace (str "\"" (slurp "VERSION") "\"") "\n" "")} + (content-type "text/plain"))) ;; For debug ;(GET "/logs" [] (pr-str (model/query '{:find [[(pull ?log [*]) ...]] :where [[?log :execution-log/level]]}))) From 744fda5fe744d05e2ee4f6afa2db991203182d7f Mon Sep 17 00:00:00 2001 From: seki Date: Thu, 22 Sep 2016 01:37:03 +0900 Subject: [PATCH 05/14] move only name --- .../control_bus/component/jobs.clj | 81 ++++++++++++++++--- .../control_bus/component/jobs_test.clj | 12 +++ 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index e8e029b..fcd08b3 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -4,6 +4,8 @@ [com.stuartsierra.component :as component] [bouncer.validators :as v] [liberator.core :as liberator] + [clojure.string :as str] + (job-streamer.control-bus [notification :as notification] [validation :refer [validate]] [util :refer [parse-body edn->datoms to-int]]) @@ -12,7 +14,7 @@ [scheduler :as scheduler])) (:import [java.util Date])) -(defn- find-latest-execution +(defn find-latest-execution "Find latest from given executions." [executions] (when executions @@ -68,18 +70,79 @@ [?job :job/name ?job-name]]} app-name job-name)) +(defn parse-query [query] + (loop [query-vector (str/split query #"\s") + query-map {:job-names []}] + (if-let [query-unit (first query-vector)] + (if (.startsWith query-unit "since:") + (recur (rest query-vector) (assoc query-map :since (.substring query-unit 6))) + (if (.startsWith query-unit "until:") + (recur (rest query-vector) (assoc query-map :until (.substring query-unit 6))) + (if (.startsWith query-unit "exit-status:") + (recur (rest query-vector) (assoc query-map :exit-status (.substring query-unit 12))) + (recur (rest query-vector) (update-in query-map [:job-names] conj query-unit))))) + query-map))) (defn find-all [{:keys [datomic]} app-name query & [offset limit]] - (let [base-query '{:find [?job] - :in [$ ?app-name ?query] + (let [query-map (if query (parse-query query) nil) + base-query '{:find [?job] + :in [$ ?app-name ?job-name-condition ?since-condition ?until-condition ?exit-status-condition] :where [[?app :application/name ?app-name] - [?app :application/jobs ?job]]} + [?app :application/jobs ?job] + [?job :job/name ?job-name]]} + job-name-condition (:job-names query-map) + since-condition (:since query-map) + until-condition (:until query-map) + exit-status-condition (:exit-status query-map) jobs (d/query datomic - (if (not-empty query) - (update-in base-query [:where] - conj '[(fulltext $ :job/name ?query) [[?job ?job-name]]]) - base-query) - app-name (or query ""))] + (cond-> base-query + (not-empty job-name-condition) + (update-in [:where] conj + '[(.contains ^String ?job-name ?job-name-condition)]) + (or since-condition until-condition exit-status-condition) + (update-in [:where] conj + '[?job :job/executions ?job-executions] + '[(job-streamer.control-bus.component.jobs/find-latest-execution ?job-executions) ?last-execution] + '[?last-execution :job-execution/exit-status ?exit-status] + '[?last-execution :job-execution/end-time ?end-time]) + since-condition + (update-in [:where] conj + '[(<= ?end-time ?since-condition)]) + until-condition + (update-in [:where] conj + '[(>= ?end-time ?until-condition)]) + exit-status-condition + (update-in [:where] conj + '[(.contains ^String ?exit-status ?exit-status-condition)])) + app-name + (or (some-> query-map :job-names first) "") + (or since-condition "") + (or until-condition "") + (or exit-status-condition ""))] + (println query-map) + (println job-name-condition) + (println exit-status-condition) + (println (or since-condition until-condition exit-status-condition)) + (println (cond-> base-query + (not-empty job-name-condition) + (update-in [:where] conj + '[(.contains ^String ?job-name ?job-name-condition)]) + (or since-condition until-condition exit-status-condition) + (update-in [:where] conj + '[?job :job/executions ?job-executions] + '[(job-streamer.control-bus.component.jobs/find-latest-execution ?job-executions) ?last-execution] + '[?last-execution :job-execution/exit-status ?exit-status] + '[?last-execution :job-execution/end-time ?end-time]) + since-condition + (update-in [:where] conj + '[(<= ?end-time ?since-condition)]) + until-condition + (update-in [:where] conj + '[(>= ?end-time ?until-condition)]) + (nil? exit-status-condition) + (update-in [:where] conj + '[(.contains ^String ?exit-status ?exit-status-condition)]))) + {:results (->> jobs (drop (dec (or offset 0))) (take (or limit 20)) diff --git a/test/clj/job_streamer/control_bus/component/jobs_test.clj b/test/clj/job_streamer/control_bus/component/jobs_test.clj index a76bc27..c6c1993 100644 --- a/test/clj/job_streamer/control_bus/component/jobs_test.clj +++ b/test/clj/job_streamer/control_bus/component/jobs_test.clj @@ -71,3 +71,15 @@ (is (= 201 (-> (handler request) :status)))) (let [res (jobs/find-all (:jobs system) "default" nil)] (is (= 1 (:hits res))))))) + +(deftest parse-query + (testing "parse-query" + (println (jobs/parse-query "a b since:2016-09-01 batch-status:COMP")) + (is (="a" (first (:job-names (jobs/parse-query "a b"))))))) + +(deftest find-all-with-query + (testing "find-all" + (let [system (new-system config)] + (let [res (jobs/find-all (:jobs system) "default" "exit-status:COMP")] + (is (= 0 (:hits res))) + (is (empty? (:results res))))))) From 7c9fb9034ace961df73546c09471d3dd64252648 Mon Sep 17 00:00:00 2001 From: seki Date: Thu, 22 Sep 2016 02:07:30 +0900 Subject: [PATCH 06/14] refactor --- src/clj/job_streamer/control_bus/component/jobs.clj | 6 +++--- test/clj/job_streamer/control_bus/component/jobs_test.clj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index fcd08b3..5ba0a3d 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -75,9 +75,9 @@ query-map {:job-names []}] (if-let [query-unit (first query-vector)] (if (.startsWith query-unit "since:") - (recur (rest query-vector) (assoc query-map :since (.substring query-unit 6))) + (recur (rest query-vector) (assoc query-map :since (java.sql.Date/valueOf (.substring query-unit 6)))) (if (.startsWith query-unit "until:") - (recur (rest query-vector) (assoc query-map :until (.substring query-unit 6))) + (recur (rest query-vector) (assoc query-map :until (java.sql.Date/valueOf (.substring query-unit 6)))) (if (.startsWith query-unit "exit-status:") (recur (rest query-vector) (assoc query-map :exit-status (.substring query-unit 12))) (recur (rest query-vector) (update-in query-map [:job-names] conj query-unit))))) @@ -139,7 +139,7 @@ until-condition (update-in [:where] conj '[(>= ?end-time ?until-condition)]) - (nil? exit-status-condition) + exit-status-condition (update-in [:where] conj '[(.contains ^String ?exit-status ?exit-status-condition)]))) diff --git a/test/clj/job_streamer/control_bus/component/jobs_test.clj b/test/clj/job_streamer/control_bus/component/jobs_test.clj index c6c1993..85b3e6d 100644 --- a/test/clj/job_streamer/control_bus/component/jobs_test.clj +++ b/test/clj/job_streamer/control_bus/component/jobs_test.clj @@ -74,7 +74,7 @@ (deftest parse-query (testing "parse-query" - (println (jobs/parse-query "a b since:2016-09-01 batch-status:COMP")) + (println (jobs/parse-query "a b since:2016-09-01 exit-status:COMP")) (is (="a" (first (:job-names (jobs/parse-query "a b"))))))) (deftest find-all-with-query From 9dec6f84690ff823ce2fc1e8c975b356fcef8770 Mon Sep 17 00:00:00 2001 From: seki Date: Thu, 22 Sep 2016 02:33:09 +0900 Subject: [PATCH 07/14] refactor --- test/clj/job_streamer/control_bus/component/jobs_test.clj | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/clj/job_streamer/control_bus/component/jobs_test.clj b/test/clj/job_streamer/control_bus/component/jobs_test.clj index 85b3e6d..2e7fc6c 100644 --- a/test/clj/job_streamer/control_bus/component/jobs_test.clj +++ b/test/clj/job_streamer/control_bus/component/jobs_test.clj @@ -74,8 +74,11 @@ (deftest parse-query (testing "parse-query" - (println (jobs/parse-query "a b since:2016-09-01 exit-status:COMP")) - (is (="a" (first (:job-names (jobs/parse-query "a b"))))))) + (let [result (jobs/parse-query "a b since:2016-09-01 until:2016-09-02 exit-status:COMPLETED")] + (is (= "a" (first (:job-names result)))) + (is (= (java.sql.Date/valueOf "2016-09-01") (:since result))) + (is (= (java.sql.Date/valueOf "2016-09-02") (:until result))) + (is (= "COMPLETED" (:exit-status result)))))) (deftest find-all-with-query (testing "find-all" From d7ef95fc5adbe4489bc05c064ab49011b076521d Mon Sep 17 00:00:00 2001 From: seki Date: Thu, 22 Sep 2016 02:35:56 +0900 Subject: [PATCH 08/14] refactor --- .../control_bus/component/jobs.clj | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index 5ba0a3d..1848ab0 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -119,29 +119,6 @@ (or since-condition "") (or until-condition "") (or exit-status-condition ""))] - (println query-map) - (println job-name-condition) - (println exit-status-condition) - (println (or since-condition until-condition exit-status-condition)) - (println (cond-> base-query - (not-empty job-name-condition) - (update-in [:where] conj - '[(.contains ^String ?job-name ?job-name-condition)]) - (or since-condition until-condition exit-status-condition) - (update-in [:where] conj - '[?job :job/executions ?job-executions] - '[(job-streamer.control-bus.component.jobs/find-latest-execution ?job-executions) ?last-execution] - '[?last-execution :job-execution/exit-status ?exit-status] - '[?last-execution :job-execution/end-time ?end-time]) - since-condition - (update-in [:where] conj - '[(<= ?end-time ?since-condition)]) - until-condition - (update-in [:where] conj - '[(>= ?end-time ?until-condition)]) - exit-status-condition - (update-in [:where] conj - '[(.contains ^String ?exit-status ?exit-status-condition)]))) {:results (->> jobs (drop (dec (or offset 0))) From cc13b9566c32aa2788bc6c4d376a465fbf4a87ee Mon Sep 17 00:00:00 2001 From: seki Date: Fri, 23 Sep 2016 22:19:34 +0900 Subject: [PATCH 09/14] make it completely move --- dev/dev.clj | 2 +- .../job_streamer/control_bus/component/jobs.clj | 14 ++++++++------ src/clj/job_streamer/control_bus/system.clj | 7 +++++-- .../control_bus/component/jobs_test.clj | 7 ------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/dev/dev.clj b/dev/dev.clj index 8f9ab96..adb528c 100644 --- a/dev/dev.clj +++ b/dev/dev.clj @@ -14,7 +14,7 @@ [job-streamer.control-bus.system :as system])) (def dev-config - {:app {:middleware [wrap-stacktrace]} + {:app {:middleware [wrap-stacktrace :stacktrace]} :datomic {:uri "datomic:mem://jobstreamer"}}) (def config diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index 1848ab0..f88557c 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -102,15 +102,16 @@ (or since-condition until-condition exit-status-condition) (update-in [:where] conj '[?job :job/executions ?job-executions] - '[(job-streamer.control-bus.component.jobs/find-latest-execution ?job-executions) ?last-execution] - '[?last-execution :job-execution/exit-status ?exit-status] - '[?last-execution :job-execution/end-time ?end-time]) + '[?job-execution :job-execution/create-time ?create-time] + '[(max ?create-time)] + '[?job-executions :job-execution/exit-status ?exit-status] + '[?job-executions :job-execution/end-time ?end-time]) since-condition (update-in [:where] conj - '[(<= ?end-time ?since-condition)]) + '[(>= ?end-time ?since-condition)]) until-condition (update-in [:where] conj - '[(>= ?end-time ?until-condition)]) + '[(<= ?end-time ?until-condition)]) exit-status-condition (update-in [:where] conj '[(.contains ^String ?exit-status ?exit-status-condition)])) @@ -308,7 +309,8 @@ :status-notification/exit-status :status-notification/type] (:db/id sn)))) vec)})))))) - vec)))))) + vec)))) + :etag (str (int (/ (System/currentTimeMillis) 10000))))) (defn entry-resource [{:keys [datomic scheduler] :as jobs} app-name job-name] diff --git a/src/clj/job_streamer/control_bus/system.clj b/src/clj/job_streamer/control_bus/system.clj index 76227a8..c9b2691 100644 --- a/src/clj/job_streamer/control_bus/system.clj +++ b/src/clj/job_streamer/control_bus/system.clj @@ -21,7 +21,8 @@ [socketapp :refer [socketapp-component]]) (job-streamer.control-bus.endpoint [api :refer [api-endpoint]]) - [job-streamer.control-bus.endpoint.api :refer [api-endpoint]])) + [job-streamer.control-bus.endpoint.api :refer [api-endpoint]]) + (:use ring.middleware.stacktrace)) (defn wrap-same-origin-policy [handler alias] @@ -38,7 +39,9 @@ (def base-config {:app {:middleware [[wrap-not-found :not-found] [wrap-same-origin-policy :same-origin] - [wrap-defaults :defaults]] + [wrap-defaults :defaults] + [ring.middleware.stacktrace/wrap-stacktrace :stacktrace]] + :not-found "Resource Not Found" :defaults (meta-merge api-defaults {})}}) diff --git a/test/clj/job_streamer/control_bus/component/jobs_test.clj b/test/clj/job_streamer/control_bus/component/jobs_test.clj index 2e7fc6c..81101ab 100644 --- a/test/clj/job_streamer/control_bus/component/jobs_test.clj +++ b/test/clj/job_streamer/control_bus/component/jobs_test.clj @@ -79,10 +79,3 @@ (is (= (java.sql.Date/valueOf "2016-09-01") (:since result))) (is (= (java.sql.Date/valueOf "2016-09-02") (:until result))) (is (= "COMPLETED" (:exit-status result)))))) - -(deftest find-all-with-query - (testing "find-all" - (let [system (new-system config)] - (let [res (jobs/find-all (:jobs system) "default" "exit-status:COMP")] - (is (= 0 (:hits res))) - (is (empty? (:results res))))))) From a14de51db38c657dc84b86fbe19a0c4cfb02a63a Mon Sep 17 00:00:00 2001 From: seki Date: Sat, 24 Sep 2016 00:13:14 +0900 Subject: [PATCH 10/14] apply plural job name --- src/clj/job_streamer/control_bus/component/jobs.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index f88557c..8dbbbf2 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -86,7 +86,7 @@ (defn find-all [{:keys [datomic]} app-name query & [offset limit]] (let [query-map (if query (parse-query query) nil) base-query '{:find [?job] - :in [$ ?app-name ?job-name-condition ?since-condition ?until-condition ?exit-status-condition] + :in [$ ?app-name [?job-name-condition ...] ?since-condition ?until-condition ?exit-status-condition] :where [[?app :application/name ?app-name] [?app :application/jobs ?job] [?job :job/name ?job-name]]} @@ -116,7 +116,7 @@ (update-in [:where] conj '[(.contains ^String ?exit-status ?exit-status-condition)])) app-name - (or (some-> query-map :job-names first) "") + (or job-name-condition [""]) (or since-condition "") (or until-condition "") (or exit-status-condition ""))] From 24607a435bac22464cfd665d7750984d45db1e73 Mon Sep 17 00:00:00 2001 From: seki Date: Sat, 24 Sep 2016 00:13:52 +0900 Subject: [PATCH 11/14] update datomic version --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 0a585a1..a0a67b9 100644 --- a/project.clj +++ b/project.clj @@ -12,7 +12,7 @@ [net.unit8.wscl/websocket-classloader "0.2.1"] [net.unit8.logback/logback-websocket-appender "0.1.0"] [io.undertow/undertow-websockets-jsr "1.3.22.Final"] - [com.datomic/datomic-free "0.9.5372" :exclusions [org.slf4j/slf4j-api org.slf4j/slf4j-nop + [com.datomic/datomic-free "0.9.5394" :exclusions [org.slf4j/slf4j-api org.slf4j/slf4j-nop com.amazonaws/aws-java-sdk]] [org.jsoup/jsoup "1.9.2"] [org.clojure/data.json "0.2.6"] From 41689e2165c02b7d0d0fb4cfc31a0cff870a347a Mon Sep 17 00:00:00 2001 From: seki Date: Sat, 24 Sep 2016 00:47:07 +0900 Subject: [PATCH 12/14] fix it cant serch when query dont have job-name --- src/clj/job_streamer/control_bus/component/jobs.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index 8dbbbf2..cbb723e 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -88,8 +88,7 @@ base-query '{:find [?job] :in [$ ?app-name [?job-name-condition ...] ?since-condition ?until-condition ?exit-status-condition] :where [[?app :application/name ?app-name] - [?app :application/jobs ?job] - [?job :job/name ?job-name]]} + [?app :application/jobs ?job]]} job-name-condition (:job-names query-map) since-condition (:since query-map) until-condition (:until query-map) @@ -98,7 +97,8 @@ (cond-> base-query (not-empty job-name-condition) (update-in [:where] conj - '[(.contains ^String ?job-name ?job-name-condition)]) + '[?job :job/name ?job-name] + '[(.contains ^String ?job-name ?job-name-condition)]) (or since-condition until-condition exit-status-condition) (update-in [:where] conj '[?job :job/executions ?job-executions] @@ -116,7 +116,7 @@ (update-in [:where] conj '[(.contains ^String ?exit-status ?exit-status-condition)])) app-name - (or job-name-condition [""]) + (or (not-empty job-name-condition) [""]) (or since-condition "") (or until-condition "") (or exit-status-condition ""))] From 7508cd80b4685489dea1edfc90a075212f840170 Mon Sep 17 00:00:00 2001 From: kawasima Date: Tue, 27 Sep 2016 02:50:18 +0900 Subject: [PATCH 13/14] Refactoring a query parser for job --- .../control_bus/component/jobs.clj | 97 +++++++++++-------- src/clj/job_streamer/control_bus/system.clj | 7 +- .../control_bus/component/jobs_test.clj | 29 +++++- 3 files changed, 82 insertions(+), 51 deletions(-) diff --git a/src/clj/job_streamer/control_bus/component/jobs.clj b/src/clj/job_streamer/control_bus/component/jobs.clj index cbb723e..172efb7 100644 --- a/src/clj/job_streamer/control_bus/component/jobs.clj +++ b/src/clj/job_streamer/control_bus/component/jobs.clj @@ -2,10 +2,11 @@ (:require [clojure.tools.logging :as log] [clojure.edn :as edn] [com.stuartsierra.component :as component] + [bouncer.core :as b] [bouncer.validators :as v] [liberator.core :as liberator] [clojure.string :as str] - + [clj-time.format :as f] (job-streamer.control-bus [notification :as notification] [validation :refer [validate]] [util :refer [parse-body edn->datoms to-int]]) @@ -70,56 +71,70 @@ [?job :job/name ?job-name]]} app-name job-name)) +(defn- parse-query-since [q] + (let [since (.substring q (count "since:"))] + (when (b/valid? {:since since} + :since [[v/datetime (:date f/formatters)]]) + {:since (f/parse (:date f/formatters) since)}))) + +(defn- parse-query-until [q] + (let [until (.substring q (count "until:"))] + (when (b/valid? {:until until} + :until [[v/datetime (:date f/formatters)]]) + {:until (f/parse (:date f/formatters) until)}))) + +(defn- parse-query-exit-status [q] + (let [exit-status (.substring q (count "exit-status:"))] + (when (b/valid? {:exit-status exit-status} + :exit-status v/required) + {:exit-status exit-status}))) + (defn parse-query [query] - (loop [query-vector (str/split query #"\s") - query-map {:job-names []}] - (if-let [query-unit (first query-vector)] - (if (.startsWith query-unit "since:") - (recur (rest query-vector) (assoc query-map :since (java.sql.Date/valueOf (.substring query-unit 6)))) - (if (.startsWith query-unit "until:") - (recur (rest query-vector) (assoc query-map :until (java.sql.Date/valueOf (.substring query-unit 6)))) - (if (.startsWith query-unit "exit-status:") - (recur (rest query-vector) (assoc query-map :exit-status (.substring query-unit 12))) - (recur (rest query-vector) (update-in query-map [:job-names] conj query-unit))))) - query-map))) + (when (not-empty query) + (->> (str/split query #"\s") + (map #(cond + (.startsWith % "since:") (parse-query-since %) + (.startsWith % "until:") (parse-query-until %) + (.startsWith % "exit-status:") (parse-query-exit-status %) + :default {:job-name [%]})) + (apply merge-with concat {:job-name nil})))) (defn find-all [{:keys [datomic]} app-name query & [offset limit]] - (let [query-map (if query (parse-query query) nil) + (let [qmap (parse-query query) base-query '{:find [?job] :in [$ ?app-name [?job-name-condition ...] ?since-condition ?until-condition ?exit-status-condition] :where [[?app :application/name ?app-name] [?app :application/jobs ?job]]} - job-name-condition (:job-names query-map) - since-condition (:since query-map) - until-condition (:until query-map) - exit-status-condition (:exit-status query-map) jobs (d/query datomic (cond-> base-query - (not-empty job-name-condition) - (update-in [:where] conj - '[?job :job/name ?job-name] - '[(.contains ^String ?job-name ?job-name-condition)]) - (or since-condition until-condition exit-status-condition) - (update-in [:where] conj - '[?job :job/executions ?job-executions] - '[?job-execution :job-execution/create-time ?create-time] - '[(max ?create-time)] - '[?job-executions :job-execution/exit-status ?exit-status] - '[?job-executions :job-execution/end-time ?end-time]) - since-condition - (update-in [:where] conj - '[(>= ?end-time ?since-condition)]) - until-condition - (update-in [:where] conj - '[(<= ?end-time ?until-condition)]) - exit-status-condition - (update-in [:where] conj - '[(.contains ^String ?exit-status ?exit-status-condition)])) + (not-empty (:job-name qmap)) + (update-in [:where] conj + '[?job :job/name ?job-name] + '[(.contains ^String ?job-name ?job-name-condition)]) + (or (:since qmap) (:until qmap) (:exit-status qmap)) + (update-in [:where] conj + '[?job :job/executions ?job-executions] + '[?job-execution :job-execution/create-time ?create-time] + '[(max ?create-time)] + '[?job-executions :job-execution/exit-status ?exit-status] + '[?job-executions :job-execution/end-time ?end-time]) + + (:since qmap) + (update-in [:where] conj + '[(>= ?end-time ?since-condition)]) + + (:until qmap) + (update-in [:where] conj + '[(<= ?end-time ?until-condition)]) + + (:exit-status qmap) + (update-in [:where] conj + '[(.contains ^String ?exit-status ?exit-status-condition)])) app-name - (or (not-empty job-name-condition) [""]) - (or since-condition "") - (or until-condition "") - (or exit-status-condition ""))] + (:job-name qmap []) + (:since qmap "") + (:until qmap "") + (:exit-status qmap ""))] {:results (->> jobs (drop (dec (or offset 0))) diff --git a/src/clj/job_streamer/control_bus/system.clj b/src/clj/job_streamer/control_bus/system.clj index c9b2691..ecea67d 100644 --- a/src/clj/job_streamer/control_bus/system.clj +++ b/src/clj/job_streamer/control_bus/system.clj @@ -21,9 +21,7 @@ [socketapp :refer [socketapp-component]]) (job-streamer.control-bus.endpoint [api :refer [api-endpoint]]) - [job-streamer.control-bus.endpoint.api :refer [api-endpoint]]) - (:use ring.middleware.stacktrace)) - + [job-streamer.control-bus.endpoint.api :refer [api-endpoint]])) (defn wrap-same-origin-policy [handler alias] (fn [req] @@ -39,8 +37,7 @@ (def base-config {:app {:middleware [[wrap-not-found :not-found] [wrap-same-origin-policy :same-origin] - [wrap-defaults :defaults] - [ring.middleware.stacktrace/wrap-stacktrace :stacktrace]] + [wrap-defaults :defaults]] :not-found "Resource Not Found" :defaults (meta-merge api-defaults {})}}) diff --git a/test/clj/job_streamer/control_bus/component/jobs_test.clj b/test/clj/job_streamer/control_bus/component/jobs_test.clj index 81101ab..b25f1b3 100644 --- a/test/clj/job_streamer/control_bus/component/jobs_test.clj +++ b/test/clj/job_streamer/control_bus/component/jobs_test.clj @@ -10,7 +10,8 @@ [meta-merge.core :refer [meta-merge]] [clojure.test :refer :all] [clojure.pprint :refer :all] - [clojure.edn :as edn])) + [clojure.edn :as edn] + [clj-time.format :as f])) @@ -75,7 +76,25 @@ (deftest parse-query (testing "parse-query" (let [result (jobs/parse-query "a b since:2016-09-01 until:2016-09-02 exit-status:COMPLETED")] - (is (= "a" (first (:job-names result)))) - (is (= (java.sql.Date/valueOf "2016-09-01") (:since result))) - (is (= (java.sql.Date/valueOf "2016-09-02") (:until result))) - (is (= "COMPLETED" (:exit-status result)))))) + (is (= "a" (first (:job-name result)))) + (is (= "2016-09-01" (f/unparse (:date f/formatters) (:since result)))) + (is (= "2016-09-02" (f/unparse (:date f/formatters) (:until result)))) + (is (= "COMPLETED" (:exit-status result))))) + (testing "nil query returns nil" + (let [result (jobs/parse-query nil)] + (is (nil? result)))) + (testing "empty query returns nil" + (let [result (jobs/parse-query "")] + (is (nil? result)))) + + (testing "single simple query" + (let [result (jobs/parse-query "a")] + (is (= {:job-name '("a")} result)))) + + (testing "single simple query" + (let [result (jobs/parse-query "a")] + (is (= {:job-name '("a")} result)))) + + (testing "ignore breaking tokens in a query" + (let [result (jobs/parse-query "a since: until: since:xxx until:yyy")] + (is (= {:job-name '("a")} result))))) From da3640d86a48a713025303508e26f55f378bef0a Mon Sep 17 00:00:00 2001 From: kawasima Date: Tue, 27 Sep 2016 13:32:49 +0900 Subject: [PATCH 14/14] Fixes the version for release --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 978ba2b..faef31a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7.0-SNAPSHOT +0.7.0