(options?: QueueStrategyOptions)
| 50 | * ``` |
| 51 | */ |
| 52 | export function queueStrategy(options?: QueueStrategyOptions): QueueStrategy { |
| 53 | // Manual promise chaining to ensure async serialization |
| 54 | // LiteQueuer (unlike AsyncQueuer from @tanstack/pacer) lacks built-in async queue |
| 55 | // primitives and concurrency control. We compensate by manually chaining promises |
| 56 | // to ensure each transaction completes before the next one starts. |
| 57 | let processingChain = Promise.resolve() |
| 58 | |
| 59 | const queuer = new LiteQueuer<() => Transaction>( |
| 60 | (fn) => { |
| 61 | // Chain each transaction to the previous one's completion |
| 62 | processingChain = processingChain |
| 63 | .then(async () => { |
| 64 | const transaction = fn() |
| 65 | // Wait for the transaction to be persisted before processing next item |
| 66 | await transaction.isPersisted.promise |
| 67 | }) |
| 68 | .catch(() => { |
| 69 | // Errors are handled via transaction.isPersisted.promise and surfaced there. |
| 70 | // This catch prevents unhandled promise rejections from breaking the chain, |
| 71 | // ensuring subsequent transactions can still execute even if one fails. |
| 72 | }) |
| 73 | }, |
| 74 | { |
| 75 | wait: options?.wait ?? 0, |
| 76 | maxSize: options?.maxSize, |
| 77 | addItemsTo: options?.addItemsTo ?? `back`, // Default FIFO: add to back |
| 78 | getItemsFrom: options?.getItemsFrom ?? `front`, // Default FIFO: get from front |
| 79 | started: true, // Start processing immediately |
| 80 | }, |
| 81 | ) |
| 82 | |
| 83 | return { |
| 84 | _type: `queue`, |
| 85 | options, |
| 86 | execute: <T extends object = Record<string, unknown>>( |
| 87 | fn: () => Transaction<T>, |
| 88 | ) => { |
| 89 | // Add the transaction-creating function to the queue |
| 90 | queuer.addItem(fn as () => Transaction) |
| 91 | }, |
| 92 | cleanup: () => { |
| 93 | queuer.stop() |
| 94 | queuer.clear() |
| 95 | }, |
| 96 | } |
| 97 | } |
no test coverage detected