Skip to content

Commit 3330908

Browse files
authored
story(issue-33): make package responsible for running themselves (#34)
1 parent 5045e70 commit 3330908

File tree

6 files changed

+49
-123
lines changed

6 files changed

+49
-123
lines changed

example/rest-petstore/app/app.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import (
1111
"github.com/z5labs/humus/example/internal/petstore"
1212
"github.com/z5labs/humus/example/rest-petstore/endpoint"
1313

14-
"github.com/z5labs/humus"
1514
"github.com/z5labs/humus/rest"
1615
)
1716

1817
type Config struct {
1918
rest.Config `config:",squash"`
2019
}
2120

22-
func Init(ctx context.Context, cfg Config) (humus.App, error) {
21+
func Init(ctx context.Context, cfg Config) (*rest.App, error) {
2322
store := petstore.NewInMemory()
2423

2524
app := rest.New(

example/rest-petstore/main.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ import (
1010
_ "embed"
1111

1212
"github.com/z5labs/humus/example/rest-petstore/app"
13-
14-
"github.com/z5labs/humus"
13+
"github.com/z5labs/humus/rest"
1514
)
1615

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

2019
func main() {
21-
humus.Run(bytes.NewReader(configBytes), app.Init)
20+
rest.Run(bytes.NewReader(configBytes), app.Init)
2221
}

humus.go

+4-30
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,13 @@
77
package humus
88

99
import (
10-
"bytes"
1110
"context"
1211
_ "embed"
1312
"errors"
14-
"io"
1513
"log/slog"
1614
"os"
1715
"time"
1816

19-
"github.com/z5labs/humus/internal"
20-
"github.com/z5labs/humus/internal/global"
21-
2217
"github.com/z5labs/bedrock"
2318
"github.com/z5labs/bedrock/pkg/app"
2419
"github.com/z5labs/bedrock/pkg/appbuilder"
@@ -43,11 +38,7 @@ import (
4338
)
4439

4540
//go:embed default_config.yaml
46-
var configBytes []byte
47-
48-
func init() {
49-
global.RegisterConfigSource(internal.ConfigSource(bytes.NewReader(configBytes)))
50-
}
41+
var DefaultConfig []byte
5142

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

9182
// Run
92-
func Run[T any](r io.Reader, build func(context.Context, T) (App, error)) {
93-
cfgSrcs := global.ConfigSources
94-
cfgSrcs = append(cfgSrcs, internal.ConfigSource(r))
95-
83+
func Run[T any](build func(context.Context, T) (App, error), srcs ...config.Source) error {
9684
runner := runner{
97-
srcs: cfgSrcs,
85+
srcs: srcs,
9886
detectResource: detectResource,
9987
newTraceExporter: func(ctx context.Context, oc OTelConfig) (sdktrace.SpanExporter, error) {
10088
return otlptracegrpc.New(
@@ -123,21 +111,7 @@ func Run[T any](r io.Reader, build func(context.Context, T) (App, error)) {
123111
},
124112
}
125113

126-
err := run(runner, build)
127-
if err == nil {
128-
return
129-
}
130-
131-
// there's a chance Run failed on config parsing/unmarshalling
132-
// thus the logging config is most likely unusable and we should
133-
// instead create our own logger here for logging this error
134-
// there's a chance Run failed on config parsing/unmarshalling
135-
// thus the logging config is most likely unusable and we should
136-
// instead create our own logger here for logging this error
137-
fallbackLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
138-
AddSource: true,
139-
}))
140-
fallbackLogger.Error("failed while running application", slog.String("error", err.Error()))
114+
return run(runner, build)
141115
}
142116

143117
type runner struct {

humus_test.go

+12-68
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@ import (
1010
"context"
1111
"encoding/json"
1212
"errors"
13-
"os"
14-
"path/filepath"
1513
"strings"
1614
"testing"
17-
"time"
1815

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

4341
func TestRun(t *testing.T) {
44-
t.Run("will log a record to stdout", func(t *testing.T) {
42+
t.Run("will return an error", func(t *testing.T) {
4543
t.Run("if no otlp target is set", func(t *testing.T) {
46-
filename := filepath.Join(t.TempDir(), "log.json")
47-
f, err := os.Create(filename)
48-
if !assert.Nil(t, err) {
49-
return
50-
}
51-
52-
done := make(chan struct{})
53-
go func() {
54-
defer close(done)
55-
56-
stdout := os.Stdout
57-
defer func() {
58-
os.Stdout = stdout
59-
}()
60-
61-
os.Stdout = f
62-
63-
app := appFunc(func(ctx context.Context) error {
64-
log := Logger("app")
65-
log.InfoContext(ctx, "hello")
66-
return nil
67-
})
44+
app := appFunc(func(ctx context.Context) error {
45+
log := Logger("app")
46+
log.InfoContext(ctx, "hello")
47+
return nil
48+
})
6849

69-
Run(strings.NewReader(""), func(ctx context.Context, cfg Config) (App, error) {
50+
err := Run(
51+
func(ctx context.Context, cfg Config) (App, error) {
7052
return app, nil
71-
})
72-
}()
73-
74-
select {
75-
case <-time.After(30 * time.Second):
76-
t.Fail()
77-
return
78-
case <-done:
79-
}
80-
81-
err = f.Close()
82-
if !assert.Nil(t, err) {
83-
return
84-
}
85-
86-
f, err = os.Open(filename)
87-
if !assert.Nil(t, err) {
88-
return
89-
}
90-
defer f.Close()
91-
92-
type log struct {
93-
Body struct {
94-
Value string `json:"Value"`
95-
} `json:"Body"`
96-
Scope struct {
97-
Name string `json:"Name"`
98-
} `json:"Scope"`
99-
}
100-
101-
var l log
102-
dec := json.NewDecoder(f)
103-
err = dec.Decode(&l)
53+
},
54+
internal.ConfigSource(strings.NewReader("")),
55+
)
10456
if !assert.Nil(t, err) {
10557
return
10658
}
107-
if !assert.Equal(t, "app", l.Scope.Name) {
108-
return
109-
}
110-
if !assert.Equal(t, "hello", l.Body.Value) {
111-
return
112-
}
11359
})
114-
})
11560

116-
t.Run("will return an error", func(t *testing.T) {
11761
t.Run("if it fails to read one of the config sources", func(t *testing.T) {
11862
build := func(ctx context.Context, cfg Config) (App, error) {
11963
return nil, nil

internal/global/config.go

-14
This file was deleted.

rest/rest.go

+30-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import (
1212
_ "embed"
1313
"errors"
1414
"fmt"
15+
"io"
16+
"log/slog"
1517
"net"
1618
"net/http"
19+
"os"
1720

1821
"github.com/z5labs/humus"
1922
"github.com/z5labs/humus/internal"
20-
"github.com/z5labs/humus/internal/global"
2123

2224
"github.com/z5labs/bedrock"
2325
"github.com/z5labs/bedrock/pkg/app"
@@ -27,11 +29,7 @@ import (
2729
)
2830

2931
//go:embed default_config.yaml
30-
var configBytes []byte
31-
32-
func init() {
33-
global.RegisterConfigSource(internal.ConfigSource(bytes.NewReader(configBytes)))
34-
}
32+
var DefaultConfig []byte
3533

3634
// Config
3735
type Config struct {
@@ -47,6 +45,32 @@ type Config struct {
4745
} `config:"openapi"`
4846
}
4947

48+
// Run
49+
func Run[T any](r io.Reader, f func(context.Context, T) (*App, error)) {
50+
err := humus.Run(
51+
func(ctx context.Context, cfg T) (humus.App, error) {
52+
return f(ctx, cfg)
53+
},
54+
internal.ConfigSource(bytes.NewReader(humus.DefaultConfig)),
55+
internal.ConfigSource(bytes.NewReader(DefaultConfig)),
56+
internal.ConfigSource(r),
57+
)
58+
if err == nil {
59+
return
60+
}
61+
62+
// there's a chance Run failed on config parsing/unmarshalling
63+
// thus the logging config is most likely unusable and we should
64+
// instead create our own logger here for logging this error
65+
// there's a chance Run failed on config parsing/unmarshalling
66+
// thus the logging config is most likely unusable and we should
67+
// instead create our own logger here for logging this error
68+
fallbackLogger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
69+
AddSource: true,
70+
}))
71+
fallbackLogger.Error("failed while running application", slog.String("error", err.Error()))
72+
}
73+
5074
// Option
5175
type Option func(*App)
5276

0 commit comments

Comments
 (0)