Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
run: go mod download

- name: Run tests
run: go test -coverprofile=coverage.txt ./ ./internal/... ./pkg/...
run: go test -coverprofile=coverage.txt ./...

- name: Upload results to Codecov
uses: codecov/codecov-action@v5
Expand Down
6 changes: 2 additions & 4 deletions docs/content/docs/3-ioc-container/2-dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,15 @@ func (m *MetricsService) Report() {

## Multi-Binding (Slices & Maps)

Advanced architectural patterns (like the Strategy Pattern) rely on injecting *multiple* implementations of an interface
or struct. Rays natively supports multi-binding into slices and maps for both interface types and struct pointers.
Advanced architectural patterns (like the Strategy Pattern) rely on injecting *multiple* implementations of an interface or struct. Rays natively supports multi-binding into slices and maps for both interface types and struct pointers.

### Slice Injection (`[]T`)

Injecting into a slice will populate it with all registered Beams that match the slice's underlying type.

### Map Injection (`map[string]T`)

Injecting into a map requires the key to be of type `string`. Rays will map the injected Beams by their Qualifier name.
The key will be the injected Beam's `Qualifier` value.
Injecting into a map requires the key to be of type `string`. Rays will map the injected Beams by their Qualifier name. The key will be the injected Beam's `Qualifier` value.

```go
import . "github.com/BeamFoundry/rays/pkg/core"
Expand Down
6 changes: 2 additions & 4 deletions docs/content/docs/3-ioc-container/3-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@ func (e *EmailWorker) PostConstruct() Error {
```

## Phase 3: Runtime (`BeamRunner`)
Beams that implement the `rays.BeamRunner` interface will have their `Run(wg *sync.WaitGroup)` method executed when
`ctx.Run()` is called in `main.go`.
Beams that implement the `rays.BeamRunner` interface will have their `Run(wg *sync.WaitGroup)` method executed when `ctx.Run()` is called in `main.go`.

This hook is specifically designed for long-running processes (like HTTP servers, Kafka consumers, or periodic cron
jobs). The WaitGroup keeps the main application thread alive while your background workers execute.
This hook is specifically designed for long-running processes (like HTTP servers, Kafka consumers, or periodic cron jobs). The WaitGroup keeps the main application thread alive while your background workers execute.

```go
import (
Expand Down
29 changes: 14 additions & 15 deletions docs/content/docs/3-ioc-container/4-configuration-and-profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,40 @@ weight: 4

In enterprise applications, configuration and environment management go hand-in-hand.

Rays provides a unified system to bind YAML configurations directly to your structs, override them based on active
profiles (e.g., `dev`, `prod`), and conditionally load specific components depending on the environment.
Rays provides a unified system to bind YAML configurations directly to your structs,
override them based on active profiles (e.g., `dev`, `prod`), and conditionally load
specific components depending on the environment.

## 1. Binding Data

Embed `ConfigurationProperties` and define the YAML path via the `Name` tag.

**NOTE:** *Rays strictly enforces a 1-to-1 parity between your YAML files and your Go code. The `yaml` tag is **not
honored**. Only properties with the exact same case name as the Go struct field will be injected.*
**NOTE:** *Rays strictly enforces a 1-to-1 parity between your
YAML files and your Go code. The `yaml` tag is **not honored**. Only properties with
the exact same case name as the Go struct field will be injected.*

### Valid types

All numeric types, `bool` and `string` are honored.

Rays includes native support for `time.Duration`. Text values like `"5000ms"` in the YAML file are automatically parsed
using Go's standard `time.ParseDuration` function.
Rays includes native support for `time.Duration`.
Text values like `"5000ms"` in the YAML file are automatically parsed using Go's standard `time.ParseDuration` function.

Struct and struct pointers (sub-object mapping) are supported.

Struct implementing the `encoding.TextUnmarshaler` interface can also be used (string to struct mapping). The struct
type (not a pointer to that) can be used directly.
Struct implementing the `encoding.TextUnmarshaler` interface can also be used (string to struct mapping).
The struct type (not a pointer to that) can be used directly.

Slices of all the above types are supported.

Finally map of `string` and of `encoding.TextUnmarshaler` to all the above types and to other map of those two types are
supported.
Finally map of `string` and of `encoding.TextUnmarshaler` to all the above types and to other map of those two types are supported.

### Validation

Validation is done using the [Validation](github.com/go-playground/validator) project, given you provides the
corresponding tags.
Validation is done using the [Validation](github.com/go-playground/validator) project, given you provides the corresponding tags.

NOTE: To validate private fields on a struct, reflection structs will be constructed internally with public fields
instead. If using Cross-Field validation, fields should be indicated in their public form. Errors will be formatted
using the original private field instead.
NOTE: To validate private fields on a struct, reflection structs will be constructed internally with public fields instead.
If using Cross-Field validation, fields should be indicated in their public form. Errors will be formatted using the original private field instead.

### Example

Expand Down
3 changes: 1 addition & 2 deletions docs/content/docs/3-ioc-container/5-prototypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ weight: 5

# Prototypes & Foundries

If you need a new instance of an object every time it is requested (e.g., per HTTP request, per GRPC stream), you cannot
use a Singleton. You need a **Prototype**.
If you need a new instance of an object every time it is requested (e.g., per HTTP request, per GRPC stream), you cannot use a Singleton. You need a **Prototype**.

## `Foundry[T]`

Expand Down
33 changes: 10 additions & 23 deletions docs/content/docs/5-language-helpers/1-error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ weight: 1

# Error Handling

If a container fails to boot, you need to know exactly *where* the wiring failed. Rays replaces standard Go `error`
handling during the lifecycle with a richer `Error` interface that captures stack traces and key-value attributes
automatically.
If a container fails to boot, you need to know exactly *where* the wiring failed. Rays replaces standard Go `error` handling during the lifecycle with a richer `Error` interface that captures stack traces and key-value attributes automatically.

```go
import . "github.com/BeamFoundry/rays/pkg/lang"
Expand All @@ -28,11 +26,9 @@ func (s *UserService) PostConstruct() Error {

## Integration with Logging

Because Rays integrates its `lang` package directly with the `logging` framework (covered in Chapter 4), an `Error` can
report itself seamlessly.
Because Rays integrates its `lang` package directly with the `logging` framework (covered in Chapter 4), an `Error` can report itself seamlessly.

Instead of manually unpacking the error to log it, simply call `err.LogError()`. This function automatically extracts
the error message, the stack trace, and all attached attributes, serializing them into your configured logging backend.
Instead of manually unpacking the error to log it, simply call `err.LogError()`. This function automatically extracts the error message, the stack trace, and all attached attributes, serializing them into your configured logging backend.

```go
import . "github.com/BeamFoundry/rays/pkg/lang"
Expand All @@ -54,27 +50,18 @@ func (s *PaymentService) Process(amount float64) Error {

## The Try/Catch Pattern

While standard Go relies heavily on `if err != nil` checks, complex procedural logic can sometimes benefit from a more
traditional exception-handling flow. The `lang` package provides a robust `Try/Catch` mechanism designed specifically
around the framework's `Error` interface.
While standard Go relies heavily on `if err != nil` checks, complex procedural logic can sometimes benefit from a more traditional exception-handling flow. The `lang` package provides a robust `Try/Catch` mechanism designed specifically around the framework's `Error` interface.

### Core Functions
* **`Try(try func(), catches ...ErrorHandler) Error`**: Executes the `try` function. If a panic occurs involving an
`Error`, it evaluates the provided catches and returns the resulting `Error`. If no catch matches, the original error is
returned automatically. Additionally, if standard Go code or a sub-function triggers a regular `panic()`, the `Try`
block will safely catch it and wrap it into a new framework `Error` with the name "\"PanicError\"", ensuring your
application does not crash unexpectedly.
* **`Try(try func(), catches ...ErrorHandler) Error`**: Executes the `try` function. If a panic occurs involving an `Error`, it evaluates the provided catches and returns the resulting `Error`. If no catch matches, the original error is returned automatically. Additionally, if standard Go code or a sub-function triggers a regular `panic()`, the `Try` block will safely catch it and wrap it into a new framework `Error` with the name "\"PanicError\"", ensuring your application does not crash unexpectedly.
* **`Catch[E Error](action func(E) Error) ErrorHandler`**: Catches an error based on its specific Go type.
* **`CatchName(name string, action func(Error) Error) ErrorHandler`**: Catches an error based on its internal string
name.
* **`Finally(action func()) ErrorHandler`**: Executes an action after the `try` block finishes, regardless of success or
failure.
* **`CatchName(name string, action func(Error) Error) ErrorHandler`**: Catches an error based on its internal string name.
* **`Finally(action func()) ErrorHandler`**: Executes an action after the `try` block finishes, regardless of success or failure.

### Raise Helpers To easily trigger panics within a `Try` block when dealing with standard Go returns, use the `Raise`
helpers:
### Raise Helpers
To easily trigger panics within a `Try` block when dealing with standard Go returns, use the `Raise` helpers:
* **`RaiseErr(err error) bool`**: Panics if `err` is not nil.
* **`RaiseVal[T any](t T, err error) T`**: Panics if `err` is not nil; otherwise, returns the object `T`. This is
perfect for wrapping standard library calls like `RaiseVal(os.ReadFile("config.yaml"))`.
* **`RaiseVal[T any](t T, err error) T`**: Panics if `err` is not nil; otherwise, returns the object `T`. This is perfect for wrapping standard library calls like `RaiseVal(os.ReadFile("config.yaml"))`.

### Example Usage

Expand Down
9 changes: 3 additions & 6 deletions docs/content/docs/5-language-helpers/2-enum-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ weight: 2

# Type-Safe Enums

Go does not have native, strict enums. This often leads to configuration bugs where an invalid string from a YAML file
is happily parsed into a `string` field, only to fail deep within the application logic.
Go does not have native, strict enums. This often leads to configuration bugs where an invalid string from a YAML file is happily parsed into a `string` field, only to fail deep within the application logic.

Rays solves this with `Enum[T]`. It strictly binds string values from YAML into custom Go types and validates them
during the framework's Instantiation phase.
Rays solves this with `Enum[T]`. It strictly binds string values from YAML into custom Go types and validates them during the framework's Instantiation phase.

### 1. Define the Enum Type
You can define your enums using a struct to hold the variants as fields.
Expand Down Expand Up @@ -48,8 +46,7 @@ type AppConfig struct {
```

### 3. Safe Access in Business Logic
Because of the generic structuring, you must initialize the enum type by calling `.New()` to ensure its internal state
is properly configured before accessing its variants.
Because of the generic structuring, you must initialize the enum type by calling `.New()` to ensure its internal state is properly configured before accessing its variants.

You can then compare it directly to your configuration fields without needing a getter function.

Expand Down
Loading
Loading