fix: sync typed-nil dependency validation
This commit is contained in:
parent
401a8f148e
commit
6e49d83fee
4 changed files with 111 additions and 1 deletions
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -234,6 +235,7 @@ type authUserCacheEntry struct {
|
|||
|
||||
// New 创建 Router,由各业务域自行注册其 RPC handler(registerHelp/Auth/Users/Updates)。
|
||||
func New(cfg Config, deps Deps, log *zap.Logger, clk clock.Clock) *Router {
|
||||
assertNoTypedNilDeps(deps)
|
||||
instanceID := cfg.InstanceID
|
||||
if instanceID == "" {
|
||||
instanceID = fmt.Sprintf("%016x", randomNonZeroInt64())
|
||||
|
|
@ -282,6 +284,31 @@ func New(cfg Config, deps Deps, log *zap.Logger, clk clock.Clock) *Router {
|
|||
return r
|
||||
}
|
||||
|
||||
// assertNoTypedNilDeps rejects partially constructed optional dependencies at
|
||||
// the composition boundary. A Go interface containing a nil concrete pointer
|
||||
// is not equal to nil, so handler-level availability checks would otherwise
|
||||
// admit it and panic only when the first method is invoked.
|
||||
//
|
||||
// This is an invariant check, not a compatibility fallback: callers must
|
||||
// either inject a fully constructed implementation or leave the interface nil.
|
||||
func assertNoTypedNilDeps(deps Deps) {
|
||||
value := reflect.ValueOf(deps)
|
||||
typeOfDeps := value.Type()
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
field := value.Field(i)
|
||||
if field.Kind() != reflect.Interface || field.IsNil() {
|
||||
continue
|
||||
}
|
||||
implementation := field.Elem()
|
||||
switch implementation.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Pointer, reflect.Slice:
|
||||
if implementation.IsNil() {
|
||||
panic(fmt.Sprintf("rpc: dependency %s is a typed nil %s", typeOfDeps.Field(i).Name, implementation.Type()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func registerRPC[T bin.Object](d *tlprofile.Dispatcher, method tlprofile.SemanticID, handler func(context.Context, T) (any, error)) {
|
||||
if d == nil || handler == nil {
|
||||
panic("rpc: register nil canonical RPC handler or dispatcher")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue