bedrock

package module
v0.4.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2024 License: MIT Imports: 11 Imported by: 0

README

bedrock

Mentioned in Awesome Go Go Reference Go Report Card Coverage build

bedrock provides a minimal, modular and composable foundation for quickly developing services and more use case specific frameworks in Go.

Core Concepts

bedrock begins with the concepts of an App and a Runtime. App is a container for a Runtime and handles more "low-level" things, such as, OS interrupts, config parsing, environment variable overrides, etc. The Runtime is then the users entry point for jumping right into their use case specific code e.g. RESTful API, gRPC service, K8s job, etc.

Building services with bedrock

bedrock conveniently comes with a couple of Runtimes already implemented for you. This can significantly aid in shortening your overall development time, as well as, provide an example for how to implement your own custom Runtime.

For example, the below shows how simple it is to initialize an HTTP based "API" leveraging the builtin HTTP Runtime.

package main

import (
    "context"
    "net/http"

    "github.com/z5labs/bedrock"
    "github.com/z5labs/bedrock/http"
)

func initRuntime(ctx context.Context) (bedrock.Runtime, error) {
    rt := brhttp.NewRuntime(
		brhttp.ListenOnPort(8080),
		brhttp.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprint(w, "Hello, world")
		}),
	)
	return rt, nil
}

func main() {
	bedrock.New(
		bedrock.WithRuntimeBuilderFunc(initRuntime),
	).Run()
}

There you go! An entire HTTP API in less than 20 lines... well kind of. This incredibly simple example can easily be extended (aka made more production-ready) by supplying extra options to both bedrock.New and brhttp.NewRuntime. For available, options please check the official Go documentation.

Building custom frameworks with bedrock

One of the guiding principals for bedrock is to composable. This principal comes from the experience gained from working with custom, tailor made frameworks which over their lifetime within an organization are unable to adapt to changing development and deployment patterns. Eventually, these frameworks are abandoned for new ones or completely rewritten to reflect the current state of the organization.

bedrock defines a small set of types and carefully chooses its opinions to balance composability and functionality, as much as it can. The result is, in fact, a framework that isn't necessarily designed for building services directly, but instead meant for building more custom, use case specific frameworks.

For example, bedrock could be used by your organizations platform engineering or framework team(s) to quickly develop internal frameworks which abstract over all of your organizations requirements e.g. OpenTelemetry, Logging, Authenticated endpoints, etc. Then, due to the high composibility of bedrock, any changes within your organization would then be very easy to adapt to within your internal framework. A more concrete example of how a custom framework could look like can be found in example/custom_framework.

Documentation

Overview

Package bedrock provides a minimal foundation for building more complex frameworks on top of.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConfigFromContext

func ConfigFromContext(ctx context.Context) config.Manager

ConfigFromContext extracts a config.Manager from the given context.Context if it's present.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App handles the lower level things of running a service in Go. App is responsible for the following:

  • Parsing (and merging) you config(s)
  • Calling your lifecycle hooks at the appropriate times
  • Running your Runtime(s) and propogating any OS interrupts via context.Context cancellation

func New

func New(opts ...Option) *App

New returns a fully initialized App.

func (*App) Run

func (app *App) Run(args ...string) error

Run executes the application. It also handles listening for interrupts from the underlying OS and terminates the application when one is received.

Example
r := strings.NewReader(`hello: {{env "HELLO" | default "world"}}`)

app := New(
	Name("example"),
	ConfigTemplateFunc("env", configtmpl.Env),
	ConfigTemplateFunc("default", configtmpl.Default),
	Config(r),
	WithRuntimeBuilderFunc(func(ctx context.Context) (Runtime, error) {
		m := ConfigFromContext(ctx)
		var cfg struct {
			Hello string `config:"hello"`
		}
		err := m.Unmarshal(&cfg)
		if err != nil {
			return nil, err
		}

		rt := runtimeFunc(func(ctx context.Context) error {
			fmt.Printf("hello, %s\n", cfg.Hello)
			return nil
		})
		return rt, nil
	}),
)

err := app.Run()
if err != nil {
	fmt.Println(err)
	return
}
Output:

hello, world

type Lifecycle

type Lifecycle struct {
	// contains filtered or unexported fields
}

Lifecycle provides the ability to hook into certain points of the bedrock App.Run process.

func LifecycleFromContext

func LifecycleFromContext(ctx context.Context) *Lifecycle

LifecycleFromContext extracts a *Lifecycle from the given context.Context if it's present.

func (*Lifecycle) PostRun

func (l *Lifecycle) PostRun(hooks ...func(context.Context) error)

PostRun registers hooks to be after Runtime.Run has completed, regardless whether it returned an error or not.

func (*Lifecycle) PreBuild added in v0.0.7

func (l *Lifecycle) PreBuild(hooks ...func(context.Context) error)

PreBuild registers hooks to be called after the config is parsed and before all RuntimeBuilder.Builds are called.

func (*Lifecycle) PreRun

func (l *Lifecycle) PreRun(hooks ...func(context.Context) error)

PreRun registers hooks to be called after all RuntimeBuilder.Builds have been called and before all Runtime.Runs are called.

type Option

type Option func(*App)

Option are used to configure an App.

func Config

func Config(r io.Reader) Option

Config registers a config source with the application. If used multiple times, subsequent configs will be merged with the very first Config provided. The subsequent configs values will override any previous configs values.

func ConfigTemplateFunc added in v0.3.0

func ConfigTemplateFunc(name string, f any) Option

ConfigTemplateFunc registers the given template func with the underlying config reader so it can be used in config source templates.

func Hooks

func Hooks(fs ...func(*Lifecycle)) Option

Hooks allows you to register multiple lifecycle hooks.

func Name

func Name(name string) Option

Name configures the name of the application.

func WithRuntimeBuilder

func WithRuntimeBuilder(rb RuntimeBuilder) Option

WithRuntimeBuilder registers the given RuntimeBuilder with the App.

func WithRuntimeBuilderFunc

func WithRuntimeBuilderFunc(f func(context.Context) (Runtime, error)) Option

WithRuntimeBuilderFunc registers the given function as a RuntimeBuilder.

type Runtime

type Runtime interface {
	Run(context.Context) error
}

Runtime represents the entry point for user specific code. The Runtime should not worry about things like OS interrupts and config parsing because App is responsible for managing those more "low-level" things. A Runtime should be purely focused on running use case specific code e.g. RESTful API, gRPC API, K8s Job, etc.

type RuntimeBuilder

type RuntimeBuilder interface {
	Build(context.Context) (Runtime, error)
}

RuntimeBuilder represents anything which can initialize a Runtime.

type RuntimeBuilderFunc

type RuntimeBuilderFunc func(context.Context) (Runtime, error)

RuntimeBuilderFunc is a functional implementation of the RuntimeBuilder interface.

func (RuntimeBuilderFunc) Build

Build implements the RuntimeBuilder interface.

Directories

Path Synopsis
example
Package grpc provides a gRPC server which implements the app.Runtime interface.
Package grpc provides a gRPC server which implements the app.Runtime interface.
Package http provides a HTTP server which implements the app.Runtime interface.
Package http provides a HTTP server which implements the app.Runtime interface.
httpclient
Package httpclient provides a production ready http.Client.
Package httpclient provides a production ready http.Client.
httphealth
Package httphealth provides a http.Handler for exposing health.Metrics
Package httphealth provides a http.Handler for exposing health.Metrics
httpvalidate
Package httpvalidate provides helpers for validating incoming HTTP requests.
Package httpvalidate provides helpers for validating incoming HTTP requests.
pkg
config
Package config provides a useful wrapper for the popular spf13/viper package.
Package config provides a useful wrapper for the popular spf13/viper package.
config/configtmpl
Package configtmpl provides template functions for ue in config source templates.
Package configtmpl provides template functions for ue in config source templates.
health
Package health defines K8s inspired health metrics.
Package health defines K8s inspired health metrics.
lifecycle
Package lifecycle provides helpers for registering common lifecycle hooks.
Package lifecycle provides helpers for registering common lifecycle hooks.
maskslog
Package maskslog provides a slog.Handler which includes support for masking slog.Attrs.
Package maskslog provides a slog.Handler which includes support for masking slog.Attrs.
noop
Package noop provides no-op implementations to be used in tests and as defaults.
Package noop provides no-op implementations to be used in tests and as defaults.
otelconfig
Package otelconfig provides helpers for initializing specific trace.TracerProviders.
Package otelconfig provides helpers for initializing specific trace.TracerProviders.
otelslog
Package otelslog provides a OpenTelemetry aware slog.Handler implementation.
Package otelslog provides a OpenTelemetry aware slog.Handler implementation.
slogfield
Package slogfield re-exports and provides extra slog.Attrs.
Package slogfield re-exports and provides extra slog.Attrs.
Package queue provides multiple patterns which implements the app.Runtime interface.
Package queue provides multiple patterns which implements the app.Runtime interface.
pubsub
Package pubsub provides default implementations for using Google Cloud PubSub with the runtimes in the queue package.
Package pubsub provides default implementations for using Google Cloud PubSub with the runtimes in the queue package.
sqs
Package sqs provides default implementations for using AWS SQS with the runtimes in the queue package.
Package sqs provides default implementations for using AWS SQS with the runtimes in the queue package.
sqs/sqsslog
Package sqsslog provides slog helpers for SQS related data fields.
Package sqsslog provides slog helpers for SQS related data fields.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL