Skip to content

[P1][Perf] Main thread bloccato: EventKit, notifiche e seed sincroni a ogni mutazione #12

Description

@ivan-94m

Problemi

  • CalendarSyncService è @MainActor: store.events(matching:) su 13 mesi (syncWindow) e il salvataggio di ogni evento girano sul main thread → UI congelata durante la sync.
  • TodoTask.touch() esegue in modo sincrono store.save(event) di EventKit a ogni mutazione. Le operazioni batch fanno N salvataggi uno dopo l'altro: "Riprogramma a oggi" (DashboardView.swift:515), drag nel Gantt, spostamenti multipli.
  • AppConfiguration.decode (JSON) viene rieseguito in ogni body di 13 viste (@AppStorage + computed configuration).
  • SeedService.ensureSeed viene chiamato a ogni creazione (vedi issue identità).
  • SeedService.repointWorkspace fa fetch di tutte le task senza predicato.

Fix proposto

  • @ModelActor di background per sync EventKit e import; il main riceve solo il merge.
  • Coda di side effect con coalescing (un flush ogni ~300 ms, un batch per operazione).
  • AppConfiguration come @Observable singleton decodificato una sola volta, con invalidazione alla modifica.

Activity

  1. added a commit that references this issue on Oct 5, 2026
  2. ivan-94m commented on Oct 5, 2026

    @ivan-94m
    ContributorAuthor

    Prima parte in #60 (unita, CI verde):

    • Creazioni: SeedService.identity(in:) legge spazio corrente e "me" salvati (due fetch per id); il seed completo (dedupe, membership, save) non gira più a ogni nuova attività/progetto/contatto, ma all'avvio e all'arrivo di dati iCloud (NSPersistentStoreRemoteChange, con debounce).
    • repointWorkspace / repointUser: fetch con predicato invece di tutte le righe; ripuntati anche contatti, crew e scene (prima restavano nello spazio eliminato).
    • AppConfiguration.decode era già in cache.

    Resta:

    • CalendarSyncService sul main thread (events(matching:) su 13 mesi) → @ModelActor di background;
    • touch() con store.save EventKit sincrono a ogni mutazione → coda con coalescing (un batch per operazione).

    Generated by Claude Code

  3. added a commit that references this issue on Oct 6, 2026
  4. ivan-94m commented on Oct 6, 2026

    @ivan-94m
    ContributorAuthor

    Seconda parte in #61 (unita, CI verde):

    • la sync legge gli eventi della finestra (30 giorni indietro, 12 mesi avanti) in un task di background; sul main thread resta solo l'aggiornamento delle task;
    • le modifiche portate al calendario da touch() partono in un unico flush per raffica, con un solo store.commit(); gli eventi nuovi si salvano subito per avere l'eventIdentifier. Gli errori finiscono in lastError.

    Resta: l'applicazione dell'import in un @ModelActor di background, utile per archivi molto grandi. Da provare su dispositivo con la sync attiva.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions