Project for learning pure functional programming in Scala with the Typelevel ecosystem.
- Run postgres (localhost, db: postgres, user: postgres, no password) - to change the config,
see
application.conf
in this project.
You can use docker for this:
$ docker run -p 5432:5432 postgres:10.5-alpine
Or the local postgres server. If you installed it with brew
, do createuser postgres
and everything else should already be there (assuming the brew service is running).
- Run the application, e.g. by going into
sbt
and typingrun
.
To check that your DB config is right, look for errors in the log (most likely errors from Flyway).
If there are none, you should be good. You can also query the GET /bricks
endpoint.
Brick Store offers a few HTTP resources with some endpoints:
Bricks:
GET /bricks
- lists the existing bricks.POST /bricks/import
- takes a stream oforg.typelevel.brickstore.dto.BrickToCreate
objects (seeinput-data.jsonl
file for an example of the format), returns anorg.typelevel.brickstore.app.data.ImportResult
for each line (for successes - the brick's ID, for failures - acats.data.NonEmptyList
of errors).
Cart:
POST /cart/add
- takes aorg.typelevel.brickstore.dto.CartAddRequest
and adds a brick to the cart. If any errors occur, a NEL of values of typeorg.typelevel.brickstore.dto.CartAddError
will be returned.GET /cart
- gets the current user's cart (the user is hardcoded to id=1, so everyone is that user ;). The result is a non-empty list oforg.typelevel.brickstore.cart.dto.CartBrick
, or 404 if there isn't anything in the cart.
Orders:
POST /order
- creates an order, if the user has a non-empty cart. Fails otherwise.GET /order/stream
- streams existing and incoming order summaries (id, user id, total price). More below.
If you open the GET /order/stream
endpoint and let it run, you'll see a new item for every order
created after you call it. For best results, you can use the httpie
CLI tool to convert the streamed lines of JSON
to a pretty format:
$ http :8080/order/stream --stream
To see how the application works in full, you can run the following flow:
Samples are using httpie.
$ http post :8080/bricks/import < src/main/resources/input-data.jsonl
You should see something like this:
HTTP/1.1 202 Accepted
Content-Type: application/json
Date: Sun, 09 Sep 2018 21:44:37 GMT
Transfer-Encoding: chunked
{"result":1}
{"result":2}
{"result":3}
{"result":4}
{"result":5}
{"lineNumber":6,"error":["NameTooLong"]}
{"result":6}
...
{"result":40}
{"result":41}
Which means 41 results were added, but the one in line 6 wasn't (rightfully, because its name is longer than
the maximum allowed length, see org.typelevel.brickstore.bricks.BricksServiceImpl#validate
).
Having added bricks, we can add them to the cart so that we can order them.
$ http post :8080/cart/add brickId=3 quantity=2
$ http post :8080/cart/add brickId=38 quantity=800
If all goes well, these should both return 200 OK
.
Try adding a brick that doesn't exist or passing a non-positive quantity.
To see the existing orders and subscribe to future ones (until you drop the connection):
$ http :8080/order/stream --stream
It'll timeout in 30 seconds, so be quick (or call it again when it does)!
Note: You can have as many clients connecting to this endpoint as you wish, and they should all see consistent output.
Assuming your cart isn't empty, you should be able to create an order:
$ http post :8080/order
HTTP/1.1 201 Created
Content-Length: 24
Content-Type: text/plain; charset=UTF-8
Date: Sun, 09 Sep 2018 21:52:56 GMT
Created order with id: 1
And, if the order stream is opened, you'll see an output similar to this:
$ http :8080/order/stream --stream
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 09 Sep 2018 21:52:55 GMT
Transfer-Encoding: chunked
{
"id": 1,
"total": 705260,
"userId": 1
}
If you call this endpoint again, you should see the order as well.