Setup

Introduction

Before starting to think in multiple microservices, distributed environments and so on, it’s easier and better to start by knowing what components are needed to build a microservice individually. For the sake of simplicity, each microservice can be seen as one small monolithic system that provides as limited or specialized functionality. Then, each microservice will probably need to interact with a storage system, contain some kind of business logic and expose that functionality over an external API, to be used by external clients and another microservices.

Dependencies

To be able to provide all that environment functionalities, minos relies on external dedicated libraries. For example, to read or store data in postgres database aiopg is used, to publish or subscribe to kafka topics aiokafka is used and to expose a REST interface aiohttp is used. In any case, the minos philosophy is that the surrounding technologies must not be frozen to these and each of project must have its own ones so the list of supported databases and brokers will be increased in future minos releases.

Another important thing to know is that minos relies on latest Python functionalities so the minimal required version is 3.9 or greater. One of the reasons are the use of async code together with type hinted code.

Then, for this quickstart the following dependencies are needed:

  • Python >= 3.9

  • PostgreSQL >= 9.3

  • Kafka >= 2.8

In order to ease the quickstart process, here is a simple docker-compose.yml that provides the environment dependencies:

# docker-compose.yml

version: "3.9"
services:
  postgres:
    image: postgres:latest
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: minos
      POSTGRES_PASSWORD: min0s
      POSTGRES_DB: exam_db
  zookeeper:
    image: wurstmeister/zookeeper:latest
    ports:
      - "2181:2181"
  kafka:
    image: wurstmeister/kafka:latest
    ports:
      - "9092:9092"
    depends_on:
      - zookeeper
    environment:
      KAFKA_ADVERTISED_HOST_NAME: localhost
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_DELETE_TOPIC_ENABLE: "true"

Modularity

Another important detail about how the minos framework is how it is packaged. Instead of providing all the framework as a single and big component, it relies on Python namespaces to provide a modular but organized way to install only the exact part of functionality that will be used. The main packages are the following ones:

Package Managers

Before starting a Python project, a package manager is needed to install and manage external dependencies. As it’s expected, minos is compatible with any of them, but the recommended one is Poetry as it provides simple but powerful functionalities.

Poetry

To install poetry, it’s recommended to follow its own guide, that can be found here. After installing poetry, everything is ready to build the first microservice!

The first step is to create the project (the project name can be whatever you want, but a minos microservice convention is to name it as src):

poetry new exam-microservice-example --name src

The project structure will be similar to:

exam-microservice-example
├── README.rst
├── pyproject.toml
├── src
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_src.py

2 directories, 5 files

To install the minos dependencies, simply exec the following command on the project’s root directory:

poetry add \
  minos-microservice-common \
  minos-microservice-networks \
  minos-microservice-saga \
  minos-microservice-cqrs

PipEnv

[TODO: Include pipenv guide.]

Pip

[TODO: Include pip guide.]

After that, every minos dependencies are ready to use. Let’s move to the configuration step!

Configuration

The configuration step is the last part of the microservice’s setup, which is the process of defining the microservice’s name, the classes to be responsible for specific framework’s tasks and the location of credentials to interact with external resources like databases and brokers.

As many parts of the configuration requires digging deeper into each of the components of the framework, here is provided a superficial description of the main ones.

  • service.name: The name of the microservice.

  • service.aggregate: The qualified Python path to the root aggregate.

  • service.injections: A mapping of instances to be injected around the framework to provide framework’s functionality.

  • service.services: A set of background services whose main purpose that provide some framework’s functionality.

  • rest: Configuration of the rest’s interface.

  • broker: Configuration of the broker’s interface.

  • repository: Configuration of the repository database.

  • snapshot: Configuration of the snapshot database.

  • events: Configuration of the events service.

  • queries: Configuration of the queries service.

  • commands: Configuration of the commands service.

  • saga: Configuration of the saga manager.

  • discovery: Configuration of the discovery service.

Here is a template for a config.yml file, which will be used by the exam microservice.

# config.yml

service:
  name: exam
  aggregate: src.aggregates.Exam
  injections:
    postgresql_pool: minos.common.PostgreSqlPool
    command_broker: minos.networks.CommandBroker
    command_reply_broker: minos.networks.CommandReplyBroker
    event_broker: minos.networks.EventBroker
    consumer: minos.networks.Consumer
    dynamic_handler_pool: minos.networks.DynamicHandlerPool
    repository: minos.common.PostgreSqlRepository
    saga_manager: minos.saga.SagaManager
    snapshot: minos.common.PostgreSqlSnapshot
    # discovery: minos.networks.DiscoveryConnector
    query_repository: src.queries.ExamQueryRepository
  services:
    - minos.networks.ConsumerService
    - minos.networks.CommandHandlerService
    - minos.networks.CommandReplyHandlerService
    - minos.networks.EventHandlerService
    - minos.networks.RestService
    - minos.networks.SnapshotService
    - minos.networks.ProducerService
rest:
  host: 0.0.0.0
  port: 8082
broker:
  host: localhost
  port: 9092
  queue:
    database: exam_db
    user: minos
    password: min0s
    host: localhost
    port: 5432
    records: 1000
    retry: 2
repository:
  database: exam_db
  user: minos
  password: min0s
  host: localhost
  port: 5432
snapshot:
  database: exam_db
  user: minos
  password: min0s
  host: localhost
  port: 5432
queries:
  service: src.queries.ExamQueryService
commands:
  service: src.commands.ExamCommandService
saga:
  storage:
    path: ./exam.lmdb
# TODO: include discovery service into the `docker-compose.yml`
# discovery:
#   client: minos.networks.MinosDiscoveryClient
#   host: localhost
#   port: 5567

API Gateway and Discovery

[TODO: Describe integration with discovery.]