description | none |
owner | jane.lx.gay@gmail.com |
last change | Sat, 9 Mar 2019 02:29:51 +0000 (8 18:29 -0800) |
URL | git://repo.or.cz/sig-chat-ex-feb-2019.git |
https://repo.or.cz/sig-chat-ex-feb-2019.git | |
push URL | ssh://repo.or.cz/sig-chat-ex-feb-2019.git |
https://repo.or.cz/sig-chat-ex-feb-2019.git (learn more) | |
bundle info | sig-chat-ex-feb-2019.git downloadable bundles |
content tags |
The primary focus of this document is on explication of existing code and suggestions for improving robustness and clarity rather than to speculate about a feature-rich chat experience.
Running gradle build
will bundle an executable uber jar in build/libs.
To run the integration test: gradle integrationTest
Usage:
$ java -jar build/libs/signal-rest-api-exercise-v1.2-all.jar -h
Usage: simple-chat-server [-hV] [-a=ADDRESS] [-f=DB_FILE] -p=PORT
Starts the chat server.
-a, --address=ADDRESS server address (default: localhost)
-f, --dbFile=DB_FILE path to a file where the chat db is stored (default:
chats_testing.db)
-h, --help Show this help message and exit.
-p, --port=PORT server port
-V, --version Print version information and exit.
Alternatively, gradle run
will execute the main method as well.
listen only on localhost:
$ java -jar build/libs/signal-rest-api-exercise-v1.2-all.jar -a localhost -p 6000
... INFO : e.n.c.s.h.d.Dispatcher loaded 2 route handlers
... INFO : e.n.c.s.Server loaded 200 users from contacts
... INFO : e.n.c.s.a.Listener Listening on /127.0.0.1:6000
listen everywhere and specify a db (requires privilege to bind port 80):
$ java -jar build/libs/signal-rest-api-exercise-v1.2-all.jar -a :: -p 80 --dbFile /var/run/simple-chat/chats.db
... INFO : e.n.c.s.h.d.Dispatcher loaded 2 route handlers
... INFO : e.n.c.s.Server loaded 200 users from contacts
... INFO : e.n.c.s.a.Listener Listening on /0:0:0:0:0:0:0:0:80
See schemas/ for JSON schemas of chat and message.
POST /chats HTTP/1.1
Host: localhost:3335
User-Agent: curl/7.64.0
Accept: */*
Content-Length: 54
Content-Type: application/json
{
"id": 1,
"participantIds": [51201, 28463]
}
---
HTTP/1.1 200 OK
GET /chats?userId=28463 HTTP/1.1
Host: localhost:3335
User-Agent: curl/7.64.0
Accept: */*
---
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 41
Content-Encoding: identity
[{"id":1,"participantIds":[51201,28463]}]
POST /echo HTTP/1.1
Host: localhost:3335
User-Agent: curl/7.64.0
Accept: */*
Content-Length: 172
Content-Type: application/json
{
"id": "6cfd98ae-ab8a-4722-a385-dad87e5f0207",
"timestamp": 101,
"message": "Hi, how's it going?",
"sourceUserId": 28463,
"destinationUserId": 51201
}
---
HTTP/1.1 200 OK
GET /chats/1/messages HTTP/1.1
Host: localhost:3335
User-Agent: curl/7.64.0
Accept: */*
---
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 270
Content-Encoding: identity
[{"id":"0d1e05a1-0b57-44a7-967a-1d7415cbedec","timestamp":100,"message":"Hello!","sourceUserId":51201,"destinationUserId":28463},{"id":"6cfd98ae-ab8a-4722-a385-dad87e5f0207","timestamp":101,"message":"Hi, how's it going?","sourceUserId":28463,"destinationUserId":51201}]
Consider using an injection framework to achieve decoupling between server, controller, instrumentation, and data components. At present, the listener and dispatcher are decoupled from the application logic by non standardized use of reflection to search for annotations that bind routing and priority data to an interface type known to the dispatcher.
Consider using a lifecycle manager such as Spring to ensure that startup and shutdown occurs in a graceful and orderly manner.
Add timing and count metrics for use with profiling and assessing performance.
Add a coverage tool and increase unit testing such that line coverage is 100% and branch coverage is > 90%.
The protocol and schemas should be versioned.
User chats are presently returned in an arbitrary order. This is okay in the likely case that each front end instance is expected to maintain its own ordering. It may be nice to allow chats to be ordered by creation time, which would require an update to the schema.
An endpoint should be added to allow users to request to be contacts.
To achieve horizontal scaling with a DB such as Postgres, data can be partitioned. Chat data lends itself relatively well to partitioning.
With a storage system designed for horizontal scaling such as DynamoDB, it is a requirement to be able to perform consistent reads (which DynamoDB does provide).
Individual messages are immutable and may be cached indefinitely. The server should return cache control headers and allow a 304 response for GET /chat/{chatId}/messages. (Even with theoretically infinitely cacheable data, it is best to set a cache timeout of at most 30 minutes.) It would be beneficial to paginate message responses and allow incremental message retrieval.
It is unclear whether chats are indefinitely cacheable as it is possible to relax the restriction on participantIds to allow more than two participants.
Users should be authenticated and only authorized to access chats in which they are participants and messages of those chats.
The server should better support HTTP/1.1 including common Content-Encodings such as gzip, Transfer-encoding chunked.
Support HTTP 2.
Profile against expected and abnormal request loads and tune accordingly.
Since routes are static at runtime, an in memory cache of routes matching paths could be useful depending on profiling about time used matching paths.
5 years ago | master | logtree |