Skip to content

Conversation

@jjmata
Copy link
Collaborator

@jjmata jjmata commented Nov 14, 2025

Cherry-picked from here, thanks @nikhilbadyal!

Summary by CodeRabbit

  • New Features

    • Added an automated scheduled job that syncs all accounts.
  • Bug Fixes

    • Corrected schedule: synchronization now runs daily at 2:22 AM (was previously documented as every 6 hours).
  • Chores

    • Improved background job reliability to reduce duplicate or overlapping sync runs.

✏️ Tip: You can customize this high-level summary in your review settings.

@jjmata jjmata linked an issue Nov 14, 2025 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Nov 14, 2025

Walkthrough

Adds a new daily scheduled job (02:22) and a corresponding ActiveJob that iterates all Family records, enqueues per-family async syncs, logs start/end and per-family errors, and adds the sidekiq-unique-jobs gem for Sidekiq locking support.

Changes

Cohort / File(s) Summary
Scheduled Job Configuration
config/schedule.yml
Adds sync_all_accounts cron entry scheduled at 22 2 * * * (02:22 daily) referencing SyncAllJob, queue scheduled, description "Syncs all accounts for all families".
Job Implementation
app/jobs/sync_all_job.rb
Adds SyncAllJob < ApplicationJob with queue_as :scheduled and sidekiq_options lock: :until_executed, on_conflict: :log. perform iterates Family.find_each, calls family.sync_later, logs start/end and per-family errors while continuing iteration.
Dependency
Gemfile
Adds sidekiq-unique-jobs dependency (Background Jobs group) to support job locking/uniqueness.

Sequence Diagram(s)

sequenceDiagram
    participant Cron as Scheduler (cron @ 02:22)
    participant Job as SyncAllJob
    participant DB as Family DB
    participant Queue as Worker Queue

    Cron->>Job: trigger SyncAllJob.perform
    Note right of Job `#DDEBF7`: log "start"
    Job->>DB: Family.find_each
    loop per family
        DB-->>Job: yield family
        alt enqueue success
            Job->>Queue: family.sync_later (enqueue async)
            Queue-->>Job: ack enqueued
        else error
            Job-->>Job: log error (continue)
        end
    end
    Note right of Job `#E6F4EA`: log "finished"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Check sidekiq_options correctness and intended lock behavior in app/jobs/sync_all_job.rb.
  • Verify family.sync_later API/queue expectations and that it handles being called repeatedly.
  • Confirm config/schedule.yml integration with deployment cron/scheduler and queue naming (scheduled).

Poem

🐇 I hopped at two-twenty-two beneath the moonlit beams,

I nudged each family awake to carry out their dreams.
Logs twitched like whiskers, tasks leapt on the run,
One-by-one they hopped away — a sync for everyone.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title claims a 6-hour sync schedule, but the actual implementation uses a daily (24-hour) cron of '22 2 * * *' (2:22am daily). This is a factual mismatch between the title and the changeset. Update the title to reflect the actual implementation, e.g., 'Add scheduled job to sync all accounts daily at 2:22am' or 'Add daily scheduled job to sync all accounts'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 329-periodic-sync-for-configured-accounts

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4a1d26 and deb6fa6.

⛔ Files ignored due to path filters (1)
  • Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • Gemfile (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test
🔇 Additional comments (1)
Gemfile (1)

36-36: All checks pass—sidekiq-unique-jobs 8.0.11 is compatible and secure.

Verification confirms:

  • sidekiq-unique-jobs 8.0.11 is compatible with sidekiq 8.0.5 (requirement: ≥7.0.0, <9.0.0) ✓
  • No known security vulnerabilities; CVE-2024-25122 (XSS) was fixed in 8.0.7 ✓
  • Gem placement and dependency management follow project conventions ✓

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jjmata jjmata self-assigned this Nov 14, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
app/jobs/accounts/sync_all_job.rb (2)

4-8: Consider adding error handling and observability.

The current implementation lacks error handling and logging, which could make debugging issues difficult in production. Consider adding:

  1. Rescue blocks to handle potential failures gracefully
  2. Logging to track sync progress and errors
  3. Metrics/monitoring for observability

Apply this diff to add basic error handling and logging:

   def perform
+    synced_count = 0
+    error_count = 0
+
     Family.find_each do |family|
-      family.sync_later
+      begin
+        family.sync_later
+        synced_count += 1
+      rescue => e
+        error_count += 1
+        Rails.logger.error("Failed to enqueue sync for family #{family.id}: #{e.message}")
+      end
     end
+
+    Rails.logger.info("Sync job completed: #{synced_count} families enqueued, #{error_count} errors")
   end

4-8: Monitor job performance and consider staggering syncs.

Running this job every 30 minutes will synchronously enqueue sync jobs for all families at once. Depending on the number of families and downstream system capacity, this could:

  • Create a thundering herd effect with all syncs starting simultaneously
  • Take considerable time if you have many families
  • Potentially overwhelm downstream APIs or databases

Consider:

  1. Adding metrics to track job execution time and family counts
  2. Implementing rate limiting or staggering (e.g., random delays) if you experience performance issues
  3. Monitoring queue depths and sync success rates
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8ba64 and 5bce954.

📒 Files selected for processing (2)
  • app/jobs/accounts/sync_all_job.rb (1 hunks)
  • config/schedule.yml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/jobs/accounts/sync_all_job.rb (1)
app/models/concerns/syncable.rb (1)
  • sync_later (14-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test

@jjmata jjmata requested a review from sokie November 14, 2025 22:19
@jjmata
Copy link
Collaborator Author

jjmata commented Nov 14, 2025

Would love your thoughts as well, @sokie ... should we add any config in /settings/hosting or is read-only via /sidekiq/cron enough?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/jobs/accounts/sync_all_job.rb (1)

5-7: Consider rate limiting for large family counts.

If there are many families, enqueuing all sync jobs simultaneously could overwhelm the queue. Consider adding a delay between batches to spread the load.

Optional improvement:

 def perform
   Family.find_each do |family|
     family.sync_later
+  rescue => e
+    Rails.logger.error("Failed to sync family #{family.id}: #{e.message}")
   end
 end

Or with batch delays if scale is a concern:

def perform
  Family.find_each.with_index do |family, index|
    # Add 1 second delay per 10 families to spread load
    delay = (index / 10).seconds
    Accounts::SyncFamilyJob.set(wait: delay).perform_later(family)
  rescue => e
    Rails.logger.error("Failed to enqueue sync for family #{family.id}: #{e.message}")
  end
end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bce954 and 01b8eeb.

📒 Files selected for processing (1)
  • app/jobs/accounts/sync_all_job.rb (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/jobs/accounts/sync_all_job.rb (1)
app/models/concerns/syncable.rb (1)
  • sync_later (14-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test

@sokie
Copy link
Collaborator

sokie commented Nov 15, 2025

Would love your thoughts as well, @sokie ... should we add any config in /settings/hosting or is read-only via /sidekiq/cron enough?

Maybe the only thing would be a checkbox to enable/disable.
While this does nothing if you have no syncable accounts, it would still be a waste of resources to run it. ( especially for pure self hosting ).
Or even better @jjmata we can enable this when any provider is enabled

Copy link
Collaborator

@sokie sokie left a comment

Choose a reason for hiding this comment

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

While a setting would be nice, not a blocker to me.

@jjmata jjmata changed the title Add scheduled job to sync all accounts every 30 minutes Add scheduled job to sync all accounts every 24 hours Nov 15, 2025
@jjmata jjmata changed the title Add scheduled job to sync all accounts every 24 hours Add scheduled job to sync all accounts every 6 hours Nov 15, 2025
@alessiocappa
Copy link
Collaborator

I noticed a auto_sync.rb file which appears to manage automatic syncing under certain conditions. However, the first section is commented out so the automatic sync never starts:

# included do
#  before_action :sync_family, if: :family_needs_auto_sync?
# end

I’ve tried uncommenting that section and it appears a sync is performed daily (I still need to test it further).

@sokie
Copy link
Collaborator

sokie commented Nov 16, 2025

I noticed a auto_sync.rb file which appears to manage automatic syncing under certain conditions. However, the first section is commented out so the automatic sync never starts:

# included do
#  before_action :sync_family, if: :family_needs_auto_sync?
# end

I’ve tried uncommenting that section and it appears a sync is performed daily (I still need to test it further).

I can check tomorrow as well what's up

@jjmata
Copy link
Collaborator Author

jjmata commented Nov 16, 2025

Excellent! This PR might not be needed after all.

@jjmata jjmata requested a review from sokie November 16, 2025 13:07
@jjmata
Copy link
Collaborator Author

jjmata commented Nov 16, 2025

Re-requested approval from @sokie so he can report back when he looks at this.

@alessiocappa
Copy link
Collaborator

@sokie I’m not sure if you tested it, but I noticed today when I first opened the app that a sync was performed in the background. I uncommented that bit in the auto_sync.rb file.

It seems to be working even though I need to open the app. The approach in this PR is to automatically perform the sync in the background every X hours, if I properly understood, regardless of whether the user logs in or not.

I’m not sure which approach you prefer.

Copy link
Collaborator

@sokie sokie left a comment

Choose a reason for hiding this comment

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

@jjmata and @alessiocappa I've checked both.
The background sync job is better, the auto_sync.rb adds overhead to any request, needs user visit pages to trigger, and might cause spikes during heavy usage if multiple users are active. It is also limited to users family, while the background sync pulls in all families.
I would say to go ahead with this PR, and keep autosync commented, it's for the better

@jjmata jjmata mentioned this pull request Nov 19, 2025
11 tasks
@jjmata
Copy link
Collaborator Author

jjmata commented Nov 19, 2025

I noticed a auto_sync.rb file which appears to manage automatic syncing under certain conditions. However, the first section is commented out so the automatic sync never starts:

# included do
#  before_action :sync_family, if: :family_needs_auto_sync?
# end

I’ve tried uncommenting that section and it appears a sync is performed daily (I still need to test it further).

Checked up on this, and they turned it off here due to performance reasons reported here.

@jjmata
Copy link
Collaborator Author

jjmata commented Nov 20, 2025

I would say to go ahead with this PR, and keep autosync commented, it's for the better

OK, made a couple of small changes/changed it to every 24 hours at 2:22am ... will merge once it goes green.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 184f398 and c4a1d26.

📒 Files selected for processing (2)
  • app/jobs/sync_all_job.rb (1 hunks)
  • config/schedule.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/schedule.yml
🧰 Additional context used
🧬 Code graph analysis (1)
app/jobs/sync_all_job.rb (1)
app/models/concerns/syncable.rb (1)
  • sync_later (14-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test

@jjmata jjmata changed the title Add scheduled job to sync all accounts every 6 hours Add scheduled job to sync all accounts every 24 hours Nov 20, 2025
@jjmata jjmata merged commit d6cbf30 into main Nov 20, 2025
6 checks passed
alessiocappa added a commit to alessiocappa/sure that referenced this pull request Nov 20, 2025
* Add scheduled job to sync all accounts every 30 minutes

Signed-off-by: Nikhil Badyal <[email protected]>

* Change job queue from default to scheduled

Signed-off-by: Juan José Mata <[email protected]>

* Flatten job into single directory

* Every 30 minutes is a bit much and will trigger Sentry warnings

* Locking and logging improvements

* Add support for extra Sidekiq goodies

---------

Signed-off-by: Nikhil Badyal <[email protected]>
Signed-off-by: Juan José Mata <[email protected]>
Co-authored-by: Nikhil Badyal <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Periodic sync for configured accounts

5 participants