gallery_server_client_s190js/docs/activity_scan.md
2026-10-26 11:00:14 +01:00

8.3 KiB

Certo. Dopo le modifiche in s179js, il flusso Activity è ormai molto simile a quello Photo, ma la notifica alla gallery segue ancora il percorso tramite POST /activities.

  1. Flusso attuale di scansione Activity

Quando premi Scan Activities:

                     UTENTE
                        │
                        ▼
                Scan Activities
                        │
                        ▼
            routes/scanActivities.js
                        │
                        ▼
            scanActivitiesUser()
                        │
            trova cartelle Activity
                        │
                        ▼
                scanActivity()
                        │
                        ▼
           scanActivityCartella()
                        │
               trova FIT/GPX/TCX
                        │
                        ▼
         enqueueActivityIngestJob()
                        │
                        ▼
             activity_ingest_jobs
                        │
          ┌─────────────┼──────────────┐
          │             │              │
       pending       processing       done
          │
          ▼
          │    ACTIVITY DAEMON [A]
          └────────────►│
                        ▼
                 runOneJob()
                        │
                        ▼
             scanActivitySingle()
                        │
                        ▼
             processActivityFile()
                        │
                parsing FIT/GPX/TCX
                        │
                        ▼
                 activities DB
                        │
                        ├───────────────┐
                        │               │
                        ▼               ▼
                 geocode_jobs      ritorno meta
                        │
                        ▼
                GEOCODE DAEMON [G]
                        │
                        ▼
                  geocoding

Lo Scan adesso è solo il produttore

Questa è la differenza fondamentale rispetto a prima.

Prima:

Scan ↓ trova file ↓ parsa FIT ↓ salva Activity ↓ file successivo

Adesso:

Scan ↓ trova file ↓ mette job pending ↓ file successivo

Per questo nel log vedi velocemente:

[S] 📥 [ACTIVITY QUEUE] xxx.fit status=pending inserted [S] 📥 [ACTIVITY QUEUE] yyy.fit status=pending inserted [S] 📥 [ACTIVITY QUEUE] zzz.fit status=pending inserted

e poi:

[S] Scan ATTIVITÀ COMPLETATO

Questo però non significa che tutte le Activity siano elaborate. Significa solamente che la fase di discovery ha finito di riempire la coda.

  1. Il daemon svuota la coda

Parallelamente [A] fa:

activity_ingest_jobs │ ▼ prende primo pending │ ▼ processing │ ▼ parse FIT │ ▼ salva Activity │ ▼ accoda Geocode │ ▼ sincronizza server │ ▼ done │ ▼ prende IMMEDIATAMENTE il pending successivo

Infatti nel tuo log:

[A] Avvio job ... [A] Nuova activity ... [A] Activity ... inviata al server remoto [A] Job ... completato; stato: done [A] Avvio job successivo ...

Non ci sono 2 secondi tra un'attività e l'altra.

I 2 secondi servono solo quando:

pending = 0

  1. Geocode è completamente indipendente

Quando scanActivitySingle() salva l'Activity esegue anche:

enqueueGeocodeJob

quindi:

ACTIVITY DAEMON │ ▼ activities DB │ └────────────► geocode_jobs │ ▼ GEOCODE DAEMON [G] │ ▼ geocoding

Activity daemon non aspetta che il Geocode finisca.

Per questo nel log puoi vedere:

[A] job Activity successivo

mentre:

[G] geocodeWorker processing

sta ancora lavorando sull'attività precedente.

  1. Flusso attuale di notifica alla gallery Activity

Qui il percorso è leggermente diverso da Photo.

Quando scanActivitySingle() restituisce la nuova Activity:

                ACTIVITY DAEMON [A]
                        │
                        ▼
              scannedActivity/meta
                        │
                        ▼
                 postWithAuth()
                        │
                        ▼
          POST BASE_URL/activities
                        │
                        ▼
              routes/activities.js
                        │
                        ▼
                INSERT activity
               ON CONFLICT MERGE
                        │
                        ▼
         invalidateActivitySpatialIndex()
                        │
                        ▼
              broadcastToUser()
                        │
                  payload:
              type: "added"
              id: activityId
              entity: "activity"
                        │
                        ▼
                   WebSocket
                        │
                        ▼
                     CLIENT
                        │
                        ▼
              Activity Gallery

Quindi la notifica alla gallery non viene inviata direttamente dall'Activity daemon.

Il daemon fa:

Activity daemon ↓ HTTP POST ↓ server ↓ WebSocket ↓ Gallery

Questo è importante perché il processo [A] non importa ws-server e quindi non rischia di aprire un secondo WebSocket sulla porta 4002.

  1. Pipeline completa

Mettendo insieme tutto:

                     SCAN
                      │
                      ▼
             trova FIT/GPX/TCX
                      │
                      ▼
            activity_ingest_jobs
                      │
                      │ pending
                      ▼
             ACTIVITY DAEMON [A]
                      │
                      ▼
              parse FIT/GPX/TCX
                      │
                      ▼
                activities DB
                      │
         ┌────────────┴─────────────┐
         │                          │
         ▼                          ▼
   geocode_jobs                 activity meta
         │                          │
         ▼                          ▼
 GEOCODE DAEMON [G]        POST /activities
                                    │
                                    ▼
                                  SERVER
                                    │
                          INSERT / UPDATE
                                    │
                                    ▼
                                WebSocket
                                    │
                                    ▼
                           ACTIVITY GALLERY

         Activity daemon
                │
                ▼
        job status = done
                │
                ▼
         prossimo pending
  1. Cosa significa per il futuro banner

Ora abbiamo finalmente una coda affidabile:

activity_ingest_jobs

quindi il banner Activity non deve più basarsi sul vecchio:

scan_status.json

Può mostrare direttamente:

remaining = pending + processing

Per esempio:

Activities processing: 27

poi:

Activities processing: 26 Activities processing: 25 ... Activities processing: 1

e quando:

pending = 0 processing = 0

il banner scompare.

Questo sarebbe molto più corretto del vecchio progress dello Scan, perché lo Scan può aver finito di accodare i file mentre l'Activity daemon ha ancora 30 FIT da elaborare.