@@ -29,6 +29,8 @@ import { botNames, botOpenIds } from "./monitor.state.js";
2929import { monitorWebhook , monitorWebSocket } from "./monitor.transport.js" ;
3030import { getFeishuRuntime } from "./runtime.js" ;
3131import { getMessageFeishu } from "./send.js" ;
32+ import { getFeishuSequentialKey } from "./sequential-key.js" ;
33+ import { createSequentialQueue } from "./sequential-queue.js" ;
3234import { createFeishuThreadBindingManager } from "./thread-bindings.js" ;
3335import type { FeishuChatType , ResolvedFeishuAccount } from "./types.js" ;
3436
@@ -290,25 +292,6 @@ function parseFeishuCardActionEventPayload(value: unknown): FeishuCardActionEven
290292 } ;
291293}
292294
293- /**
294- * Per-chat serial queue that ensures messages from the same chat are processed
295- * in arrival order while allowing different chats to run concurrently.
296- */
297- function createChatQueue ( ) {
298- const queues = new Map < string , Promise < void > > ( ) ;
299- return ( chatId : string , task : ( ) => Promise < void > ) : Promise < void > => {
300- const prev = queues . get ( chatId ) ?? Promise . resolve ( ) ;
301- const next = prev . then ( task , task ) ;
302- queues . set ( chatId , next ) ;
303- void next . finally ( ( ) => {
304- if ( queues . get ( chatId ) === next ) {
305- queues . delete ( chatId ) ;
306- }
307- } ) ;
308- return next ;
309- } ;
310- }
311-
312295function mergeFeishuDebounceMentions (
313296 entries : FeishuMessageEvent [ ] ,
314297) : FeishuMessageEvent [ "message" ] [ "mentions" ] | undefined {
@@ -395,7 +378,9 @@ function registerEventHandlers(
395378 } ) ;
396379 const log = runtime ?. log ?? console . log ;
397380 const error = runtime ?. error ?? console . error ;
398- const enqueue = createChatQueue ( ) ;
381+ // Keep normal Feishu traffic FIFO per chat while allowing explicit out-of-band
382+ // commands like /btw and /stop to bypass the busy main-chat lane.
383+ const enqueue = createSequentialQueue ( ) ;
399384 const runFeishuHandler = async ( params : { task : ( ) => Promise < void > ; errorMessage : string } ) => {
400385 if ( fireAndForget ) {
401386 void params . task ( ) . catch ( ( err ) => {
@@ -410,7 +395,12 @@ function registerEventHandlers(
410395 }
411396 } ;
412397 const dispatchFeishuMessage = async ( event : FeishuMessageEvent ) => {
413- const chatId = event . message . chat_id ?. trim ( ) || "unknown" ;
398+ const sequentialKey = getFeishuSequentialKey ( {
399+ accountId,
400+ event,
401+ botOpenId : botOpenIds . get ( accountId ) ,
402+ botName : botNames . get ( accountId ) ,
403+ } ) ;
414404 const task = ( ) =>
415405 handleFeishuMessage ( {
416406 cfg,
@@ -422,7 +412,7 @@ function registerEventHandlers(
422412 accountId,
423413 processingClaimHeld : true ,
424414 } ) ;
425- await enqueue ( chatId , task ) ;
415+ await enqueue ( sequentialKey , task ) ;
426416 } ;
427417 const resolveSenderDebounceId = ( event : FeishuMessageEvent ) : string | undefined => {
428418 const senderId =
0 commit comments