Skip to main content

Language-agnostic microservices boilerplate as a code

Project description

Language-agnostic microservices boilerplate as a code. You define service configuration and implementation, Harness takes care for it’s life cycle:

  • load configuration: read, validate

  • initialize environment: database and other outgoing connections

  • start servers/subscribers

  • graceful shutdown

Configuration

Harness uses Protocol Buffers as a configuration definition language (svc.proto file):

syntax = "proto3";

package cafe;

import "harness/options.proto";
import "harness/postgres.proto";
import "harness/grpc.proto";

message Configuration {
  bool debug = 1;
  harness.postgres.DSN db = 2 [(harness.input) = "python/asyncpg.v1:Connection"];
  harness.grpc.Channel taskqueue = 3 [(harness.input) = "python/grpclib.v1:Channel"];
  harness.grpc.Endpoint listen = 4 [(harness.output) = "python/grpclib.v1:Server"];
}

As you can see from this configuration, our service has:

  • debug mode

  • database connection

  • gRPC channel to the taskqueue service

  • gRPC server to serve incoming requests

We can provide values for this configuration using YAML file (config.yaml file):

db:
  value: postgres://postgres:postgres@db.cafe.svc.cluster.local:5432/coffee
taskqueue:
  host: taskqueue.platform.svc.cluster.local
  port: 50051
listen:
  host: 0.0.0.0
  port: 50051

Service Definition

Harness must be able to run your service. In order to do this you must provide a main function, it’s signature looks like this:

from svc_wires import WiresIn, WiresOut

async def main(wires_in: WiresIn) -> WiresOut:
    ...
    return WiresOut(...)

Where WiresIn and WiresOut are generated by the Harness from your service configuration:

@dataclass
class WiresIn:
    db: harness.resources.asyncpg.v1.Connection
    taskqueue: harness.resources.grpclib.v1.Channel

@dataclass
class WiresOut:
    listen: harness.resources.grpclib.v1.Server

When Harness runs your service, you receive already initialized environment in a WiresIn structure. All you have to do is to setup your request handler and return it with a WiresOut structure (svc.py file):

from harness.resources.grpclib.v1 import Server

from svc_grpc import CoffeeMachineBase

class CoffeeMachine(CoffeeMachineBase):
    ...

async def main(wires_in: WiresIn) -> WiresOut:
    print('Connection:', wires_in.db.connection)
    print('Channel:', wires_in.taskqueue.channel)
    server_resource = Server([
        CoffeeMachine(
            db=wires_in.db.connection,
            taskqueue=wires_in.taskqueue.channel,
        ),
    ])
    return WiresOut(listen=server_resource)

Files Generation

We use protoc compiler to generate boilerplate from your configuration:

$ protoc -I $HARNESS_PROTO --python_out=. --python_grpc_out=. --python_harness_out=. --mypy_out=. svc.proto

Where $HARNESS_PROTO is where to find Harness proto-files.

Runtime

Use harness command to run your service:

$ harness svc:main config.yaml

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

harness-0.1.0rc1.tar.gz (9.0 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page