Architecture
The ShopiTerm software system consist of multiple microservices.
This page lists them and gives some detail on their implementation.
For running and configuring them, see the installation and configuration pages.
External Dependencies
We use two main external dependencies in this software system: NATS and PostgreSQL.
NATS
NATS is a messaging system used by ShopiTerm for event-driven interactions.
It offers a simple-to-use interface to subscribe to and publish messages on so-called subjects.
This allows us to notify other services when something needs to be started or has finished.
PostgreSQL
PostgreSQL is the database management system used by ShopiTerm.
Each service that needs persistence in the form of a database uses it.
We use the diesel library for interfacing with PostgreSQL.
This gives us strong compile-time guarantees about the correctness of our queries.
All services use either an asynchronous variant of diesel or a connection pool, ensuring fast handling of concurrent requests to our system.
Where necessary (e.g. when updating stock information) we use transactions to ensure that operations consisting of multiple database operations result in a consistent state.
Catalogue
The catalogue service keeps track of the items available within the store. It does not track actual stock information but rather the metadata about a given item. An item has the attributes one would expect from a shop such as name, description and price. Additionally, the catalogue offers the ability to add arbitrary tags to an item.
Warehouse
The warehouse component manages the actual stock of items for ShopiTerm.
There can be any number of warehouses, each with their own stock of items.
Warehouses can be created and deleted and items can be added or removed from them.
In order to support the ordering process, items can be reserved at a warehouse before an order is finalized.
This prevents a single item instance to be sold multiple times.
Orders
The order service handles checkout and keeps the canonical record of placed orders.
It accepts a CreateOrder payload, validates the shipping address and ordered items, prices the items, reserves the required stock in the warehouse service and stores the order together with its items and shipping address in PostgreSQL.
Order creation is transactional: if persisting the order fails, any reservations are rolled back. Once the order has been written successfully, the service publishes the placed order on NATS so that the payment service can create a payment flow for it. The service also exposes endpoints to fetch an order, its items and payment information, and to mark an order as shipped. It also publishes an event to NATS when the order is marked as shipped for the notifiaction service to notify the client that the command is shipped.
Notificator
The notification service sends email confirmations to customers at key stages of the order lifecycle. It listens to NATS events published by the payment and orders services, fetches the corresponding order details from the order service, and sends customer emails via SMTP. The service sends three types of notifications: order confirmation emails when a payment is created, payment confirmation emails when payment is marked as paid, and shipping confirmation emails when an order is marked as shipped.
Payment
The payment service listens for newly created orders via NATS and creates a Taler payment for them.
Taler returns a payment URI that which is announces to NATS and can then be displayed to customers for payment with their Taler wallet.
All currently open payments are tracked using a NATS key-value store.
Once a payment is marked as paid by Taler, the corresponding ShopiTerm order is announced to be paid via NATS.
Recommendations
TODO
TUI Client
The user interface to ShopiTerm is built using ratatui.
It is exported as a library to be used the the SSH server.
The interface consist of multiple views, one for each task such as catalogue browsing or doing the payment.
A loop-based renderer then uses these views to assemble the user interface.
Keyboard input is handled based on the currently active view.
TODO: extend?
SSH Server
TODO
Common Library
The shopiterm_common is a Rust library helping us in building the whole project.
It is mainly a collection of data structures that are exchanged between services.
These structures are set up for serialization and deserialization, ensuring easy re-use between services.
API Gateway
TODO
API Client
The API client is not an actual service but rather a library used by the services to exchange information. It provides the ability to make authenticated requests to the gateway and fetch all the different data structures used by the different services.