aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 1686dd49b63c3a977ba980af8b1aedf0ba93c104 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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...