Skip to content

Commit

Permalink
story(issue-33): make package responsible for running themselves (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaba505 authored Nov 2, 2024
1 parent 5045e70 commit 3330908
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 123 deletions.
3 changes: 1 addition & 2 deletions example/rest-petstore/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ import (
"github.com/z5labs/humus/example/internal/petstore"
"github.com/z5labs/humus/example/rest-petstore/endpoint"

"github.com/z5labs/humus"
"github.com/z5labs/humus/rest"
)

type Config struct {
rest.Config `config:",squash"`
}

func Init(ctx context.Context, cfg Config) (humus.App, error) {
func Init(ctx context.Context, cfg Config) (*rest.App, error) {
store := petstore.NewInMemory()

app := rest.New(
Expand Down
5 changes: 2 additions & 3 deletions example/rest-petstore/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import (
_ "embed"

"github.com/z5labs/humus/example/rest-petstore/app"

"github.com/z5labs/humus"
"github.com/z5labs/humus/rest"
)

//go:embed config.yaml
var configBytes []byte

func main() {
humus.Run(bytes.NewReader(configBytes), app.Init)
rest.Run(bytes.NewReader(configBytes), app.Init)
}
34 changes: 4 additions & 30 deletions humus.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@
package humus

import (
"bytes"
"context"
_ "embed"
"errors"
"io"
"log/slog"
"os"
"time"

"github.com/z5labs/humus/internal"
"github.com/z5labs/humus/internal/global"

"github.com/z5labs/bedrock"
"github.com/z5labs/bedrock/pkg/app"
"github.com/z5labs/bedrock/pkg/appbuilder"
Expand All @@ -43,11 +38,7 @@ import (
)

//go:embed default_config.yaml
var configBytes []byte

func init() {
global.RegisterConfigSource(internal.ConfigSource(bytes.NewReader(configBytes)))
}
var DefaultConfig []byte

type OTelConfig struct {
ServiceName string `config:"service_name"`
Expand Down Expand Up @@ -89,12 +80,9 @@ func Logger(name string) *slog.Logger {
type App bedrock.App

// Run
func Run[T any](r io.Reader, build func(context.Context, T) (App, error)) {
cfgSrcs := global.ConfigSources
cfgSrcs = append(cfgSrcs, internal.ConfigSource(r))

func Run[T any](build func(context.Context, T) (App, error), srcs ...config.Source) error {
runner := runner{
srcs: cfgSrcs,
srcs: srcs,
detectResource: detectResource,
newTraceExporter: func(ctx context.Context, oc OTelConfig) (sdktrace.SpanExporter, error) {
return otlptracegrpc.New(
Expand Down Expand Up @@ -123,21 +111,7 @@ func Run[T any](r io.Reader, build func(context.Context, T) (App, error)) {
},
}

err := run(runner, build)
if err == nil {
return
}

// there's a chance Run failed on config parsing/unmarshalling
// thus the logging config is most likely unusable and we should
// instead create our own logger here for logging this error
// there's a chance Run failed on config parsing/unmarshalling
// thus the logging config is most likely unusable and we should
// instead create our own logger here for logging this error
fallbackLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
}))
fallbackLogger.Error("failed while running application", slog.String("error", err.Error()))
return run(runner, build)
}

type runner struct {
Expand Down
80 changes: 12 additions & 68 deletions humus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import (
"context"
"encoding/json"
"errors"
"os"
"path/filepath"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/z5labs/bedrock/pkg/config"
"github.com/z5labs/humus/internal"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
Expand All @@ -41,79 +39,25 @@ func (f appFunc) Run(ctx context.Context) error {
}

func TestRun(t *testing.T) {
t.Run("will log a record to stdout", func(t *testing.T) {
t.Run("will return an error", func(t *testing.T) {
t.Run("if no otlp target is set", func(t *testing.T) {
filename := filepath.Join(t.TempDir(), "log.json")
f, err := os.Create(filename)
if !assert.Nil(t, err) {
return
}

done := make(chan struct{})
go func() {
defer close(done)

stdout := os.Stdout
defer func() {
os.Stdout = stdout
}()

os.Stdout = f

app := appFunc(func(ctx context.Context) error {
log := Logger("app")
log.InfoContext(ctx, "hello")
return nil
})
app := appFunc(func(ctx context.Context) error {
log := Logger("app")
log.InfoContext(ctx, "hello")
return nil
})

Run(strings.NewReader(""), func(ctx context.Context, cfg Config) (App, error) {
err := Run(
func(ctx context.Context, cfg Config) (App, error) {
return app, nil
})
}()

select {
case <-time.After(30 * time.Second):
t.Fail()
return
case <-done:
}

err = f.Close()
if !assert.Nil(t, err) {
return
}

f, err = os.Open(filename)
if !assert.Nil(t, err) {
return
}
defer f.Close()

type log struct {
Body struct {
Value string `json:"Value"`
} `json:"Body"`
Scope struct {
Name string `json:"Name"`
} `json:"Scope"`
}

var l log
dec := json.NewDecoder(f)
err = dec.Decode(&l)
},
internal.ConfigSource(strings.NewReader("")),
)
if !assert.Nil(t, err) {
return
}
if !assert.Equal(t, "app", l.Scope.Name) {
return
}
if !assert.Equal(t, "hello", l.Body.Value) {
return
}
})
})

t.Run("will return an error", func(t *testing.T) {
t.Run("if it fails to read one of the config sources", func(t *testing.T) {
build := func(ctx context.Context, cfg Config) (App, error) {
return nil, nil
Expand Down
14 changes: 0 additions & 14 deletions internal/global/config.go

This file was deleted.

36 changes: 30 additions & 6 deletions rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (
_ "embed"
"errors"
"fmt"
"io"
"log/slog"
"net"
"net/http"
"os"

"github.com/z5labs/humus"
"github.com/z5labs/humus/internal"
"github.com/z5labs/humus/internal/global"

"github.com/z5labs/bedrock"
"github.com/z5labs/bedrock/pkg/app"
Expand All @@ -27,11 +29,7 @@ import (
)

//go:embed default_config.yaml
var configBytes []byte

func init() {
global.RegisterConfigSource(internal.ConfigSource(bytes.NewReader(configBytes)))
}
var DefaultConfig []byte

// Config
type Config struct {
Expand All @@ -47,6 +45,32 @@ type Config struct {
} `config:"openapi"`
}

// Run
func Run[T any](r io.Reader, f func(context.Context, T) (*App, error)) {
err := humus.Run(
func(ctx context.Context, cfg T) (humus.App, error) {
return f(ctx, cfg)
},
internal.ConfigSource(bytes.NewReader(humus.DefaultConfig)),
internal.ConfigSource(bytes.NewReader(DefaultConfig)),
internal.ConfigSource(r),
)
if err == nil {
return
}

// there's a chance Run failed on config parsing/unmarshalling
// thus the logging config is most likely unusable and we should
// instead create our own logger here for logging this error
// there's a chance Run failed on config parsing/unmarshalling
// thus the logging config is most likely unusable and we should
// instead create our own logger here for logging this error
fallbackLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
}))
fallbackLogger.Error("failed while running application", slog.String("error", err.Error()))
}

// Option
type Option func(*App)

Expand Down

0 comments on commit 3330908

Please sign in to comment.