Optimize draft sheet batch writes to single API call
- Changed write_picks_batch() from 105 individual API calls to 1 batch call - Builds 2D array covering full pick range and writes in single update_values() - Eliminates Google Sheets 429 rate limiting during resync operations - Reduces resync time from ~2 minutes to seconds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
637f1a015f
commit
a814aadd61
@ -129,6 +129,8 @@ class DraftSheetService(SheetsService):
|
|||||||
Write multiple draft picks to the sheet in a single batch operation.
|
Write multiple draft picks to the sheet in a single batch operation.
|
||||||
|
|
||||||
Used for resync operations to repopulate the entire sheet from database.
|
Used for resync operations to repopulate the entire sheet from database.
|
||||||
|
Uses true batch updates to write all picks in a single API call,
|
||||||
|
avoiding rate limiting issues.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
season: Draft season number
|
season: Draft season number
|
||||||
@ -169,41 +171,51 @@ class DraftSheetService(SheetsService):
|
|||||||
self._config.draft_sheet_worksheet
|
self._config.draft_sheet_worksheet
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sort picks by overall to write in order
|
# Sort picks by overall to find range bounds
|
||||||
sorted_picks = sorted(picks, key=lambda p: p[0])
|
sorted_picks = sorted(picks, key=lambda p: p[0])
|
||||||
|
|
||||||
# Build batch data - each pick goes to its calculated row
|
# Find min and max overall to determine row range
|
||||||
# We'll write one row at a time to handle non-contiguous picks
|
min_overall = sorted_picks[0][0]
|
||||||
success_count = 0
|
max_overall = sorted_picks[-1][0]
|
||||||
failure_count = 0
|
|
||||||
|
|
||||||
|
# Build a 2D array for the entire range (sparse - empty rows for missing picks)
|
||||||
|
# Row index 0 = min_overall, row index N = max_overall
|
||||||
|
num_rows = max_overall - min_overall + 1
|
||||||
|
batch_data: List[List[str]] = [['', '', '', ''] for _ in range(num_rows)]
|
||||||
|
|
||||||
|
# Populate the batch data array
|
||||||
for overall, orig_owner, owner, player_name, swar in sorted_picks:
|
for overall, orig_owner, owner, player_name, swar in sorted_picks:
|
||||||
try:
|
row_index = overall - min_overall
|
||||||
pick_data = [[orig_owner, owner, player_name, swar]]
|
batch_data[row_index] = [orig_owner, owner, player_name, str(swar)]
|
||||||
row = overall + 1
|
|
||||||
start_column = self._config.draft_sheet_start_column
|
|
||||||
cell_range = f'{start_column}{row}'
|
|
||||||
|
|
||||||
await loop.run_in_executor(
|
# Calculate the cell range for the batch write
|
||||||
None,
|
start_row = min_overall + 1 # +1 for header row
|
||||||
lambda cr=cell_range, pd=pick_data: worksheet.update_values(
|
start_column = self._config.draft_sheet_start_column
|
||||||
crange=cr, values=pd
|
end_column = chr(ord(start_column) + 3) # 4 columns: D -> G
|
||||||
)
|
end_row = max_overall + 1
|
||||||
)
|
|
||||||
success_count += 1
|
cell_range = f'{start_column}{start_row}:{end_column}{end_row}'
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(f"Failed to write pick {overall}: {e}")
|
|
||||||
failure_count += 1
|
|
||||||
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f"Batch write complete: {success_count} succeeded, {failure_count} failed",
|
f"Writing {len(picks)} picks in single batch to range {cell_range}",
|
||||||
|
season=season
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write all picks in a single API call
|
||||||
|
await loop.run_in_executor(
|
||||||
|
None,
|
||||||
|
lambda: worksheet.update_values(crange=cell_range, values=batch_data)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"Batch write complete: {len(picks)} picks written successfully",
|
||||||
season=season,
|
season=season,
|
||||||
total_picks=len(picks)
|
total_picks=len(picks)
|
||||||
)
|
)
|
||||||
return (success_count, failure_count)
|
return (len(picks), 0)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to initialize batch write: {e}", season=season)
|
self.logger.error(f"Failed batch write: {e}", season=season)
|
||||||
return (0, len(picks))
|
return (0, len(picks))
|
||||||
|
|
||||||
async def clear_picks_range(
|
async def clear_picks_range(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user