1515 * limitations under the License.
1616 */
1717
18- package com .nageoffer .ai .ragent .rag . service . handler ;
18+ package com .nageoffer .ai .ragent .framework . web ;
1919
2020import cn .hutool .core .util .StrUtil ;
2121import com .google .common .cache .Cache ;
2222import com .google .common .cache .CacheBuilder ;
23- import com .nageoffer .ai .ragent .rag .enums .SSEEventType ;
24- import com .nageoffer .ai .ragent .rag .dto .CompletionPayload ;
25- import com .nageoffer .ai .ragent .framework .web .SseEmitterSender ;
26- import com .nageoffer .ai .ragent .infra .chat .StreamCancellationHandle ;
2723import jakarta .annotation .PostConstruct ;
2824import jakarta .annotation .PreDestroy ;
2925import lombok .SneakyThrows ;
3531
3632import java .time .Duration ;
3733import java .util .concurrent .atomic .AtomicBoolean ;
38- import java .util .function .Supplier ;
3934
35+ /**
36+ * 流式任务跨节点取消管理器
37+ * <p>
38+ * 机制层与引擎无关:注册表 + Redis 标记 + 广播主题构成统一的取消协议,
39+ * 各引擎的个性化收尾动作(补发事件、中断上游流等)以回调形式注入
40+ */
4041@ Slf4j
4142@ Component
4243public class StreamTaskManager {
@@ -76,22 +77,26 @@ public void unsubscribe() {
7677 redissonClient .getTopic (CANCEL_TOPIC ).removeListener (listenerId );
7778 }
7879
79- public void register (String taskId , SseEmitterSender sender , Supplier <CompletionPayload > onCancelSupplier ) {
80+ /**
81+ * 注册取消收尾回调,负责补发终止事件并结束响应流
82+ * 若任务已被其他节点标记取消,回调立即执行
83+ */
84+ public void register (String taskId , Runnable onCancelFinalizer ) {
8085 StreamTaskInfo taskInfo = getOrCreate (taskId );
81- taskInfo .sender = sender ;
82- taskInfo .onCancelSupplier = onCancelSupplier ;
86+ taskInfo .finalizer = onCancelFinalizer ;
8387 if (isTaskCancelledInRedis (taskId , taskInfo )) {
84- CompletionPayload payload = taskInfo .onCancelSupplier .get ();
85- sendCancelAndDone (sender , payload );
86- sender .complete ();
88+ onCancelFinalizer .run ();
8789 }
8890 }
8991
90- public void bindHandle (String taskId , StreamCancellationHandle handle ) {
92+ /**
93+ * 绑定上游流的中断动作,取消时先于收尾回调执行
94+ */
95+ public void bindHandle (String taskId , Runnable cancelAction ) {
9196 StreamTaskInfo taskInfo = getOrCreate (taskId );
92- taskInfo .handle = handle ;
93- if (taskInfo .cancelled .get () && handle != null ) {
94- handle . cancel ();
97+ taskInfo .cancelAction = cancelAction ;
98+ if (taskInfo .cancelled .get () && cancelAction != null ) {
99+ cancelAction . run ();
95100 }
96101 }
97102
@@ -139,15 +144,13 @@ private void cancelLocal(String taskId) {
139144 return ;
140145 }
141146
142- if (taskInfo .handle != null ) {
143- taskInfo .handle . cancel ();
147+ if (taskInfo .cancelAction != null ) {
148+ taskInfo .cancelAction . run ();
144149 }
145150
146- // 在取消时执行回调,保存已累积的内容
147- if (taskInfo .sender != null ) {
148- CompletionPayload payload = taskInfo .onCancelSupplier .get ();
149- sendCancelAndDone (taskInfo .sender , payload );
150- taskInfo .sender .complete ();
151+ // 在取消时执行收尾回调,保存已累积的内容
152+ if (taskInfo .finalizer != null ) {
153+ taskInfo .finalizer .run ();
151154 }
152155 }
153156
@@ -163,21 +166,14 @@ private String cancelKey(String taskId) {
163166 return CANCEL_KEY_PREFIX + taskId ;
164167 }
165168
166- private void sendCancelAndDone (SseEmitterSender sender , CompletionPayload payload ) {
167- CompletionPayload actualPayload = payload == null ? new CompletionPayload (null , null ) : payload ;
168- sender .sendEvent (SSEEventType .CANCEL .value (), actualPayload );
169- sender .sendEvent (SSEEventType .DONE .value (), "[DONE]" );
170- }
171-
172169 @ SneakyThrows
173170 private StreamTaskInfo getOrCreate (String taskId ) {
174171 return tasks .get (taskId , StreamTaskInfo ::new );
175172 }
176173
177174 private static final class StreamTaskInfo {
178175 private final AtomicBoolean cancelled = new AtomicBoolean (false );
179- private volatile StreamCancellationHandle handle ;
180- private volatile SseEmitterSender sender ;
181- private volatile Supplier <CompletionPayload > onCancelSupplier ;
176+ private volatile Runnable cancelAction ;
177+ private volatile Runnable finalizer ;
182178 }
183179}
0 commit comments