588 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			588 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package hooks
 | ||
| 
 | ||
| import (
 | ||
| 	"context"
 | ||
| 	"fmt"
 | ||
| 	"reflect"
 | ||
| 	"sort"
 | ||
| 	"sync"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	"go.uber.org/zap"
 | ||
| )
 | ||
| 
 | ||
| // HookPriority 钩子优先级
 | ||
| type HookPriority int
 | ||
| 
 | ||
| const (
 | ||
| 	// PriorityLowest 最低优先级
 | ||
| 	PriorityLowest HookPriority = 0
 | ||
| 	// PriorityLow 低优先级
 | ||
| 	PriorityLow HookPriority = 25
 | ||
| 	// PriorityNormal 普通优先级
 | ||
| 	PriorityNormal HookPriority = 50
 | ||
| 	// PriorityHigh 高优先级
 | ||
| 	PriorityHigh HookPriority = 75
 | ||
| 	// PriorityHighest 最高优先级
 | ||
| 	PriorityHighest HookPriority = 100
 | ||
| )
 | ||
| 
 | ||
| // HookFunc 钩子函数类型
 | ||
| type HookFunc func(ctx context.Context, data interface{}) error
 | ||
| 
 | ||
| // Hook 钩子定义
 | ||
| type Hook struct {
 | ||
| 	Name     string
 | ||
| 	Func     HookFunc
 | ||
| 	Priority HookPriority
 | ||
| 	Async    bool
 | ||
| 	Timeout  time.Duration
 | ||
| }
 | ||
| 
 | ||
| // HookResult 钩子执行结果
 | ||
| type HookResult struct {
 | ||
| 	HookName string        `json:"hook_name"`
 | ||
| 	Success  bool          `json:"success"`
 | ||
| 	Duration time.Duration `json:"duration"`
 | ||
| 	Error    string        `json:"error,omitempty"`
 | ||
| }
 | ||
| 
 | ||
| // HookConfig 钩子配置
 | ||
| type HookConfig struct {
 | ||
| 	// 默认超时时间
 | ||
| 	DefaultTimeout time.Duration
 | ||
| 	// 是否记录执行时间
 | ||
| 	TrackDuration bool
 | ||
| 	// 错误处理策略
 | ||
| 	ErrorStrategy ErrorStrategy
 | ||
| }
 | ||
| 
 | ||
| // ErrorStrategy 错误处理策略
 | ||
| type ErrorStrategy int
 | ||
| 
 | ||
| const (
 | ||
| 	// ContinueOnError 遇到错误继续执行
 | ||
| 	ContinueOnError ErrorStrategy = iota
 | ||
| 	// StopOnError 遇到错误停止执行
 | ||
| 	StopOnError
 | ||
| 	// CollectErrors 收集所有错误
 | ||
| 	CollectErrors
 | ||
| )
 | ||
| 
 | ||
| // DefaultHookConfig 默认钩子配置
 | ||
| func DefaultHookConfig() HookConfig {
 | ||
| 	return HookConfig{
 | ||
| 		DefaultTimeout: 30 * time.Second,
 | ||
| 		TrackDuration:  true,
 | ||
| 		ErrorStrategy:  ContinueOnError,
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // HookSystem 钩子系统
 | ||
| type HookSystem struct {
 | ||
| 	hooks  map[string][]*Hook
 | ||
| 	config HookConfig
 | ||
| 	logger *zap.Logger
 | ||
| 	mutex  sync.RWMutex
 | ||
| 	stats  map[string]*HookStats
 | ||
| }
 | ||
| 
 | ||
| // HookStats 钩子统计
 | ||
| type HookStats struct {
 | ||
| 	TotalExecutions int           `json:"total_executions"`
 | ||
| 	Successes       int           `json:"successes"`
 | ||
| 	Failures        int           `json:"failures"`
 | ||
| 	TotalDuration   time.Duration `json:"total_duration"`
 | ||
| 	AverageDuration time.Duration `json:"average_duration"`
 | ||
| 	LastExecution   time.Time     `json:"last_execution"`
 | ||
| 	LastError       string        `json:"last_error,omitempty"`
 | ||
| }
 | ||
| 
 | ||
| // NewHookSystem 创建钩子系统
 | ||
| func NewHookSystem(config HookConfig, logger *zap.Logger) *HookSystem {
 | ||
| 	return &HookSystem{
 | ||
| 		hooks:  make(map[string][]*Hook),
 | ||
| 		config: config,
 | ||
| 		logger: logger,
 | ||
| 		stats:  make(map[string]*HookStats),
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // Register 注册钩子
 | ||
| func (hs *HookSystem) Register(event string, hook *Hook) error {
 | ||
| 	if hook.Name == "" {
 | ||
| 		return fmt.Errorf("hook name cannot be empty")
 | ||
| 	}
 | ||
| 
 | ||
| 	if hook.Func == nil {
 | ||
| 		return fmt.Errorf("hook function cannot be nil")
 | ||
| 	}
 | ||
| 
 | ||
| 	if hook.Timeout == 0 {
 | ||
| 		hook.Timeout = hs.config.DefaultTimeout
 | ||
| 	}
 | ||
| 
 | ||
| 	hs.mutex.Lock()
 | ||
| 	defer hs.mutex.Unlock()
 | ||
| 
 | ||
| 	// 检查是否已经注册了同名钩子
 | ||
| 	for _, existingHook := range hs.hooks[event] {
 | ||
| 		if existingHook.Name == hook.Name {
 | ||
| 			return fmt.Errorf("hook %s already registered for event %s", hook.Name, event)
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	hs.hooks[event] = append(hs.hooks[event], hook)
 | ||
| 
 | ||
| 	// 按优先级排序
 | ||
| 	sort.Slice(hs.hooks[event], func(i, j int) bool {
 | ||
| 		return hs.hooks[event][i].Priority > hs.hooks[event][j].Priority
 | ||
| 	})
 | ||
| 
 | ||
| 	// 初始化统计
 | ||
| 	hookKey := fmt.Sprintf("%s.%s", event, hook.Name)
 | ||
| 	hs.stats[hookKey] = &HookStats{}
 | ||
| 
 | ||
| 	hs.logger.Info("Registered hook",
 | ||
| 		zap.String("event", event),
 | ||
| 		zap.String("hook_name", hook.Name),
 | ||
| 		zap.Int("priority", int(hook.Priority)),
 | ||
| 		zap.Bool("async", hook.Async))
 | ||
| 
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // RegisterFunc 注册钩子函数(简化版)
 | ||
| func (hs *HookSystem) RegisterFunc(event, name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	hook := &Hook{
 | ||
| 		Name:     name,
 | ||
| 		Func:     fn,
 | ||
| 		Priority: priority,
 | ||
| 		Async:    false,
 | ||
| 		Timeout:  hs.config.DefaultTimeout,
 | ||
| 	}
 | ||
| 
 | ||
| 	return hs.Register(event, hook)
 | ||
| }
 | ||
| 
 | ||
| // RegisterAsyncFunc 注册异步钩子函数
 | ||
| func (hs *HookSystem) RegisterAsyncFunc(event, name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	hook := &Hook{
 | ||
| 		Name:     name,
 | ||
| 		Func:     fn,
 | ||
| 		Priority: priority,
 | ||
| 		Async:    true,
 | ||
| 		Timeout:  hs.config.DefaultTimeout,
 | ||
| 	}
 | ||
| 
 | ||
| 	return hs.Register(event, hook)
 | ||
| }
 | ||
| 
 | ||
| // Unregister 取消注册钩子
 | ||
| func (hs *HookSystem) Unregister(event, hookName string) error {
 | ||
| 	hs.mutex.Lock()
 | ||
| 	defer hs.mutex.Unlock()
 | ||
| 
 | ||
| 	hooks := hs.hooks[event]
 | ||
| 	for i, hook := range hooks {
 | ||
| 		if hook.Name == hookName {
 | ||
| 			// 删除钩子
 | ||
| 			hs.hooks[event] = append(hooks[:i], hooks[i+1:]...)
 | ||
| 
 | ||
| 			// 删除统计
 | ||
| 			hookKey := fmt.Sprintf("%s.%s", event, hookName)
 | ||
| 			delete(hs.stats, hookKey)
 | ||
| 
 | ||
| 			hs.logger.Info("Unregistered hook",
 | ||
| 				zap.String("event", event),
 | ||
| 				zap.String("hook_name", hookName))
 | ||
| 
 | ||
| 			return nil
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	return fmt.Errorf("hook %s not found for event %s", hookName, event)
 | ||
| }
 | ||
| 
 | ||
| // Trigger 触发事件
 | ||
| func (hs *HookSystem) Trigger(ctx context.Context, event string, data interface{}) ([]HookResult, error) {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	hooks := make([]*Hook, len(hs.hooks[event]))
 | ||
| 	copy(hooks, hs.hooks[event])
 | ||
| 	hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	if len(hooks) == 0 {
 | ||
| 		hs.logger.Debug("No hooks registered for event", zap.String("event", event))
 | ||
| 		return nil, nil
 | ||
| 	}
 | ||
| 
 | ||
| 	hs.logger.Debug("Triggering event",
 | ||
| 		zap.String("event", event),
 | ||
| 		zap.Int("hook_count", len(hooks)))
 | ||
| 
 | ||
| 	results := make([]HookResult, 0, len(hooks))
 | ||
| 	var errors []error
 | ||
| 
 | ||
| 	for _, hook := range hooks {
 | ||
| 		result := hs.executeHook(ctx, event, hook, data)
 | ||
| 		results = append(results, result)
 | ||
| 
 | ||
| 		if !result.Success {
 | ||
| 			err := fmt.Errorf("hook %s failed: %s", hook.Name, result.Error)
 | ||
| 			errors = append(errors, err)
 | ||
| 
 | ||
| 			// 根据错误策略决定是否继续
 | ||
| 			if hs.config.ErrorStrategy == StopOnError {
 | ||
| 				break
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	// 处理错误
 | ||
| 	if len(errors) > 0 {
 | ||
| 		switch hs.config.ErrorStrategy {
 | ||
| 		case StopOnError:
 | ||
| 			return results, errors[0]
 | ||
| 		case CollectErrors:
 | ||
| 			return results, fmt.Errorf("multiple hook errors: %v", errors)
 | ||
| 		case ContinueOnError:
 | ||
| 			// 继续执行,但记录错误
 | ||
| 			hs.logger.Warn("Some hooks failed but continuing execution",
 | ||
| 				zap.String("event", event),
 | ||
| 				zap.Int("error_count", len(errors)))
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	return results, nil
 | ||
| }
 | ||
| 
 | ||
| // executeHook 执行单个钩子
 | ||
| func (hs *HookSystem) executeHook(ctx context.Context, event string, hook *Hook, data interface{}) HookResult {
 | ||
| 	hookKey := fmt.Sprintf("%s.%s", event, hook.Name)
 | ||
| 	start := time.Now()
 | ||
| 
 | ||
| 	result := HookResult{
 | ||
| 		HookName: hook.Name,
 | ||
| 		Success:  false,
 | ||
| 	}
 | ||
| 
 | ||
| 	// 更新统计
 | ||
| 	defer func() {
 | ||
| 		result.Duration = time.Since(start)
 | ||
| 		hs.updateStats(hookKey, result)
 | ||
| 	}()
 | ||
| 
 | ||
| 	if hook.Async {
 | ||
| 		// 异步执行
 | ||
| 		go func() {
 | ||
| 			hs.doExecuteHook(ctx, hook, data)
 | ||
| 		}()
 | ||
| 		result.Success = true // 异步执行总是认为成功
 | ||
| 		return result
 | ||
| 	}
 | ||
| 
 | ||
| 	// 同步执行
 | ||
| 	err := hs.doExecuteHook(ctx, hook, data)
 | ||
| 	if err != nil {
 | ||
| 		result.Error = err.Error()
 | ||
| 		hs.logger.Error("Hook execution failed",
 | ||
| 			zap.String("event", event),
 | ||
| 			zap.String("hook_name", hook.Name),
 | ||
| 			zap.Error(err))
 | ||
| 	} else {
 | ||
| 		result.Success = true
 | ||
| 		hs.logger.Debug("Hook executed successfully",
 | ||
| 			zap.String("event", event),
 | ||
| 			zap.String("hook_name", hook.Name))
 | ||
| 	}
 | ||
| 
 | ||
| 	return result
 | ||
| }
 | ||
| 
 | ||
| // doExecuteHook 实际执行钩子
 | ||
| func (hs *HookSystem) doExecuteHook(ctx context.Context, hook *Hook, data interface{}) error {
 | ||
| 	// 设置超时上下文
 | ||
| 	hookCtx, cancel := context.WithTimeout(ctx, hook.Timeout)
 | ||
| 	defer cancel()
 | ||
| 
 | ||
| 	// 在goroutine中执行,以便处理超时
 | ||
| 	errChan := make(chan error, 1)
 | ||
| 	go func() {
 | ||
| 		defer func() {
 | ||
| 			if r := recover(); r != nil {
 | ||
| 				errChan <- fmt.Errorf("hook panicked: %v", r)
 | ||
| 			}
 | ||
| 		}()
 | ||
| 
 | ||
| 		errChan <- hook.Func(hookCtx, data)
 | ||
| 	}()
 | ||
| 
 | ||
| 	select {
 | ||
| 	case err := <-errChan:
 | ||
| 		return err
 | ||
| 	case <-hookCtx.Done():
 | ||
| 		return fmt.Errorf("hook execution timeout after %v", hook.Timeout)
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // updateStats 更新统计信息
 | ||
| func (hs *HookSystem) updateStats(hookKey string, result HookResult) {
 | ||
| 	hs.mutex.Lock()
 | ||
| 	defer hs.mutex.Unlock()
 | ||
| 
 | ||
| 	stats, exists := hs.stats[hookKey]
 | ||
| 	if !exists {
 | ||
| 		stats = &HookStats{}
 | ||
| 		hs.stats[hookKey] = stats
 | ||
| 	}
 | ||
| 
 | ||
| 	stats.TotalExecutions++
 | ||
| 	stats.LastExecution = time.Now()
 | ||
| 
 | ||
| 	if result.Success {
 | ||
| 		stats.Successes++
 | ||
| 	} else {
 | ||
| 		stats.Failures++
 | ||
| 		stats.LastError = result.Error
 | ||
| 	}
 | ||
| 
 | ||
| 	if hs.config.TrackDuration {
 | ||
| 		stats.TotalDuration += result.Duration
 | ||
| 		stats.AverageDuration = stats.TotalDuration / time.Duration(stats.TotalExecutions)
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // GetHooks 获取事件的所有钩子
 | ||
| func (hs *HookSystem) GetHooks(event string) []*Hook {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	defer hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	hooks := make([]*Hook, len(hs.hooks[event]))
 | ||
| 	copy(hooks, hs.hooks[event])
 | ||
| 	return hooks
 | ||
| }
 | ||
| 
 | ||
| // GetEvents 获取所有注册的事件
 | ||
| func (hs *HookSystem) GetEvents() []string {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	defer hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	events := make([]string, 0, len(hs.hooks))
 | ||
| 	for event := range hs.hooks {
 | ||
| 		events = append(events, event)
 | ||
| 	}
 | ||
| 
 | ||
| 	sort.Strings(events)
 | ||
| 	return events
 | ||
| }
 | ||
| 
 | ||
| // GetStats 获取钩子统计信息
 | ||
| func (hs *HookSystem) GetStats() map[string]*HookStats {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	defer hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	stats := make(map[string]*HookStats)
 | ||
| 	for key, stat := range hs.stats {
 | ||
| 		statCopy := *stat
 | ||
| 		stats[key] = &statCopy
 | ||
| 	}
 | ||
| 
 | ||
| 	return stats
 | ||
| }
 | ||
| 
 | ||
| // GetEventStats 获取特定事件的统计信息
 | ||
| func (hs *HookSystem) GetEventStats(event string) map[string]*HookStats {
 | ||
| 	allStats := hs.GetStats()
 | ||
| 	eventStats := make(map[string]*HookStats)
 | ||
| 
 | ||
| 	prefix := event + "."
 | ||
| 	for key, stat := range allStats {
 | ||
| 		if len(key) > len(prefix) && key[:len(prefix)] == prefix {
 | ||
| 			hookName := key[len(prefix):]
 | ||
| 			eventStats[hookName] = stat
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	return eventStats
 | ||
| }
 | ||
| 
 | ||
| // Clear 清除所有钩子
 | ||
| func (hs *HookSystem) Clear() {
 | ||
| 	hs.mutex.Lock()
 | ||
| 	defer hs.mutex.Unlock()
 | ||
| 
 | ||
| 	hs.hooks = make(map[string][]*Hook)
 | ||
| 	hs.stats = make(map[string]*HookStats)
 | ||
| 
 | ||
| 	hs.logger.Info("Cleared all hooks")
 | ||
| }
 | ||
| 
 | ||
| // ClearEvent 清除特定事件的所有钩子
 | ||
| func (hs *HookSystem) ClearEvent(event string) {
 | ||
| 	hs.mutex.Lock()
 | ||
| 	defer hs.mutex.Unlock()
 | ||
| 
 | ||
| 	// 删除钩子
 | ||
| 	delete(hs.hooks, event)
 | ||
| 
 | ||
| 	// 删除统计
 | ||
| 	prefix := event + "."
 | ||
| 	for key := range hs.stats {
 | ||
| 		if len(key) > len(prefix) && key[:len(prefix)] == prefix {
 | ||
| 			delete(hs.stats, key)
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	hs.logger.Info("Cleared hooks for event", zap.String("event", event))
 | ||
| }
 | ||
| 
 | ||
| // Count 获取钩子总数
 | ||
| func (hs *HookSystem) Count() int {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	defer hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	total := 0
 | ||
| 	for _, hooks := range hs.hooks {
 | ||
| 		total += len(hooks)
 | ||
| 	}
 | ||
| 
 | ||
| 	return total
 | ||
| }
 | ||
| 
 | ||
| // EventCount 获取特定事件的钩子数量
 | ||
| func (hs *HookSystem) EventCount(event string) int {
 | ||
| 	hs.mutex.RLock()
 | ||
| 	defer hs.mutex.RUnlock()
 | ||
| 
 | ||
| 	return len(hs.hooks[event])
 | ||
| }
 | ||
| 
 | ||
| // 实现Service接口
 | ||
| 
 | ||
| // Name 返回服务名称
 | ||
| func (hs *HookSystem) Name() string {
 | ||
| 	return "hook-system"
 | ||
| }
 | ||
| 
 | ||
| // Initialize 初始化钩子系统
 | ||
| func (hs *HookSystem) Initialize(ctx context.Context) error {
 | ||
| 	hs.logger.Info("Hook system initialized")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // Start 启动钩子系统
 | ||
| func (hs *HookSystem) Start(ctx context.Context) error {
 | ||
| 	hs.logger.Info("Hook system started")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // HealthCheck 健康检查
 | ||
| func (hs *HookSystem) HealthCheck(ctx context.Context) error {
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // Shutdown 关闭钩子系统
 | ||
| func (hs *HookSystem) Shutdown(ctx context.Context) error {
 | ||
| 	hs.logger.Info("Hook system shutdown")
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // 便捷方法
 | ||
| 
 | ||
| // OnUserCreated 用户创建事件钩子
 | ||
| func (hs *HookSystem) OnUserCreated(name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	return hs.RegisterFunc("user.created", name, priority, fn)
 | ||
| }
 | ||
| 
 | ||
| // OnUserUpdated 用户更新事件钩子
 | ||
| func (hs *HookSystem) OnUserUpdated(name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	return hs.RegisterFunc("user.updated", name, priority, fn)
 | ||
| }
 | ||
| 
 | ||
| // OnUserDeleted 用户删除事件钩子
 | ||
| func (hs *HookSystem) OnUserDeleted(name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	return hs.RegisterFunc("user.deleted", name, priority, fn)
 | ||
| }
 | ||
| 
 | ||
| // OnOrderCreated 订单创建事件钩子
 | ||
| func (hs *HookSystem) OnOrderCreated(name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	return hs.RegisterFunc("order.created", name, priority, fn)
 | ||
| }
 | ||
| 
 | ||
| // OnOrderCompleted 订单完成事件钩子
 | ||
| func (hs *HookSystem) OnOrderCompleted(name string, priority HookPriority, fn HookFunc) error {
 | ||
| 	return hs.RegisterFunc("order.completed", name, priority, fn)
 | ||
| }
 | ||
| 
 | ||
| // TriggerUserCreated 触发用户创建事件
 | ||
| func (hs *HookSystem) TriggerUserCreated(ctx context.Context, user interface{}) ([]HookResult, error) {
 | ||
| 	return hs.Trigger(ctx, "user.created", user)
 | ||
| }
 | ||
| 
 | ||
| // TriggerUserUpdated 触发用户更新事件
 | ||
| func (hs *HookSystem) TriggerUserUpdated(ctx context.Context, user interface{}) ([]HookResult, error) {
 | ||
| 	return hs.Trigger(ctx, "user.updated", user)
 | ||
| }
 | ||
| 
 | ||
| // TriggerUserDeleted 触发用户删除事件
 | ||
| func (hs *HookSystem) TriggerUserDeleted(ctx context.Context, user interface{}) ([]HookResult, error) {
 | ||
| 	return hs.Trigger(ctx, "user.deleted", user)
 | ||
| }
 | ||
| 
 | ||
| // HookBuilder 钩子构建器
 | ||
| type HookBuilder struct {
 | ||
| 	hook *Hook
 | ||
| }
 | ||
| 
 | ||
| // NewHookBuilder 创建钩子构建器
 | ||
| func NewHookBuilder(name string, fn HookFunc) *HookBuilder {
 | ||
| 	return &HookBuilder{
 | ||
| 		hook: &Hook{
 | ||
| 			Name:     name,
 | ||
| 			Func:     fn,
 | ||
| 			Priority: PriorityNormal,
 | ||
| 			Async:    false,
 | ||
| 			Timeout:  30 * time.Second,
 | ||
| 		},
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // WithPriority 设置优先级
 | ||
| func (hb *HookBuilder) WithPriority(priority HookPriority) *HookBuilder {
 | ||
| 	hb.hook.Priority = priority
 | ||
| 	return hb
 | ||
| }
 | ||
| 
 | ||
| // WithTimeout 设置超时时间
 | ||
| func (hb *HookBuilder) WithTimeout(timeout time.Duration) *HookBuilder {
 | ||
| 	hb.hook.Timeout = timeout
 | ||
| 	return hb
 | ||
| }
 | ||
| 
 | ||
| // Async 设置为异步执行
 | ||
| func (hb *HookBuilder) Async() *HookBuilder {
 | ||
| 	hb.hook.Async = true
 | ||
| 	return hb
 | ||
| }
 | ||
| 
 | ||
| // Build 构建钩子
 | ||
| func (hb *HookBuilder) Build() *Hook {
 | ||
| 	return hb.hook
 | ||
| }
 | ||
| 
 | ||
| // TypedHookFunc 类型化钩子函数
 | ||
| type TypedHookFunc[T any] func(ctx context.Context, data T) error
 | ||
| 
 | ||
| // RegisterTypedFunc 注册类型化钩子函数
 | ||
| func RegisterTypedFunc[T any](hs *HookSystem, event, name string, priority HookPriority, fn TypedHookFunc[T]) error {
 | ||
| 	hookFunc := func(ctx context.Context, data interface{}) error {
 | ||
| 		typedData, ok := data.(T)
 | ||
| 		if !ok {
 | ||
| 			return fmt.Errorf("invalid data type for hook %s, expected %s", name, reflect.TypeOf((*T)(nil)).Elem().Name())
 | ||
| 		}
 | ||
| 		return fn(ctx, typedData)
 | ||
| 	}
 | ||
| 
 | ||
| 	return hs.RegisterFunc(event, name, priority, hookFunc)
 | ||
| }
 |