Skip to content

Commit d318ece

Browse files
authored
fix(fxhealthcheck): Fix resolution collision by using full import path in type IDs (#368)
1 parent 37e8c19 commit d318ece

File tree

3 files changed

+37
-8
lines changed

3 files changed

+37
-8
lines changed

fxhealthcheck/reflect.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,39 @@ import (
44
"reflect"
55
)
66

7-
// GetType returns the type of a target.
7+
// fullTypeID builds a stable identifier for a type in the form "<pkgpath>.<TypeName>".
8+
func fullTypeID(t reflect.Type) string {
9+
if t == nil {
10+
return ""
11+
}
12+
13+
// Unwrap pointers to get the underlying named type (if any).
14+
for t.Kind() == reflect.Pointer {
15+
t = t.Elem()
16+
}
17+
18+
// For named types, PkgPath() + Name() gives a unique and stable identity.
19+
if t.Name() != "" && t.PkgPath() != "" {
20+
return t.PkgPath() + "." + t.Name()
21+
}
22+
23+
// Fallback for non-named kinds (slices, maps, func, etc.).
24+
return t.String()
25+
}
26+
27+
// GetType returns a stable identifier for the given target’s type.
828
func GetType(target any) string {
9-
return reflect.TypeOf(target).String()
29+
return fullTypeID(reflect.TypeOf(target))
1030
}
1131

12-
// GetReturnType returns the return type of a target.
32+
// GetReturnType returns a stable identifier for the return type of constructor-like target.
33+
// If a target is a function, we examine its first return value (index 0), unwrap pointers, and
34+
// build an identifier for that named type. For non-function or empty-return cases, we return "".
1335
func GetReturnType(target any) string {
14-
return reflect.TypeOf(target).Out(0).String()
36+
t := reflect.TypeOf(target)
37+
if t == nil || t.Kind() != reflect.Func || t.NumOut() == 0 {
38+
return ""
39+
}
40+
41+
return fullTypeID(t.Out(0))
1542
}

fxhealthcheck/reflect_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ func TestGetType(t *testing.T) {
1515
target any
1616
expected string
1717
}{
18+
{nil, ""},
1819
{123, "int"},
1920
{"test", "string"},
20-
{probes.NewSuccessProbe(), "*probes.SuccessProbe"},
21-
{probes.NewFailureProbe(), "*probes.FailureProbe"},
21+
{probes.NewSuccessProbe(), "github.com/ankorstore/yokai/fxhealthcheck/testdata/probes.SuccessProbe"},
22+
{probes.NewFailureProbe(), "github.com/ankorstore/yokai/fxhealthcheck/testdata/probes.FailureProbe"},
2223
}
2324

2425
for _, tt := range tests {
@@ -40,6 +41,7 @@ func TestGetReturnType(t *testing.T) {
4041
target any
4142
expected string
4243
}{
44+
{nil, ""},
4345
{func() string { return "test" }, "string"},
4446
{func() int { return 123 }, "int"},
4547
}

fxhealthcheck/registry_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ func TestResolveCheckerProbesRegistrationsSuccess(t *testing.T) {
3030
probes.NewFailureProbe(),
3131
},
3232
Definitions: []fxhealthcheck.CheckerProbeDefinition{
33-
fxhealthcheck.NewCheckerProbeDefinition("*probes.SuccessProbe", healthcheck.Liveness),
34-
fxhealthcheck.NewCheckerProbeDefinition("*probes.FailureProbe", healthcheck.Readiness),
33+
fxhealthcheck.NewCheckerProbeDefinition("github.com/ankorstore/yokai/fxhealthcheck/testdata/probes.SuccessProbe", healthcheck.Liveness),
34+
fxhealthcheck.NewCheckerProbeDefinition("github.com/ankorstore/yokai/fxhealthcheck/testdata/probes.FailureProbe", healthcheck.Readiness),
3535
},
3636
}
3737

0 commit comments

Comments
 (0)