mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-09 00:56:37 +08:00
autoresearch iter 1: keep Using2/Using3 dependency causes reachable
Using2/Using3 flattened per-dependency injection failures with %v while Using1 wrapped with %w, so errors.Is could not see ErrServiceNotFound through a multi-dependency resolution failure.
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -179,8 +180,8 @@ func Using[T1 any](ctx *Context, fn func(s1 T1)) error {
|
|||||||
func Using2[T1, T2 any](ctx *Context, fn func(s1 T1, s2 T2)) error {
|
func Using2[T1, T2 any](ctx *Context, fn func(s1 T1, s2 T2)) error {
|
||||||
s1, err1 := Inject[T1](ctx)
|
s1, err1 := Inject[T1](ctx)
|
||||||
s2, err2 := Inject[T2](ctx)
|
s2, err2 := Inject[T2](ctx)
|
||||||
if err1 != nil || err2 != nil {
|
if err := errors.Join(err1, err2); err != nil {
|
||||||
return fmt.Errorf("%w: (dep1: %v, dep2: %v)", ErrServiceNotReady, err1, err2)
|
return fmt.Errorf("%w: %w", ErrServiceNotReady, err)
|
||||||
}
|
}
|
||||||
fn(s1, s2)
|
fn(s1, s2)
|
||||||
return nil
|
return nil
|
||||||
@@ -191,8 +192,8 @@ func Using3[T1, T2, T3 any](ctx *Context, fn func(s1 T1, s2 T2, s3 T3)) error {
|
|||||||
s1, err1 := Inject[T1](ctx)
|
s1, err1 := Inject[T1](ctx)
|
||||||
s2, err2 := Inject[T2](ctx)
|
s2, err2 := Inject[T2](ctx)
|
||||||
s3, err3 := Inject[T3](ctx)
|
s3, err3 := Inject[T3](ctx)
|
||||||
if err1 != nil || err2 != nil || err3 != nil {
|
if err := errors.Join(err1, err2, err3); err != nil {
|
||||||
return fmt.Errorf("%w: (dep1: %v, dep2: %v, dep3: %v)", ErrServiceNotReady, err1, err2, err3)
|
return fmt.Errorf("%w: %w", ErrServiceNotReady, err)
|
||||||
}
|
}
|
||||||
fn(s1, s2, s3)
|
fn(s1, s2, s3)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -222,6 +222,33 @@ func TestContextUsingMultiple(t *testing.T) {
|
|||||||
assert.True(t, called3)
|
assert.True(t, called3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UsingN must keep every dependency failure reachable through the error chain,
|
||||||
|
// not just report that something went wrong.
|
||||||
|
func TestContextUsingMultipleErrorChain(t *testing.T) {
|
||||||
|
ctx := core.NewContext(context.Background())
|
||||||
|
|
||||||
|
err := core.Using2(ctx, func(s SampleService, l LogService) {
|
||||||
|
t.Fatal("callback must not run when dependencies are missing")
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotReady)
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotFound)
|
||||||
|
|
||||||
|
// Only LogService is missing now, so exactly one joined cause must be present.
|
||||||
|
core.Provide[SampleService](ctx, &sampleServiceImpl{})
|
||||||
|
err = core.Using2(ctx, func(s SampleService, l LogService) {
|
||||||
|
t.Fatal("callback must not run when a dependency is missing")
|
||||||
|
})
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotReady)
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotFound)
|
||||||
|
|
||||||
|
err = core.Using3(ctx, func(s SampleService, l LogService, c ConfigService) {
|
||||||
|
t.Fatal("callback must not run when a dependency is missing")
|
||||||
|
})
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotReady)
|
||||||
|
assert.ErrorIs(t, err, core.ErrServiceNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextHierarchyAndFork(t *testing.T) {
|
func TestContextHierarchyAndFork(t *testing.T) {
|
||||||
parent := core.NewContext(nil) // nil base context test
|
parent := core.NewContext(nil) // nil base context test
|
||||||
core.Provide[SampleService](parent, &sampleServiceImpl{prefix: "Parent:"})
|
core.Provide[SampleService](parent, &sampleServiceImpl{prefix: "Parent:"})
|
||||||
|
|||||||
Reference in New Issue
Block a user