All Projects → DoNewsCode → Core

DoNewsCode / Core

Licence: mit
Package core is a service container that elegantly bootstrap and coordinate twelve-factor apps in Go.

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to Core

Haystack
Top level repository for Haystack, containing documentation and deployment scripts
Stars: ✭ 261 (+667.65%)
Mutual labels:  metrics, distributed-tracing, opentracing
Hyperf
🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
Stars: ✭ 4,206 (+12270.59%)
Mutual labels:  framework, opentracing, dependency-injection
Airframe
Essential Building Blocks for Scala
Stars: ✭ 442 (+1200%)
Mutual labels:  metrics, dependency-injection
Zipkin Go Opentracing
OpenTracing Bridge for Zipkin Go
Stars: ✭ 472 (+1288.24%)
Mutual labels:  distributed-tracing, opentracing
Inspectit
inspectIT is the leading Open Source APM (Application Performance Management) tool for analyzing your Java (EE) applications.
Stars: ✭ 513 (+1408.82%)
Mutual labels:  metrics, opentracing
Opentracing Php
OpenTracing API for PHP
Stars: ✭ 407 (+1097.06%)
Mutual labels:  distributed-tracing, opentracing
Izumi
Productivity-oriented collection of lightweight fancy stuff for Scala toolchain
Stars: ✭ 423 (+1144.12%)
Mutual labels:  framework, dependency-injection
Mortar
Mortar is a GO framework/library for building gRPC (and REST) web services.
Stars: ✭ 492 (+1347.06%)
Mutual labels:  metrics, dependency-injection
Loopback Next
LoopBack makes it easy to build modern API applications that require complex integrations.
Stars: ✭ 3,972 (+11582.35%)
Mutual labels:  framework, dependency-injection
Jaeger Ui
Web UI for Jaeger
Stars: ✭ 639 (+1779.41%)
Mutual labels:  distributed-tracing, opentracing
Frint
Modular JavaScript framework for building scalable and reactive applications
Stars: ✭ 608 (+1688.24%)
Mutual labels:  framework, dependency-injection
Opencensus Java
A stats collection and distributed tracing framework
Stars: ✭ 640 (+1782.35%)
Mutual labels:  metrics, distributed-tracing
Di
Dependency injection container in go (golang)
Stars: ✭ 390 (+1047.06%)
Mutual labels:  framework, dependency-injection
Transmittable Thread Local
📌 TransmittableThreadLocal (TTL), the missing Java™ std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.
Stars: ✭ 4,678 (+13658.82%)
Mutual labels:  framework, distributed-tracing
Gongular
A different approach to Go web frameworks
Stars: ✭ 438 (+1188.24%)
Mutual labels:  framework, dependency-injection
Jaeger Client Node
Jaeger Bindings for OpenTracing API for Node.js
Stars: ✭ 485 (+1326.47%)
Mutual labels:  distributed-tracing, opentracing
Opentelemetry Js
OpenTelemetry JavaScript Client
Stars: ✭ 700 (+1958.82%)
Mutual labels:  metrics, distributed-tracing
Pandora
A Manageable, Measurable and Traceable Node.js Application Manager represented by Alibaba powered by TypeScript
Stars: ✭ 3,084 (+8970.59%)
Mutual labels:  metrics, opentracing
Go Project Sample
Introduce the best practice experience of Go project with a complete project example.通过一个完整的项目示例介绍Go语言项目的最佳实践经验.
Stars: ✭ 344 (+911.76%)
Mutual labels:  opentracing, dependency-injection
Gf
GoFrame is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
Stars: ✭ 6,501 (+19020.59%)
Mutual labels:  framework, opentracing

CORE

Package core is a service container that elegantly bootstrap and coordinate twelve-factor apps in Go.

Build Go Reference codecov Go Report Card Release

Background

The twelve-factor methodology has proven its worth over the years. Since its invention many fields in technology have changed, many among them are shining and exciting. In the age of Kubernetes, service mesh and serverless architectures, the twelve-factor methodology has not faded away, but rather has happened to be a good fit for nearly all of those powerful platforms.

Scaffolding a twelve-factor go app may not be a difficult task for experienced engineers, but certainly presents some challenges to juniors. For those who are capable of setting things up, there are still many decisions left to make, and choices to be agreed upon within the team.

Package core was created to bootstrap and coordinate such services.

Feature

Package core shares the common concerns of your application:

  • Configuration management: env, flags, files, etc.
  • Pluggable transports: HTTP, gRPC, etc.
  • Dependency injection
  • Job management: Cron, long-running, one-off commandline, etc.
  • Events and Queues
  • Metrics
  • Distributed Tracing
  • Database migrations and seedings
  • Distributed transactions
  • Leader election

Overview

Whatever the app is, the bootstrapping phase is roughly composed by:

  • Read the configuration from out of the binary. Namely, flags, environment variables, and/or configuration files.

  • Initialize dependencies. Databases, message queues, service discoveries, etc.

  • Define how to run the app. HTTP, RPC, command-lines, cronjobs, or more often mixed.

Package core abstracts those repeated steps, keeping them concise, portable yet explicit. Let's see the following snippet:

package main

import (
  "context"
  "net/http"

  "github.com/DoNewsCode/core"
  "github.com/DoNewsCode/core/observability"
  "github.com/DoNewsCode/core/otgorm"
  "github.com/gorilla/mux"
)

func main() {
  // Phase One: create a core from a configuration file
  c := core.New(core.WithYamlFile("config.yaml"))

  // Phase two: bind dependencies
  c.Provide(otgorm.Providers())

  // Phase three: define service
  c.AddModule(core.HttpFunc(func(router *mux.Router) {
    router.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
      writer.Write([]byte("hello world"))
    })
  }))

  // Phase Four: run!
  c.Serve(context.Background())
}

In a few lines, an HTTP service is bootstrapped in the style outlined above. It is simple, explicit, and to some extent, declarative.

The service demonstrated above uses an inline handler function to highlight the point. Normally, for real projects, we will use modules instead. The "module" in package Core's glossary is not necessarily a go module (though it can be). It is simply a group of services.

You may note that the HTTP service doesn't really consume the dependency. That's true.

Let's rewrite the HTTP service to consume the above dependencies.

package main

import (
  "context"
  "net/http"

  "github.com/DoNewsCode/core"
  "github.com/DoNewsCode/core/otgorm"
  "github.com/DoNewsCode/core/srvhttp"
  "github.com/gorilla/mux"
  "gorm.io/gorm"
)

type User struct {
  Id   string
  Name string
}

type Repository struct {
  DB *gorm.DB
}

func (r Repository) Find(id string) (*User, error) {
  var user User
  if err := r.DB.First(&user, id).Error; err != nil {
    return nil, err
  }
  return &user, nil
}

type Handler struct {
  R Repository
}

func (h Handler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
  encoder := srvhttp.NewResponseEncoder(writer)
  encoder.Encode(h.R.Find(request.URL.Query().Get("id")))
}

type Module struct {
  H Handler
}

func New(db *gorm.DB) Module {
  return Module{Handler{Repository{db}}}
}

func (m Module) ProvideHTTP(router *mux.Router) {
  router.Handle("/", m.H)
}

func main() {
  // Phase One: create a core from a configuration file
  c := core.New(core.WithYamlFile("config.yaml"))

  // Phase two: bind dependencies
  c.Provide(otgorm.Providers())

  // Phase three: define service
  c.AddModuleFunc(New)

  // Phase four: run!
  c.Serve(context.Background())
}

Phase three has been replaced by the c.AddModuleFunc(New). AddModuleFunc populates the arguments to New from dependency containers and add the returned module instance to the internal module registry.

When c.Serve() is called, all registered modules will be scanned for implemented interfaces. The module in the example implements interface:

type HTTPProvider interface {
	ProvideHTTP(router *mux.Router)
}

Therefore, the core knows this module wants to expose HTTP service and subsequently invokes the ProvideHTTP with a router. You can register multiple modules, and each module can implement one or more services.

Now we have a fully workable project, with layers of handler, repository, and entity. Had this been a DDD workshop, we would be expanding the example even further.

That being said, let's redirect our attention to other goodies package core has offered:

  • Package core natively supports multiplexing modules. You could start you project as a monolith with multiple modules, and gradually migrate them into microservices.

  • Package core doesn't lock in transport or framework. For instance, you can use go kit to construct your services, and bring in transports like gRPC, AMPQ, thrift, etc. Non-network services like CLI and Cron are also supported.

  • Package core also babysits the services after initialization. The duty includes but not limited to distributed tracing, metrics exporting, error handling, event-dispatching, and leader election.

Be sure to checkout the documentation section to learn more.

Documentation

Design Principles

  • No package global state.
  • Promote dependency injection.
  • Testable code.
  • Minimalist interface design. Easy to decorate and replace.
  • Work with the Go ecosystem rather than reinventing the wheel.
  • End to end Context passing.

Non-Goals

  • Tries to be a Spring, Laravel, or Ruby on Rails.
  • Tries to care about service details.
  • Tries to reimplement the functionality provided by modern platforms.

Suggested service framework

  • Gin (if HTTP only)
  • Go Kit (if multiple transports)
  • Kratos (when v2 is ready)
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].