Skip to content

Sync on collection update #1240

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

Closed

Conversation

sunkup
Copy link
Member

@sunkup sunkup commented Jan 14, 2025

Purpose

Nice to have for:

Short description

  • Pass account of the changed collection along when notifying listeners of collections change.
  • Then have SyncWorkerManager listen to any collection changes and use the account passed along to
  • then trigger a short delay-coroutine job, which resets itself on new change observations and after delay expiration
  • enqueues a one time sync of the whole account (not just the service which the collection belongs to - although that would prob be possible as well).

Checklist

  • The PR has a proper title, description and label.
  • I have self-reviewed the PR.
  • I have added documentation to complex functions and functions that can be used by other modules.
  • I have added reasonable tests or consciously decided to not add tests.

@sunkup sunkup added the enhancement New feature or request label Jan 14, 2025
@sunkup sunkup self-assigned this Jan 14, 2025
@sunkup sunkup requested a review from ArnyminerZ January 14, 2025 15:23
@sunkup sunkup marked this pull request as ready for review January 14, 2025 15:23
Copy link
Member

@rfc2822 rfc2822 left a comment

Choose a reason for hiding this comment

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

I wonder how this behaves when the services are refreshed. Doesn't it enqueue a lot of syncs during service detection (whenever a collection is updated)?

My ideas (may or may not make sense):

  • A delay of a few seconds between the collection change and the sync (like for the push registration) could at least reduce the number of synchronizations during service detection.
  • Or maybe pause it somehow?
  • Maybe separate callbacks for the actions we want to observe (update read-only, update sync flag)? Has advantages and disadvantages.

@sunkup sunkup removed the request for review from ArnyminerZ January 20, 2025 16:07
@sunkup sunkup marked this pull request as draft January 20, 2025 16:07
@sunkup sunkup force-pushed the 851-force-read-only-setting-not-effective-immediately branch 2 times, most recently from 945029e to 7f58df8 Compare January 21, 2025 09:24
@sunkup sunkup force-pushed the 851-force-read-only-setting-not-effective-immediately branch from f9a0940 to 7d4bca1 Compare January 21, 2025 09:45
@sunkup sunkup requested a review from ArnyminerZ January 21, 2025 10:13
@sunkup sunkup marked this pull request as ready for review January 21, 2025 10:13
@rfc2822
Copy link
Member

rfc2822 commented Jan 27, 2025

Hm, because we're not sure about unwanted consequences (regarding service detection etc)

Maybe we could the sync from the UI? So that not the DB Collection is observed, but instead when the user changes the read-only / sync flag in the UI, it waits a few seconds and then starts a sync?

@sunkup
Copy link
Member Author

sunkup commented Jan 27, 2025

Hm, because we're not sure about unwanted consequences (regarding service detection etc)

Maybe we could the sync from the UI? So that not the DB Collection is observed, but instead when the user changes the read-only / sync flag in the UI, it waits a few seconds and then starts a sync?

Sure, we should drop #1230 then though, since we don't want that feature anymore?

@rfc2822
Copy link
Member

rfc2822 commented Jan 27, 2025

Sure, we should drop #1230 then though, since we don't want that feature anymore?

I mean we could sync when they're (un)checked by the user in the UI, but not when the sync flag is modified by for instance some background code.

@rfc2822
Copy link
Member

rfc2822 commented Jan 27, 2025

But maybe let's do it after the other 4.5 things and could also be good to discuss (dis)advantages in a talk

Copy link
Member

@ArnyminerZ ArnyminerZ left a comment

Choose a reason for hiding this comment

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

Works perfectly

@rfc2822
Copy link
Member

rfc2822 commented Mar 12, 2025

I still wonder why we really want to couple it on the data layer and not in the UI layer.

Advantage of data layer: independent from UI – when collections are for instance changed by managed settings or other circumstances, sync would still run again

Risk of data layer: we don't know when collections are really updated. For instance, we may at some time update the collection properties (calendar name, color, …) during the first PROPFIND of a sync, as we have thought about often. In that case a sync could automatically trigger another sync.

I think the basic question is: what's our goal?

  • Shall every change in a collection entry, in the database/repository, regardless of where it comes from, automatically trigger a sync?
  • Or shall only UI changes (enable/disable collection, select read-only) automatically trigger a sync to reflect these changes?

I'm not sure yet, but I think it would be more safe to trigger this on UI layer instead, at least for now. What are your thoughts?

@sunkup
Copy link
Member Author

sunkup commented Mar 18, 2025

I think the basic question is: what's our goal?

  • Shall every change in a collection entry, in the database/repository, regardless of where it comes from, automatically trigger a sync?

Besides having OnChangeListener we could also have a SyncOnChangeListener, whichSyncOnCollectionsChangeListener would subscribe to. We would only notify for a sync to start when needed. That is when collection sync and the force-read-only setting change (are enabled or disabled).

I think that's still clean architecture and it would solve the issue of unintentional syncs of other collection changes.

I'm not sure yet, but I think it would be more safe to trigger this on UI layer instead, at least for now. What are your thoughts?

I think both ways can be equally safe. Going the UI route is probably a bit less complex.

@rfc2822
Copy link
Member

rfc2822 commented Apr 8, 2025

If it reacts on DB changes, why not also when the title (→ calendar name), color etc. changes (during a collection list refresh)? So OnChangeListener would cover more cases that also could be useful than a SyncOnChangeListener.

Two things:

  1. Shall we adapt sync enqueueing so that it replaces the current sync instead of keeping it? For this use case:
  • User checks collection A to be synced.
  • User waits 7 seconds. Sync starts.
  • While the sync runs, user checks collection B to be synced.
  • User waits 7 seconds. Sync is still running (let's say it takes some time), and it's not replaced nor is a new sync enqueued.
  • User waits until sync is complete.
  • User expects calendar B to be there because sync has finished. However it's not there.

We could use ExistingWorkPolicy.REPLACE, but then service detection (assuming again that it takes some time) would start, cancel, restart syncs several times. Sounds like it could cause problems.

With ExistingWorkPolicy.APPEND, it could append some unnecessary syncs.

  1. And/or shall we add some logic that service detection can postpone the logic while it runs? Then we would have to determine where such logic fits best.

@sunkup
Copy link
Member Author

sunkup commented Apr 9, 2025

If it reacts on DB changes, why not also when the title (→ calendar name), color etc. changes (during a collection list refresh)? So OnChangeListener would cover more cases that also could be useful than a SyncOnChangeListener.

This would increase the likelihood of enqueuing new unneccessary syncs though, no? Like you mentioned:

Risk of data layer: we don't know when collections are really updated. For instance, we may at some time update the collection properties (calendar name, color, …) during the first PROPFIND of a sync, as we have thought about often. In that case a sync could automatically trigger another sync.

I do think however this would could be neglectible if we replace only enqueued workers. So not replace a running sync worker (ExistingWorkPolicy.REPLACE) and not stack a ton of uneccessary syncs (ExistingWorkPolicy.APPEND), but only replace/update the pending sync request directly after the currently running one.

I think this way we could reduce the amount of unecessary syncs considerably. Unfortunately it seems like workmanager does not have this feature inbuilt. So if we'd want only the latest request to run after the currently running one, that means to have at most two "active" workers:

  • No workers: Enqueue normally
  • 1 running: Add 2nd to stack
  • 1 running + 1 queued: Skip! (max 2 reached)

We would need to do some querying ourselves before appending new requests, like so:

val activeCount = WorkManager.getInstance(context)
    .getWorkInfosForUniqueWork("onetime-sync ...")
    .get()
    .count { 
         it.state == WorkInfo.State.RUNNING || it.state == WorkInfo.State.ENQUEUED
    }

if (activeCount < 2)
    WorkManager.getInstance(context).enqueueUniqueWork(
        "onetime-sync ...",
        ExistingWorkPolicy.APPEND,
        workRequest
    )

Now for your two things:

  1. Solved by appending at most one more worker
  2. If I understand correctly, you would have RefreshCollectionsWorker be enqueued and run, but then have it not do its actual work (inside doWork) based on some logic/check? I can't see how this is beneficial 🤔

I'd love to have a call on this issue too 🔄

@sunkup
Copy link
Member Author

sunkup commented Apr 9, 2025

Discussed in call.

Too risky. Hard to oversee potential problems. Infinite detection-sync loops etc.

We will create a new PR with UI triggers to test the water first.

@sunkup sunkup closed this Apr 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatically sync when collections are (un)checked "Force read-only" setting not effective immediately
3 participants