Creating Services
To build a new service, some rules and standards need to be followed according to its category.
However, for all categories, a service must have at least the following files in its directory:
service
\_go.mod
\_go.sum
\_service.toml
\_main.go
The go.mod and go.sum files are from the Go language itself, for controlling the module name and its dependencies.
The service.toml file contains information pertinent to the service, such as name, version, programming language used by it, environment variables, etc. This file is required for the correct initialization of a service, as well as undergoing validations during the execution of the pipeline of CI/CD in a merge request.
The main.go file must contain all the code responsible for initializing the service, whether using the correct API according to its category, as well as initializing particular external components for the functioning of the service itself, such as initializing an external resource, for example.
A service can also have other source files. However, these vary according to its category.
Additionally, for Somatech services, every service also needs to have the following files:
A README.md file is a text file, with syntax Markdown describing briefly the service itself, with relevant information for knowledge, as well as being possible to detail more about it, inserting badges, to display relevant information about it, such as code coverage in unit tests, version, among others.
A Dockerfile file is the necessary file for building the docker image of the service for its deploy (or eventual local test, if necessary).
So with the following layout:
service
\_README.md
\_go.mod
\_go.sum
\_Dockerfile
\_service.toml
\_main.go
IMPORTANT: It's possible to create this initial structure of a service through the tool soma-cli. Consult it for more details.
Optional Layouts
Configurations
For the case of a service having configurations, that is, a structure of type Settings declared in a .proto file, it must have all the code related to the treatment of this information gathered in a specific file, named settings.go. In this way the basic structure would be the following:
service
\_README.md
\_go.mod
\_go.sum
\_Dockerfile
\_service.toml
\_main.go
\_settings.go
Lifecycle
Every initialization of external components, necessary for the functioning of the service, must be done using the Lifecycle interface of Mikros. This allows members of the service's main structure to be initialized correctly. As well as releasing some necessary resource.
The specification of this API can be consulted in file.
So, a service that has this need will have the following structure of files, with the lifecycle.go file being used specifically for service initializations and resource release:
service
\_README.md
\_go.mod
\_go.sum
\_Dockerfile
\_service.toml
\_main.go
\_lifecycle.go
gRPC or HTTP Services
A service from the gRPC
or HTTP
category part from the premise that a protobuf file also exists for it, with APIs (RPCs) and entity definitions. This implies that the service needs to "implement" support for this defined API.
So, all the implementation related to the API generated by protobuf must be gathered in a single source file, named server.go. And the structure of a service from this category would look like this:
service
\_README.md
\_go.mod
\_go.sum
\_Dockerfile
\_service.toml
\_main.go
\_server.go
subscriber or database-subscriber Services
Services from the subscriber
or database-subscriber
category must have a source file with the name subscriber.go where the declaration of its principal struct must be done, as well as any common code between the events handled.
Also, the service must also have a specific source file for each of the listened events. The name of these files must follow the pattern:
- To have the same name as the event (only its suffix), in lowercase and in
snake_case
.
Each file must handle specifically an event, with at least one function that returns an handler of type types/event.EventHandler. It must also contain methods of the principal struct that are only used by its handler.
The creation of an handler must have at least the following characteristics:
A specific function to "create" and return the handler, to be called in the SDK initialization API. The name of this function must follow the rule:
- To start with the prefix
New
, followed by the event name (only its suffix), inCamelCase
, with theHandler
prefix.
- To start with the prefix
Example for the case of an event named FILE_CREATED
:
package main
import (
"context"
"github.com/somatech1/mikros/types/event"
)
func NewFileCreatedHandler(service *subscriber) event.EventHandler {
return func(ctx context.Context, e *event.Event) error {
// Handles event
if err := doSomething(); err != nil {
return event.Skip()
}
return event.Ack()
}
}
The structure of code for a repository for this category of service must contain at least the following (using the FILE_CREATED
event mentioned previously):
service
\_README.md
\_go.mod
\_go.sum
\_Dockerfile
\_service.toml
\_main.go
\_subscriber.go
\_file_created.go
consumer Services
Just like a subscriber, a consumer service type also does not have any formal specification for its construction other than the need for the code to implement the specific interface for its category.
The structure of code for a repository for this category of service must contain at least the following:
service
\_consumer.go
The consumer.go file must contain the implementation of the ConsumptionRegister interface, as well as the methods that will handle the received records.