wrote readme, updated api
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
# go-mana-component
|
||||||
|
|
||||||
|
Component identity propagation for layered Go libraries.
|
||||||
|
|
||||||
|
Source: https://git.wisehodl.dev/jay/go-mana-component
|
||||||
|
Mirror: https://github.com/wisehodl/go-mana-component
|
||||||
|
|
||||||
|
## What this library does
|
||||||
|
|
||||||
|
- Injects a named component identity into a `context.Context` at library boundaries
|
||||||
|
- Propagates module identity and component hierarchy across layers
|
||||||
|
- Provides `slog` attributes for structured logging and a string map for generic consumers
|
||||||
|
|
||||||
|
## What this library does not do
|
||||||
|
|
||||||
|
`go-mana-component` does not log, does not define what a module or component
|
||||||
|
means semantically, and does not manage component lifecycles or dependencies.
|
||||||
|
It only carries identity. Interpretation, enforcement of naming conventions,
|
||||||
|
metrics, and tracing instrumentation all belong elsewhere.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get git.wisehodl.dev/jay/go-mana-component
|
||||||
|
```
|
||||||
|
|
||||||
|
If the primary repository is unavailable, use the `replace` directive in your `go.mod`:
|
||||||
|
|
||||||
|
```
|
||||||
|
replace git.wisehodl.dev/jay/go-mana-component => github.com/wisehodl/go-mana-component latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
As an example, the `go-honeybee` library uses a three-layer component hierarchy
|
||||||
|
for pools, workers, and connections. To provide structured logging, each
|
||||||
|
component accepts a component-aware context and an `slog.Handler` and then
|
||||||
|
constructs a logger internally.
|
||||||
|
|
||||||
|
### At a library boundary
|
||||||
|
|
||||||
|
A top-level constructor receives a context and creates a new component
|
||||||
|
identity. Injecting the component attributes on the logger allows it to carry
|
||||||
|
`module` and `path` automatically.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func NewPool(ctx context.Context, id string, handler slog.Handler) (*Pool, error) {
|
||||||
|
ctx = component.MustNew(ctx, "honeybee", "outbound_pool")
|
||||||
|
|
||||||
|
attrs, _ := component.Attrs(ctx)
|
||||||
|
logger := slog.New(handler).WithAttrs(attrs).With(slog.String("pool_id", id))
|
||||||
|
|
||||||
|
return &Pool{ctx: ctx, logger: logger}, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Descending into a sub-component
|
||||||
|
|
||||||
|
A child constructor calls `MustExtend`, inheriting the module and extending the
|
||||||
|
path. No parent identifiers need to be passed as arguments.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func NewWorker(ctx context.Context, id string, handler slog.Handler) (*Worker, error) {
|
||||||
|
ctx = component.MustExtend(ctx, "outbound_worker")
|
||||||
|
|
||||||
|
attrs, _ := component.Attrs(ctx)
|
||||||
|
logger := slog.New(handler).WithAttrs(attrs).With(slog.Any("peer_id", id))
|
||||||
|
|
||||||
|
return &Worker{ctx: ctx, logger: logger}, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
At the connection layer, another `MustExtend` call extends the path to
|
||||||
|
`outbound_pool.outbound_worker.connection` with no additional plumbing.
|
||||||
|
|
||||||
|
`GetFields` provides the component fields as a `map[string]string` for non-slog
|
||||||
|
consumers.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test ./...
|
||||||
|
```
|
||||||
@@ -41,8 +41,8 @@ func Get(ctx context.Context) (Component, bool) {
|
|||||||
return t, ok
|
return t, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustStart is Start but panics on error.
|
// MustNew is New but panics on error.
|
||||||
func MustStart(ctx context.Context, module string, name string) context.Context {
|
func MustNew(ctx context.Context, module string, name string) context.Context {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
panic("context is nil")
|
panic("context is nil")
|
||||||
}
|
}
|
||||||
@@ -55,8 +55,8 @@ func MustStart(ctx context.Context, module string, name string) context.Context
|
|||||||
return insert(ctx, module, name, []string{})
|
return insert(ctx, module, name, []string{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustNext is Next but panics on error.
|
// MustExtend is Extend but panics on error.
|
||||||
func MustNext(ctx context.Context, name string) context.Context {
|
func MustExtend(ctx context.Context, name string) context.Context {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
panic("context is nil")
|
panic("context is nil")
|
||||||
}
|
}
|
||||||
@@ -73,8 +73,8 @@ func MustNext(ctx context.Context, name string) context.Context {
|
|||||||
return insert(ctx, c.Module(), name, c.Path())
|
return insert(ctx, c.Module(), name, c.Path())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start sets a new component on the context, resetting any existing component.
|
// New sets a new component on the context, resetting any existing component.
|
||||||
func Start(ctx context.Context, module string, name string) (context.Context, error) {
|
func New(ctx context.Context, module string, name string) (context.Context, error) {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
return nil, fmt.Errorf("context is nil")
|
return nil, fmt.Errorf("context is nil")
|
||||||
}
|
}
|
||||||
@@ -87,8 +87,8 @@ func Start(ctx context.Context, module string, name string) (context.Context, er
|
|||||||
return insert(ctx, module, name, []string{}), nil
|
return insert(ctx, module, name, []string{}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next appends name to the current component path, inheriting its module.
|
// Extend appends name to the current component path, inheriting its module.
|
||||||
func Next(ctx context.Context, name string) (context.Context, error) {
|
func Extend(ctx context.Context, name string) (context.Context, error) {
|
||||||
if ctx == nil {
|
if ctx == nil {
|
||||||
return nil, fmt.Errorf("context is nil")
|
return nil, fmt.Errorf("context is nil")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user