90 lines
3.8 KiB
Markdown
90 lines
3.8 KiB
Markdown
# `mcq-test-results-js`
|
|
|
|
I had originally thought to write this service using Rust and Postgres as the data store,
|
|
but after some consideration I decided to use JavaScript (not TypeScript) to iterate quickly,
|
|
spend less time fighting with the borrow checker or tweaking `moduleResolution` in a `tsconfig.json`
|
|
and focus on aspects I considered to be important:
|
|
|
|
- clean modular code
|
|
- dependency injection
|
|
- easily extensible integration tests
|
|
- See `src/api.test.js`
|
|
|
|
Plus, it's just a prototype right? :P
|
|
|
|
I chose SQLite to simplify the deployment and running of the service, as it can be tricky ensuring that a separate DB service
|
|
is migrated and running before the service starts trying to connect.
|
|
Additionally it allows the integration tests to use the database layer without having to run multiple services inside a compose network.
|
|
Finally I wanted to use SQL features like transactions and check constraints to meet requirements of atomicity due to unpaid AWS bills.
|
|
|
|
Regarding the XML parsing, I chose to use a library with a simple API and be quite generous in what I accepted in requests instead of using a schema and instead let the application and database layers enforce missing or invalid fields.
|
|
|
|
## Using the Service
|
|
|
|
### Starting the Service
|
|
|
|
```
|
|
docker compose up
|
|
```
|
|
|
|
`localhost:4567` is forwarded to the listening service inside docker.
|
|
|
|
### Tests
|
|
|
|
Running tests requires `NPM` to be installed, if you have it you can simply run
|
|
|
|
```
|
|
npm i
|
|
npm t
|
|
```
|
|
|
|
This will install the dependencies and run the tests.
|
|
|
|
Note that the database on your host machine will not be shared with the instance running inside docker.
|
|
|
|
### Deployment
|
|
|
|
You can find the built service image with
|
|
|
|
```
|
|
docker images | grep mcq-test-results
|
|
```
|
|
|
|
This image can then be tagged and pushed to the appropriate container registry to be run in ECS, or EKS, or whatever container service it is we use here at Markr...
|
|
|
|
**IMPORTANT**
|
|
|
|
In order for the service's data to be persisted the directory `/opt/mcq-test-results/db` **must** be mounted as a high write speed persistent block store.
|
|
|
|
## Next Steps
|
|
|
|
### Migrate to PostgreSQL
|
|
Postgres has excellent built in aggregate functions such as `percentile_cont` that will likely outperform the application level calculations being done by the `simple-statistics` library used here.
|
|
|
|
### Logging
|
|
The application has very little in the way of logging. Suggest a JSON logging library such as [Bunyan](https://github.com/trentm/node-bunyan) to improve debugging and traceability of the application.
|
|
|
|
## Assumptions
|
|
|
|
### Student Uniqueness
|
|
The sample data didn't seem to make a great deal of sense; perhaps our friend at the school board butchered it redacting student PII.
|
|
|
|
It contained entries where for example:
|
|
- the same `student-number` was supplied by students with different names
|
|
- John John & Jean Stephanie both supplied 2398
|
|
- students with the same name supplied different `student-numbers`
|
|
- there are 3 Penelope Graces (!) all supplying different student numbers
|
|
|
|
Here I assumed that the students and teacher are smart enough to know their names and student numbers and consider them to be unique individuals
|
|
based on the combination of those attributes.
|
|
...then again maybe they're just messing with the teacher...
|
|
|
|
### On Selecting the highest score
|
|
When inserting entries into the database, a row is only inserted or updated if the `marksObtained` are greater than the value
|
|
of an existing row.
|
|
I had originally thought to standardise the `marksAvailable` based on the highest value seen in any entry for a given `testId`
|
|
but I didn't know definitively that a test should all have the same `marksAvailable`. The test data didn't seem to indicate that the machines could submit any entries to the contrary either.
|
|
|
|
### Size Limits
|
|
20MB is assumed to be the maximum test submission size
|