A small project to demonstrate how a back-end service for managing bike stations could be implemented using Rust and CockroachDB.
The most important crates this projects uses are:
- Axum - Creates the web server and routes the endpoint handlers.
- SQLx - Connects with the CockroachDB, providing compile-time query validation.
- Tokio - Provides the
async
runtime. - Reqwest - HTTP client used to retrieve data to be ingested from the GBFS JSON files.
SeaORM was considered to manage the database, but I dropped it because found datatype issues with CockroachDB. Diesel was also considered but had a steeper learning curve.
src/
- Contains all Rust code.main.rs
- Runs the async Tokio main and registers Axum endpoints.handler/
stations.rs
- Defines the functions attached to the endpoints, plus some helper functions. These write to the DB directly.
model/
gbfs.rs
- Defines the struct representing the GBFS JSON file used as request body in/ingest
stations.rs
- Defines structs mapping the database tables and JSON objects coming from GBFS URLs
sql/
- Contains the database configurationsetup_db.sql
- Creates the database and tables. Useful to restore the DB.
Clone this repo, and run
git clone https://github.com/strosek/bike-stations.git
cd bike-stations
docker compose up --build
Then you can call the service at port 3000
:
curl -v -X POST localhost:3000/ingest -H "Content-Type: application/json" --data {<GBFS requset body here>}
curl -v -X GET localhost:3000/stations
To reset the database stop the containers and run them again:
docker compose down
docker compose up
This project was created from scratch with a 4-hours coding time limit without much familiarity with the crates used. This left a lot to be done to bring the app to production quality. Among the most important improvements to be done are:
- Improve error management, replace unwraps with the right pattern matching and error propagation.
- HTTP error codes should be accurate and error messages expressive.
- Better organization of database access objects, including pools and configuration.
- Database limits should be in place with paging for GET, and setting a limit for POST on how many rows can be inserted at once.
- Proper logging and monitoring should be added.
- Tests, and doctests.
- Add documentation.
- Code should be organized in multiple workspaces to improve compilation time.
- Implement Deserialization to handle multiple field data types more cleanly (differences in DB vs JSONs)
- Add logic to prevent issues with duplicates during ingestion