Introducing MMO

Monorepo Microservice Orchestrator

Peter Malina

CTO @ FlowUp

Outline

  • The Clean Architecture
  • Microservices
  • Monorepos
  • CI & CD
  • MMO
  • Project scaffolding
  • Generators

The Clean Architecture

Microservices (pros)

  • Logic decoupling
  • Smaller services
  • Simpler to understand

Microservices (cons)

  • Strict contracts between services
  • Dependencies
  • 200 deploy buttons
  • ... and databases
  • ... and caches

Deathstar architecture

Monorepos (pros)

  • Easier testing
  • No submodules needed
  • Build feedback for whole repo
  • Component sharing
  • Refactoring

Monorepos (cons)

  • Single CI pipeline
  • Hard to maintain for large teams
  • If master fails, everything fails
  • May need more tooling

CI & CD

MMO

  • Monorepo Microservice Orchestrator
  • Scaffolding
  • Code generation
  • Plugins
  • Still in Alpha :/

https://github.com/flowup/mmo

https://github.com/flowup/mmo-plugins

MMO

  • Automating repetitive tasks
  • Using gRPC as a communication protocol
go get -u github.com/flowup/mmo

Scaffolding  - new project

$ mmo init myapp
$ tree myapp/
myapp/
├── LICENSE
├── mmo.yaml
├── README.md
└── .drone.yml

Scaffolding  - new Service

$ mmo add service book
$ tree book/
book/
├── cmd
│   └── book
│       └── main.go
├── deployment
│   └── deployment.yaml
├── protobuf
│   └── proto.proto
├── service.go
└── service_test.go

Plugin Ecosystem

  • flowup/mmo-gen-go-grpc - generates grpc from proto files
  • flowup/mmo-gen-proto-interface - generates interface implementations from grpc
  • flowup/mmo-gen-grpc-gateway - generates HTTP gateway from grpc
  • flowup/mmo-gen-swagger - generates swagger from proto files
  • flowup/mmo-gen-angular-client - generates angular client from proto files

mmo.yaml with plugins

name: myapp
plugins:
  - flowup/mmo-gen-swagger:1.0.1
prefix: github.com/flowup/testbench/myapp
services:
  book:
    description: ""
    plugins:
      - flowup/mmo-gen-go-grpc:1.0.2
      - flowup/mmo-gen-grpc-gateway:1.0.1

Proto for every service

syntax = "proto3";

package book;

import "google/protobuf/empty.proto";


service BookService {
    rpc GetVersion (google.protobuf.Empty) returns (Version) {}

    rpc CreateBook(Book) returns (Book) {}

    rpc GetAllBooks(google.protobuf.Empty) returns (Books) {}
}

message Version {
    string name = 1;
}

message Book {
    string name = 1;
    string description = 2;
    string author = 3;
}

message Books {
    repeated Book books = 1;
}

Proto for every service

// Service represents an implementation of the Book service interface
type Service struct {
}

// NewService creates a new service object
func NewService() *Service {
    return &Service{}
}

// CreateBook creates a new book
func (s *Service) CreateBook(ctx context.Context, in *Book) (*Book, error) {
	return in, nil
}

HTTP Gateway

syntax = "proto3";

package book;

import "google/protobuf/empty.proto";


service BookService {
    rpc CreateBook(Book) returns (Book) {
+       option (google.api.http) = {
+           post: "/v1/example/echo"
+           body: "*"
+       };
    }
}

message Book {
    string name = 1;
    string description = 2;
    string author = 3;
}

gRPC SDKs

import "github.com/flowup/testbench/myapp/book"

type OtherService struct {
    books *book.Service
}

func (s *OtherService) DoSomething(ctx context.Context, in *Model) (*Model, error) {
    book, err := s.books.CreateBook(ctx, book.Book{.....})
    
    ...
}

Thank you!

Questions?

Made with Slides.com