# queue-api A simple job queue api ## Usage To run just type `lein run` then access [localhost:3000/swagger-ui](http://localhost:3000/swagger-ui/index.html). ## Stack I chose [luminus](http://www.luminusweb.net/) for my stack as it made the initial setup way easier since it provide a wide range option of configuration for a lot of technologies. To bootstrap the project I used `lein new luminus queue-api +swagger +service +kibit` plus datascrypt, which by default doesn't come with Luminus. ### +Swagger When possible I always add it to a project for it make easier to visualize and test endpoints. ### +Service To remove all front end stuff since I didn't need it. ### +Kibit I added because 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. 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 would search for a Datomic seeing that query system of both are compatible. ## Solution ### Data structure Project has two models: * Agent * `:agent/id` unique identification of an agent * `:agent/name` agent name * `:agent/primary-skillset`: list of primary skillsets of an agent * `:agent/secondary-skillset` list of secondary skillsets of an agent * `:agent/job` reference to job that the agent is processing * Job * `:job/id` unique identification of a job * `:job/status` current status of the job it can be: * `:unassigned` it is waiting to be assigned * `:processing` it is being precessed by an agent * `:completed` it has been done with. * `:job/agent` reference a job that is processing this job or had processed it. it is nil when `:unassigned` * `:job/type` type of the job that it can perform Those models wrap up in schema: ```clojure {:agent/id {:db/unique :db.unique/identity} :agent/primary-skillset {:db/cardinality :db.cardinality/many} :agent/secondary-skillset {:db/cardinality :db.cardinality/many} :agent/job {:db.valueType :db.type/ref} :job/id {:db/unique :db.unique/identity} :job/agent {:db.valueType :db.type/ref}} ``` ### 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 and considering the exercise requirements we gonna need 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 would 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. * Endpoint to add a job is `:put` at `/job` * Endpoint to request a job is `:post` at `/job` * Endpoint to get current queue state is `:get` at `/job` For model detail access swagger-ui. ### db/core.clj To be continued...