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...
|