diff options
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | src/clj/queue_api/db/core.clj | 9 | ||||
| -rw-r--r-- | src/clj/queue_api/routes/services.clj | 12 | ||||
| -rw-r--r-- | test/clj/queue_api/test/db/core_test.clj | 20 | 
4 files changed, 37 insertions, 21 deletions
| @@ -12,8 +12,8 @@ then access [localhost:3000/swagger-ui](http://localhost:3000/swagger-ui/index.h  ## Stack -I chose [luminus](http://www.luminusweb.net/) for my stack as it makes the initial setup way easier since it provide a wide range option of configuration for a bunch of technologies. -To bootstrap the project I used `lein new luminus queue-api +swagger +service +kibit` plus datascrypt which doesn't come with Luminus. +I chose [luminus](http://www.luminusweb.net/) for my stack as it makes the initial setup way easier, it provides a wide range profiles for a bunch of technologies. +I bootstrapped  the project with `lein new luminus queue-api +swagger +service +kibit` plus datascrypt which doesn't come with Luminus.  ### +Swagger @@ -21,15 +21,15 @@ When possible I always add it to a project for it make easier to visualize and t  ### +Service -To remove all front end stuff since I didn't need it. +To remove all front end stuff since I don't need it.  ### +Kibit -I added because it gives some insight how to make you code more idiomatic. +It gives some insight how to make you code more idiomatic.  ### Datascript -I chose [datascript](https://github.com/tonsky/datascript) for its easy setup, after little to no effort I had it working. +[datascript](https://github.com/tonsky/datascript) was chosen for its easy setup, after little to no effort I had it working.  Even though it was meant to run on browser it fit nicely in the project, and because it works pretty much like Datomic it has [powerful query system](https://docs.datomic.com/on-prem/query.html) and works seamlessly with clojure.  Additionally it had an okay [non-documentation](https://github.com/tonsky/datascript/wiki/Getting-started) with some [samples](https://github.com/kristianmandrup/datascript-tutorial) and if I couldn't find for Datascript I'd search for a Datomic seeing that query system of both are compatible.   @@ -70,7 +70,8 @@ Those models wrap up in schema:  ### services.clj  After all luminus file there is actually two files that have the core logic of the app `services.clj` and `db/core.cljs`. -For `services.clj` it holds all code for endpoint definition and model validation. considering the exercise requirements we gonna need 5 endpoints: +For `services.clj` it holds all code for endpoint definition and input validation.  +Considering the exercise requirements there is a need for 5 endpoints:  * Endpoint to add agent is  a`:put` at `/agent`    * Endpoint to get how many jobs of each type this agent has performed is a `:post` at `/agent`. Note: usually since it is a method that doesn't modify anything I'd have used `:get` and pass the agent id via path (`/agent/:id`) but one of the requirement is "*All endpoints should accept and return JSON content type payloads*" I worked with POST PUT. @@ -84,7 +85,7 @@ For model and validation details access swagger-ui.  Core.clj holds all logic to interact with Datascrip therefore all the code to manage the queue.  The idea behind it is actually simpler than part 1 since Datascrip handle the hard word.  -For example, to store jobs and agents I'd simply `transact!` the entire object and we good to go. +For example, to store jobs and agents I'd simply `transact!` the entire object and it is good to go.  ```clojure   (d/transact! queue-api.db.core/conn @@ -95,7 +96,7 @@ For example, to store jobs and agents I'd simply `transact!` the entire object a                   :job/status :unassigned}])  ``` -While with a simple query I can fetch the exact piece of information that I need for the moment. +While with a simple query I could fetch the exact piece of information that I need for the moment.  ```clojure  (d/q '[:find ?d ?id diff --git a/src/clj/queue_api/db/core.clj b/src/clj/queue_api/db/core.clj index c76f0fb..0482feb 100644 --- a/src/clj/queue_api/db/core.clj +++ b/src/clj/queue_api/db/core.clj @@ -102,7 +102,12 @@          (if (seq jn)            (first jn)))))) -(defn request-job +(defn agent +  "Get a agent by id" +  [id] +  (d/entity @conn [:agent/id id])) + +(defn fittest-job    "Get the fittest job for a agent `id`."    [^String id]    (let [a (d/entity @conn [:agent/id id])] @@ -146,7 +151,7 @@    [^String id]    (let [a (d/entity @conn [:agent/id id])]      (if-not (nil? a) -      (let [jid (:job/id (request-job id))] +      (let [jid (:job/id (fittest-job id))]          (end-job a)          (start-job id jid)          jid))))
\ No newline at end of file diff --git a/src/clj/queue_api/routes/services.clj b/src/clj/queue_api/routes/services.clj index 0b26281..766f831 100644 --- a/src/clj/queue_api/routes/services.clj +++ b/src/clj/queue_api/routes/services.clj @@ -44,10 +44,14 @@        :return {:job_request {:job_id s/Any :agent_id String}}        :body-params [agent_id :- String]        :summary "Request a job to a given agent" -      (let [j (db/dequeue-job agent_id)] -        (if (nil? j) -          (bad-request {:message "Agent does not exist"}) -          (ok {:job_request {:job_id j :agent_id agent_id}})))) + +      (let [a (agent agent_id)] +        (if (nil? a) +          (not-found {:message "Agent does not exist"})) +        (let [j (db/dequeue-job agent_id)] +          (if (nil? j) +            (not-found {:message "There is no job available for given agent"}) +            (ok {:job_request {:job_id j :agent_id agent_id}})))))      (GET "/" []        :return {:completed  [String] diff --git a/test/clj/queue_api/test/db/core_test.clj b/test/clj/queue_api/test/db/core_test.clj index 371b903..117cc26 100644 --- a/test/clj/queue_api/test/db/core_test.clj +++ b/test/clj/queue_api/test/db/core_test.clj @@ -105,8 +105,7 @@      (d/transact! conn base-schema)      (f))) -(defn agent [id] -  (d/entity @conn [:agent/id id])) +  (defn job [id]    (d/entity @conn [:job/id id])) @@ -225,21 +224,28 @@          :processing (-> a :agent/job :job/status)          "96cf6f11-591d-4cde-9ab0-56e371acb6d2" (-> a :agent/job :job/id))))) -(deftest request-job-test +(deftest fittest-job-test    (testing "test query for skillset"      ;;primary-skillset urgent      (is (= (job "51ab0771-f1e4-4268-868f-9029a58f6612") -           (request-job "644be0ce-035d-48cb-867e-8e6de2714a8d"))) +           (fittest-job "644be0ce-035d-48cb-867e-8e6de2714a8d")))      ;;secondary-skillset urgent      (is (= (job "6e90db58-7a6d-46e2-a02a-e33dc82e6e33") -           (request-job "ff02347a-1b2d-440c-a2a1-7a593dba564e"))) +           (fittest-job "ff02347a-1b2d-440c-a2a1-7a593dba564e")))      (d/transact! conn complete-schema)      ;;primary-skillset not urgent      (is (= (job "96cf6f11-591d-4cde-9ab0-56e371acb6d2") -           (request-job "644be0ce-035d-48cb-867e-8e6de2714a8d"))) +           (fittest-job "644be0ce-035d-48cb-867e-8e6de2714a8d")))      ;;secondary-skillset not urgent      (is (= (job "f90e149e-fa51-4212-a6bf-8cf81c78d28c") -           (request-job "ff02347a-1b2d-440c-a2a1-7a593dba564e"))))) +           (fittest-job "ff02347a-1b2d-440c-a2a1-7a593dba564e"))))) + +(deftest agent-test +  (testing "Test agent" +    (are [left right] +      (= left right) +      (d/entity @conn [:agent/id "644be0ce-035d-48cb-867e-8e6de2714a8d"]) (agent "644be0ce-035d-48cb-867e-8e6de2714a8d") +      nil (agent "7b8e17fc-7953-44cf-9249-294c4eb73087"))))  (deftest dequeue-job-test    (testing "Test Dummy Derp dequeuing process" | 
