The starting point with the stack is the exemplary repository we provide on gitlab.com: https://gitlab.com/empowerlab/example. It illustrates all the features you may need to start a full-fledged project.
The example repository will deploy nine services:
- The product service and its database, serving a product model
- The customer service and its database, serving a customer model
- The invoicing servicing and its database, serving an invoice and invoice line models
- The login service and its database, serving account and role models. It also serves the login web page and is used as the Hydra consent application.
- The GraphQL API gateway, which aggregates the API of all services and exposes them to the Internet.
- The admin service, which will service the Admin GUI web application, connected to the gateway.
- The Hydra service, which will perform the authentification controls
- The NATS service, which will manage the asynchronous messaging in your backend
- The Jaeger service, which will implement the distributing tracing
The backend services
The invoice model had a customerUUID field, linked to the customer service. Each time you insert a new invoice, the invoicing service will check the customer service to ensure the customer exists.
Same for the invoice line model, it contains a productUUID field linked to the product service. But unlike customers, products are also stored in a table in the invoicing service. Each time you insert/update/delete a product, the product service will send an event to NATS. The invoicing service subscribes to these events and updates his product table accordingly. When an operation is performed on the productUUID field in an invoice line, the invoice service will first check his own product table and give his assent if the product exists. If not, it will try to contact the product service before rejecting the request.
Each time you perform a CRUD operation on a model, an event will be sent to NATS. This is done like this, the service first opens a transaction in his database and perform operations, also updating an event table in the database service. If an error occurs the transaction is rollbacked. If everything is ok, the transaction and all its events are committed in the database, and the events are sent to NATS to inform the other services.
When you deploy a service, the first time or when the schema changed, the database needs to be initialized with the
$serviceName migrate command. This is automatically done by the kubernetes deployment files or the docker-compose.yml file, through an init container.
This is an automigrate command, the database schema will be adjusted depending on your models definitions.
When deploying the Hydra service, it's database will also need to be initialized. Like the Golang service, this is done through an init container.
Moreover, we also need to create a client record for the Admin GUI, otherwise the request will be rejected. Again, this done through an init container.