-
Notifications
You must be signed in to change notification settings - Fork 1
β‘ Bolt: Parallelize folder deletion #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -465,7 +465,7 @@ | |||||||||||||
| ) | ||||||||||||||
| return False | ||||||||||||||
| if "group" not in data["group"]: | ||||||||||||||
| log.error( | ||||||||||||||
Check warningCode scanning / Prospector (reported by Codacy) Use lazy % formatting in logging functions (logging-fstring-interpolation) Warning
Use lazy % formatting in logging functions (logging-fstring-interpolation)
|
||||||||||||||
| f"Invalid data from {sanitize_for_log(url)}: Missing 'group.group' (folder name)." | ||||||||||||||
| ) | ||||||||||||||
| return False | ||||||||||||||
|
|
@@ -651,7 +651,7 @@ | |||||||||||||
| return [rule["PK"] for rule in folder_rules if rule.get("PK")] | ||||||||||||||
| except httpx.HTTPError: | ||||||||||||||
| return [] | ||||||||||||||
| except Exception as e: | ||||||||||||||
Check warningCode scanning / Pylint (reported by Codacy) Variable name "e" doesn't conform to snake_case naming style Warning
Variable name "e" doesn't conform to snake_case naming style
|
||||||||||||||
| # We log error but don't stop the whole process; | ||||||||||||||
| # individual folder failure shouldn't crash the sync | ||||||||||||||
| log.warning(f"Error fetching rules for folder {folder_id}: {e}") | ||||||||||||||
|
|
@@ -808,7 +808,7 @@ | |||||||||||||
| grp["PK"], | ||||||||||||||
| ) | ||||||||||||||
| return str(grp["PK"]) | ||||||||||||||
| except Exception as e: | ||||||||||||||
Check noticeCode scanning / Pylintpython3 (reported by Codacy) Catching too general exception Exception Note
Catching too general exception Exception
|
||||||||||||||
| log.debug(f"Could not extract ID from POST response: {e}") | ||||||||||||||
|
|
||||||||||||||
| # 2. Fallback: Poll for the new folder (The Robust Retry Logic) | ||||||||||||||
|
|
@@ -835,7 +835,7 @@ | |||||||||||||
| ) | ||||||||||||||
| time.sleep(wait_time) | ||||||||||||||
|
|
||||||||||||||
| log.error( | ||||||||||||||
Check noticeCode scanning / Pylintpython3 (reported by Codacy) Use lazy % formatting in logging functions Note
Use lazy % formatting in logging functions
|
||||||||||||||
| f"Folder {sanitize_for_log(name)} was not found after creation and retries." | ||||||||||||||
| ) | ||||||||||||||
| return None | ||||||||||||||
|
|
@@ -1149,16 +1149,33 @@ | |||||||||||||
| existing_folders = list_existing_folders(client, profile_id) | ||||||||||||||
| if not no_delete: | ||||||||||||||
| deletion_occurred = False | ||||||||||||||
| # Use a dict to deduplicate folders to delete | ||||||||||||||
| folders_to_delete = {} | ||||||||||||||
| for folder_data in folder_data_list: | ||||||||||||||
| name = folder_data["group"]["group"].strip() | ||||||||||||||
| if name in existing_folders: | ||||||||||||||
| # Optimization: Maintain local state of folders to avoid re-fetching | ||||||||||||||
| # delete_folder returns True on success | ||||||||||||||
| if delete_folder( | ||||||||||||||
| client, profile_id, name, existing_folders[name] | ||||||||||||||
| ): | ||||||||||||||
| del existing_folders[name] | ||||||||||||||
| deletion_occurred = True | ||||||||||||||
| folders_to_delete[name] = existing_folders[name] | ||||||||||||||
|
|
||||||||||||||
| if folders_to_delete: | ||||||||||||||
| # Parallelize deletion: 5 workers is generally safe for DELETE operations | ||||||||||||||
| with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: | ||||||||||||||
| future_to_folder = { | ||||||||||||||
| executor.submit( | ||||||||||||||
| delete_folder, client, profile_id, name, folder_id | ||||||||||||||
| ): name | ||||||||||||||
| for name, folder_id in folders_to_delete.items() | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| for future in concurrent.futures.as_completed(future_to_folder): | ||||||||||||||
| name = future_to_folder[future] | ||||||||||||||
| try: | ||||||||||||||
| if future.result(): | ||||||||||||||
| del existing_folders[name] | ||||||||||||||
| deletion_occurred = True | ||||||||||||||
| except Exception as e: | ||||||||||||||
| log.error( | ||||||||||||||
| f"Failed to delete folder {sanitize_for_log(name)}: {e}" | ||||||||||||||
| ) | ||||||||||||||
|
Comment on lines
+1176
to
+1178
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The newly added parallel folder deletion logic catches exceptions but fails to sanitize the exception object
Suggested change
Comment on lines
+1159
to
+1178
|
||||||||||||||
|
|
||||||||||||||
| # CRITICAL FIX: Increased wait time for massive folders to clear | ||||||||||||||
| if deletion_occurred: | ||||||||||||||
|
|
@@ -1176,7 +1193,7 @@ | |||||||||||||
| with concurrent.futures.ThreadPoolExecutor( | ||||||||||||||
| max_workers=max_workers | ||||||||||||||
| ) as executor: | ||||||||||||||
| future_to_folder = { | ||||||||||||||
Check noticeCode scanning / Pylint (reported by Codacy) Catching too general exception Exception Note
Catching too general exception Exception
|
||||||||||||||
| executor.submit( | ||||||||||||||
| _process_single_folder, | ||||||||||||||
| folder_data, | ||||||||||||||
|
|
||||||||||||||
Check warning
Code scanning / Pylintpython3 (reported by Codacy)
Variable name "e" doesn't conform to snake_case naming style Warning