adc521f94d
第 4 层 Dispatcher 经 NATS request-reply + 队列组同步调用第 5 层 MCP 工具, 工具不可用/超时即降级,不阻断主流程。 - shared/contract: ToolCall/ToolResult + sundynix.tools.go.* subject 约定 + ToolSubjectGo/Py - shared/bus: CallTool(发起) / ServeTool(队列组订阅+应答) - mcp-go: 接共享 bus,gateway 通配订阅按工具名分发(wiki_search/echo),main 优雅退出 - dispatcher: ToolCaller 接口 + Orchestrator.retrieveContext(调 wiki_search,超时3s降级) - e2e: TestToolCallRoundTrip(PASS);demo.sh 加 mcp-go(就绪门避免启动竞态),live 跑通 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
62 lines
1.9 KiB
Go
62 lines
1.9 KiB
Go
// Package nats 是调度器对共享 bus 的薄封装(消费任务 / 回写 Token)。
|
||
package nats
|
||
|
||
import (
|
||
"context"
|
||
"log"
|
||
|
||
sharedbus "github.com/sundynix/sundynix-shared/bus"
|
||
"github.com/sundynix/sundynix-shared/contract"
|
||
)
|
||
|
||
// TaskHandler 处理单个任务。
|
||
type TaskHandler func(ctx context.Context, t *contract.Task) error
|
||
|
||
// Subscriber 包装共享 bus,向调度器暴露消费能力。
|
||
type Subscriber struct {
|
||
inner *sharedbus.Bus
|
||
}
|
||
|
||
// MustConnect 接入 NATS 并确保任务流存在(消费者声明在 Consume 时完成)。
|
||
func MustConnect(url string) *Subscriber {
|
||
inner, err := sharedbus.Connect(url)
|
||
if err != nil {
|
||
log.Fatalf("[dispatcher/nats] connect: %v", err)
|
||
}
|
||
if err := inner.EnsureTaskStream(context.Background()); err != nil {
|
||
log.Fatalf("[dispatcher/nats] ensure stream: %v", err)
|
||
}
|
||
log.Printf("[dispatcher/nats] connected %s", url)
|
||
return &Subscriber{inner: inner}
|
||
}
|
||
|
||
// ConsumeTasks 从 sundynix.tasks.* 持续消费任务(队列组负载均衡),阻塞至 ctx 取消。
|
||
func (s *Subscriber) ConsumeTasks(ctx context.Context, h TaskHandler) error {
|
||
stop, err := s.inner.ConsumeTasks(ctx, func(c context.Context, t *contract.Task) error {
|
||
return h(c, t)
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer stop()
|
||
<-ctx.Done()
|
||
return ctx.Err()
|
||
}
|
||
|
||
// PublishToken / CompleteStream 让 Subscriber 满足 eino.TokenSink,
|
||
// 把推理 Token 回流到 sundynix.streams.<taskID>。
|
||
func (s *Subscriber) PublishToken(taskID string, token []byte) error {
|
||
return s.inner.PublishToken(taskID, token)
|
||
}
|
||
|
||
func (s *Subscriber) CompleteStream(taskID string) error {
|
||
return s.inner.CompleteStream(taskID)
|
||
}
|
||
|
||
// CallTool 让 Subscriber 满足 eino.ToolCaller,经 NATS request-reply 调起第 5 层 MCP 工具。
|
||
func (s *Subscriber) CallTool(ctx context.Context, subject string, call *contract.ToolCall) (*contract.ToolResult, error) {
|
||
return s.inner.CallTool(ctx, subject, call)
|
||
}
|
||
|
||
func (s *Subscriber) Close() { s.inner.Close() }
|