Skip to content

Commit 62ec273

Browse files
committed
fix(file-search): preserve spreadsheet extraction cancellation
1 parent eefb5e0 commit 62ec273

2 files changed

Lines changed: 43 additions & 3 deletions

File tree

‎apps/sim/lib/file-parsers/complete-text.test.ts‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,41 @@ describe('complete extraction for search', () => {
6060
await rm(dir, { recursive: true, force: true })
6161
}
6262
})
63+
it('preserves cancellation before inspecting a spreadsheet buffer', async () => {
64+
const reason = new Error('Cancelled by caller')
65+
await expect(
66+
new XlsxParser().parseBuffer(Buffer.from('invalid workbook'), {
67+
contentMode: 'complete',
68+
signal: AbortSignal.abort(reason),
69+
})
70+
).rejects.toBe(reason)
71+
})
72+
it.each([1, 2])('preserves cancellation while extracting a %i-row spreadsheet', async (rows) => {
73+
const workbook = XLSX.utils.book_new()
74+
XLSX.utils.book_append_sheet(
75+
workbook,
76+
XLSX.utils.aoa_to_sheet([['first'], ['second']].slice(0, rows)),
77+
'Data'
78+
)
79+
const buffer = XLSX.write(workbook, { type: 'buffer', bookType: 'xlsx' })
80+
const controller = new AbortController()
81+
const reason = new Error('Cancelled during extraction')
82+
const formatCell = XLSX.utils.format_cell
83+
const format = vi.spyOn(XLSX.utils, 'format_cell').mockImplementationOnce((...args) => {
84+
controller.abort(reason)
85+
return formatCell(...args)
86+
})
87+
try {
88+
await expect(
89+
new XlsxParser().parseBuffer(buffer, {
90+
contentMode: 'complete',
91+
signal: controller.signal,
92+
})
93+
).rejects.toBe(reason)
94+
} finally {
95+
format.mockRestore()
96+
}
97+
})
6398
it('marks a workbook with only whitespace as degraded in complete mode', async () => {
6499
const workbook = XLSX.utils.book_new()
65100
XLSX.utils.book_append_sheet(

‎apps/sim/lib/file-parsers/xlsx-parser.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class XlsxParser implements FileParser {
6767
}
6868

6969
async parseBuffer(buffer: Buffer, options: FileParseOptions = {}): Promise<FileParseResult> {
70+
options.signal?.throwIfAborted()
7071
try {
7172
const bufferSize = buffer.length
7273
logger.info(
@@ -86,10 +87,14 @@ export class XlsxParser implements FileParser {
8687
...SHEET_DISPLAY_READ_OPTIONS,
8788
})
8889

89-
return options.contentMode === 'complete'
90-
? this.processCompleteWorkbook(workbook, options)
91-
: this.processWorkbook(workbook)
90+
const result =
91+
options.contentMode === 'complete'
92+
? this.processCompleteWorkbook(workbook, options)
93+
: this.processWorkbook(workbook)
94+
options.signal?.throwIfAborted()
95+
return result
9296
} catch (error) {
97+
options.signal?.throwIfAborted()
9398
logger.error('XLSX buffer parsing error:', error)
9499
if (isEncryptedOfficeParserError(error)) {
95100
throw new FileParserError(

0 commit comments

Comments
 (0)