Skip to content

🧹 Refactor: Extract helper functions from sync_profile#792

Open
abhimehro wants to merge 2 commits into
mainfrom
jules-6223985617443445838-52b9cd39
Open

🧹 Refactor: Extract helper functions from sync_profile#792
abhimehro wants to merge 2 commits into
mainfrom
jules-6223985617443445838-52b9cd39

Conversation

@abhimehro
Copy link
Copy Markdown
Owner

@abhimehro abhimehro commented May 14, 2026

🎯 What: Extracted three helper functions (_fetch_all_folder_data, _build_plan_entry, and _prepare_folders_and_rules) from the complex sync_profile function.

💡 Why: sync_profile was too long and had high cyclomatic complexity, making it difficult to read and maintain. Breaking it down into logical sub-steps improves code health and modularity.

Verification: Ran uv run pytest (369 passing tests), uv run mypy . (no type errors), and uv tool run ruff check . and uv tool run ruff format ..

Result: The sync_profile function is significantly shorter and more readable without altering any functionality.

===== ELIR =====
PURPOSE: Refactor sync_profile into smaller functions.
SECURITY: No security implications as no functionality was altered.
FAILS IF: Extracted logic behaves differently, which was tested extensively via test suite.
VERIFY: Review functionality mapping between extracted functions and the previous unified code.
MAINTAIN: The extraction was mechanical and semantic, keep an eye out for more extraction opportunities in sync_profile.


Open in Devin Review

Copilot AI review requested due to automatic review settings May 14, 2026 13:19
@trunk-io
Copy link
Copy Markdown

trunk-io Bot commented May 14, 2026

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@cursor
Copy link
Copy Markdown

cursor Bot commented May 14, 2026

PR Summary

Low Risk
Low risk refactor that primarily moves existing logic into helper functions, but it touches the main sync workflow and concurrency/deletion sequencing so regressions would show up at runtime if behavior diverges.

Overview
Refactors the sync_profile workflow by extracting three chunks of logic into _fetch_all_folder_data, _build_plan_entry, and _prepare_folders_and_rules, reducing function size and cyclomatic complexity.

The extracted helpers preserve the existing behavior for parallel URL validation/fetch, dry-run plan generation (including legacy vs multi-action rule formats), and the pre-sync phase that verifies access, optionally deletes matching folders, overlaps rule fetching with deletions, and waits for deletion propagation when needed.

Reviewed by Cursor Bugbot for commit 50d6908. Configure here.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown

@codescene-delta-analysis codescene-delta-analysis Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Health Improved (1 files improve in Code Health)

Gates Passed
6 Quality Gates Passed

See analysis details in CodeScene

View Improvements
File Code Health Impact Categories Improved
main.py 1.66 → 1.80 Brain Method, Complex Method, Bumpy Road Ahead, Overall Code Complexity, Deep, Nested Complexity

Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

Open in Devin Review

Comment thread main.py
existing_rules = set()
if existing_folders_and_rules[0] is None:
return False
existing_folders, existing_rules = existing_folders_and_rules
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Unused existing_folders variable after unpacking

At main.py:2630, existing_folders is unpacked from the tuple but never used afterward in sync_profile. In the old code, existing_folders was also not used after the deletion/scanning phase — all mutations happened inline before creating SyncContext. This is harmless but the variable could be replaced with _ to signal intent: _, existing_rules = existing_folders_and_rules.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread main.py
return fetch_folder_data(url)
return None

with concurrent.futures.ThreadPoolExecutor() as executor:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: ThreadPoolExecutor default max_workers in _fetch_all_folder_data

At main.py:2422, the ThreadPoolExecutor() is created without an explicit max_workers argument, defaulting to min(32, os.cpu_count() + 4). This matches the original inline code. For a large number of folder URLs, this could create many concurrent DNS lookups and HTTP fetches. This is a pre-existing design choice, not introduced by the refactoring, but worth noting if the number of folder URLs could be very large.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread main.py
Comment on lines +2522 to +2537
# Start fetching rules from kept folders in background (parallel to deletions)
existing_rules_future = shared_executor.submit(
get_all_existing_rules, client, profile_id, folders_to_scan
)

if not no_delete:
deletion_occurred = False
if folders_to_delete:
# Parallel delete to speed up the "clean slate" phase
# Use shared_executor (3 workers)
future_to_name = {
shared_executor.submit(
delete_folder, client, profile_id, name, folder_id
): name
for name, folder_id in folders_to_delete
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Potential executor saturation in _prepare_folders_and_rules

At main.py:2523, get_all_existing_rules is submitted to shared_executor (which has DELETE_WORKERS=3 max workers). Then at lines 2532-2536, delete_folder tasks are also submitted to the same executor. If there are ≥3 folders to delete, the background rules-fetch task occupies 1 of 3 slots, leaving only 2 for deletions. This is identical to the pre-refactoring behavior and get_all_existing_rules uses its own internal ThreadPoolExecutor(max_workers=5) for parallel work, so there's no deadlock risk — just slightly reduced delete parallelism.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants