fix: enhance CSV import rate limiting and UI protection

- Reduce batch size from 3 to 2 expenses per batch for more conservative processing
- Increase delay between batches from 1.5s to 2s to prevent HTTP 429 errors
- Add isProcessingExpenses state to prevent multiple simultaneous imports
- Disable import buttons during expense processing for better UX
- Ensure processing state is always cleared in finally block

Resolves HTTP 429 rate limiting errors during bulk expense creation from CSV imports.
This commit is contained in:
dlawler489 2026-05-05 20:02:30 +10:00
parent b8d0416a79
commit c2bdaa3c0d

View file

@ -54,6 +54,7 @@ export default function DataImport() {
const [etsyFile, setEtsyFile] = useState<File | null>(null); const [etsyFile, setEtsyFile] = useState<File | null>(null);
const [shippingFile, setShippingFile] = useState<File | null>(null); const [shippingFile, setShippingFile] = useState<File | null>(null);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isProcessingExpenses, setIsProcessingExpenses] = useState(false);
const [results, setResults] = useState<ImportResults | null>(null); const [results, setResults] = useState<ImportResults | null>(null);
// PDF Import State // PDF Import State
@ -117,6 +118,8 @@ export default function DataImport() {
etsyFees: EtsyFeeRecord[] etsyFees: EtsyFeeRecord[]
) => { ) => {
try { try {
setIsProcessingExpenses(true);
// Get existing expenses to avoid duplicates // Get existing expenses to avoid duplicates
const existingExpensesRes = await api.get('/expenses?limit=1000'); const existingExpensesRes = await api.get('/expenses?limit=1000');
const existingExpenses = existingExpensesRes.data.expenses || []; const existingExpenses = existingExpensesRes.data.expenses || [];
@ -180,9 +183,9 @@ export default function DataImport() {
let created = 0; let created = 0;
let skippedDuplicates = 0; let skippedDuplicates = 0;
// Process expenses with rate limiting (conservative approach to avoid 429 errors) // Process expenses with very conservative rate limiting to prevent 429 errors
const BATCH_SIZE = 3; // Reduced from 5 to be more conservative const BATCH_SIZE = 2; // Further reduced to 2 expenses per batch
const DELAY_MS = 1500; // Increased delay to 1.5 seconds const DELAY_MS = 2000; // Increased to 2 seconds between batches
const totalBatches = Math.ceil(expensesToCreate.length / BATCH_SIZE); const totalBatches = Math.ceil(expensesToCreate.length / BATCH_SIZE);
console.log(`Creating ${expensesToCreate.length} expenses in ${totalBatches} batches to avoid rate limiting...`); console.log(`Creating ${expensesToCreate.length} expenses in ${totalBatches} batches to avoid rate limiting...`);
@ -249,6 +252,8 @@ export default function DataImport() {
} catch (error) { } catch (error) {
console.error('Error creating expenses:', error); console.error('Error creating expenses:', error);
toast.error('Failed to create expenses from CSV data'); toast.error('Failed to create expenses from CSV data');
} finally {
setIsProcessingExpenses(false);
} }
}; };
@ -838,10 +843,10 @@ export default function DataImport() {
<div className="mt-6 flex gap-4"> <div className="mt-6 flex gap-4">
<button <button
onClick={processCsvFiles} onClick={processCsvFiles}
disabled={!etsyFile || isLoading} disabled={!etsyFile || isLoading || isProcessingExpenses}
className="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 disabled:bg-gray-400" className="bg-blue-600 text-white px-6 py-2 rounded-lg hover:bg-blue-700 disabled:bg-gray-400"
> >
{isLoading ? 'Processing...' : 'Analyze Financial Data'} {isLoading || isProcessingExpenses ? 'Processing...' : 'Analyze Financial Data'}
</button> </button>
</div> </div>
</div> </div>
@ -973,7 +978,8 @@ export default function DataImport() {
</div> </div>
<button <button
onClick={createOrdersFromCSV} onClick={createOrdersFromCSV}
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 ml-4" disabled={isProcessingExpenses}
className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-400 ml-4"
> >
<Package className="w-4 h-4" /> <Package className="w-4 h-4" />
Re-sync Orders Re-sync Orders