@@ -34,6 +34,7 @@ interface OperationQueueState {
3434
3535const retryTimeouts = new Map < string , NodeJS . Timeout > ( )
3636const operationTimeouts = new Map < string , NodeJS . Timeout > ( )
37+ const subblockDebounceTimeouts = new Map < string , NodeJS . Timeout > ( )
3738
3839let emitWorkflowOperation :
3940 | ( ( operation : string , target : string , payload : any , operationId ?: string ) => void )
@@ -59,6 +60,54 @@ export const useOperationQueueStore = create<OperationQueueState>((set, get) =>
5960 hasOperationError : false ,
6061
6162 addToQueue : ( operation ) => {
63+ // Handle debouncing for subblock operations
64+ if (
65+ operation . operation . operation === 'subblock-update' &&
66+ operation . operation . target === 'subblock'
67+ ) {
68+ const { blockId, subblockId } = operation . operation . payload
69+ const debounceKey = `${ blockId } -${ subblockId } `
70+
71+ const existingTimeout = subblockDebounceTimeouts . get ( debounceKey )
72+ if ( existingTimeout ) {
73+ clearTimeout ( existingTimeout )
74+ }
75+
76+ set ( ( state ) => ( {
77+ operations : state . operations . filter (
78+ ( op ) =>
79+ ! (
80+ op . status === 'pending' &&
81+ op . operation . operation === 'subblock-update' &&
82+ op . operation . target === 'subblock' &&
83+ op . operation . payload ?. blockId === blockId &&
84+ op . operation . payload ?. subblockId === subblockId
85+ )
86+ ) ,
87+ } ) )
88+
89+ const timeoutId = setTimeout ( ( ) => {
90+ subblockDebounceTimeouts . delete ( debounceKey )
91+
92+ const queuedOp : QueuedOperation = {
93+ ...operation ,
94+ timestamp : Date . now ( ) ,
95+ retryCount : 0 ,
96+ status : 'pending' ,
97+ }
98+
99+ set ( ( state ) => ( {
100+ operations : [ ...state . operations , queuedOp ] ,
101+ } ) )
102+
103+ get ( ) . processNextOperation ( )
104+ } , 150 ) // 150ms debounce for subblock operations
105+
106+ subblockDebounceTimeouts . set ( debounceKey , timeoutId )
107+ return
108+ }
109+
110+ // Handle non-subblock operations (existing logic)
62111 const state = get ( )
63112
64113 // Check for duplicate operation ID
@@ -80,13 +129,8 @@ export const useOperationQueueStore = create<OperationQueueState>((set, get) =>
80129 // For block operations, check the block ID specifically
81130 ( ( operation . operation . target === 'block' &&
82131 op . operation . payload ?. id === operation . operation . payload ?. id ) ||
83- // For subblock operations, check blockId and subblockId
84- ( operation . operation . target === 'subblock' &&
85- op . operation . payload ?. blockId === operation . operation . payload ?. blockId &&
86- op . operation . payload ?. subblockId === operation . operation . payload ?. subblockId ) ||
87132 // For other operations, fall back to full payload comparison
88133 ( operation . operation . target !== 'block' &&
89- operation . operation . target !== 'subblock' &&
90134 JSON . stringify ( op . operation . payload ) === JSON . stringify ( operation . operation . payload ) ) )
91135 )
92136
@@ -127,6 +171,7 @@ export const useOperationQueueStore = create<OperationQueueState>((set, get) =>
127171
128172 confirmOperation : ( operationId ) => {
129173 const state = get ( )
174+ const operation = state . operations . find ( ( op ) => op . id === operationId )
130175 const newOperations = state . operations . filter ( ( op ) => op . id !== operationId )
131176
132177 const retryTimeout = retryTimeouts . get ( operationId )
@@ -141,6 +186,20 @@ export const useOperationQueueStore = create<OperationQueueState>((set, get) =>
141186 operationTimeouts . delete ( operationId )
142187 }
143188
189+ // Clean up any debounce timeouts for subblock operations
190+ if (
191+ operation ?. operation . operation === 'subblock-update' &&
192+ operation . operation . target === 'subblock'
193+ ) {
194+ const { blockId, subblockId } = operation . operation . payload
195+ const debounceKey = `${ blockId } -${ subblockId } `
196+ const debounceTimeout = subblockDebounceTimeouts . get ( debounceKey )
197+ if ( debounceTimeout ) {
198+ clearTimeout ( debounceTimeout )
199+ subblockDebounceTimeouts . delete ( debounceKey )
200+ }
201+ }
202+
144203 logger . debug ( 'Removing operation from queue' , {
145204 operationId,
146205 remainingOps : newOperations . length ,
@@ -166,6 +225,20 @@ export const useOperationQueueStore = create<OperationQueueState>((set, get) =>
166225 operationTimeouts . delete ( operationId )
167226 }
168227
228+ // Clean up any debounce timeouts for subblock operations
229+ if (
230+ operation . operation . operation === 'subblock-update' &&
231+ operation . operation . target === 'subblock'
232+ ) {
233+ const { blockId, subblockId } = operation . operation . payload
234+ const debounceKey = `${ blockId } -${ subblockId } `
235+ const debounceTimeout = subblockDebounceTimeouts . get ( debounceKey )
236+ if ( debounceTimeout ) {
237+ clearTimeout ( debounceTimeout )
238+ subblockDebounceTimeouts . delete ( debounceKey )
239+ }
240+ }
241+
169242 if ( operation . retryCount < 3 ) {
170243 const newRetryCount = operation . retryCount + 1
171244 const delay = 2 ** newRetryCount * 1000 // 2s, 4s, 8s
0 commit comments