Vai al contenuto

AGLANCIO - Scheduler multi-istanza sincronizzazione AreaGate

Identificazione

Campo Valore
Programma AGLANCIO
Righe 2.276
Versione 2.10.0 (28/04/2026) - vedi Versioni AGLANCIO
Versione script 0003
Tipo Subroutine (mmsubw.cpy), always-on, ciclo continuo
Interfaccia cobol AGLANCIO istanza_NN (parametro LINKAGE)

Funzione

AGLANCIO e' lo scheduler di sincronizzazione che orchestra l'esecuzione di 138 programmi SWN* tra il gestionale Eurocoge (file COBOL indicizzati) e il database PostgreSQL KPN utilizzato da AreaAPP (mobile/web).

Opera come demone multi-istanza: piu' copie (0-99) possono girare in parallelo, ciascuna responsabile di un sottoinsieme di processi.


Parametri di avvio

cobol AGLANCIO istanza_NN

Il parametro LINKAGE aglancio-linkage (pic x(20)) contiene "istanza_NN". Il programma estrae il numero di istanza (0-99) dalla posizione 9:2.

Se il parametro non viene passato (1 solo argomento), l'istanza viene impostata a 0.


Istanze e classi

Assegnazione automatica

All'avvio (m-cerca-istanze-attive), AGLANCIO forza automaticamente le istanze in base all'ID del processo:

Range ID processo Istanza forzata Tipo
0 - 39.999 0 (se modo=T e istanza >= 80) Standard ad intervalli
0 - 39.999 80 (se modo=O e istanza < 80) Standard a orari fissi
40.000 - 49.999 90 Processi particolari
50.000 - 50.999 92 Database Sw-ing
51.000 - 51.999 99 (se istanza = 0) Database Frontiera
90.000 - 99.999 91 Processi custom

Istanze speciali

Istanza Caratteristica Note
0 Standard Processi ad intervalli normali
80-89 Orari fissi Ignorano lo standby orario
90 Particolari ID 40000-49999
91 Custom ID 90000-99999
92 Sw-ing DB secondario, ignora standby
99 Frontiera DB frontiera, ignora standby

Ciclo principale

Schema completo

m-00 (startup)
  +-- Parsing parametro istanza
  +-- ctr-abil
  +-- gesdebug-apri-principale
  +-- Imposta path files di controllo (controllo/)
  +-- Imposta nomi file: spegni, alive, check, version, verlancio, istanze
  +-- Verifica se chiamato da GESSTPRC (agprg-called)
  +-- open-files, rd-azi
  +-- Crea file FVERSION con k-versione-x-script
  +-- Carica versione script lancio_ambienti (FVERLANCIO)
  +-- Avvia thread m-keep-alive

MAIN LOOP (perform until m-richiesto-spegnimento = "S"):
  +-- db-test-connection
  |     +-- Chiude DB esistente
  |     +-- Rilegge configurazione (x99-src-cfg: 6 parametri COGCNF)
  |     +-- Apre connessione PostgreSQL (SWGETS + sql-init)
  |     +-- Se OK: db-open-tables (check version su 5 tabelle)
  |
  +-- Se connessione OK:
  |     +-- Se ciclo iniziale:
  |     |     +-- m-aggiorna-runtime-version
  |     |     +-- m-cerca-istanze-attive (scan ARPPROC, crea file FISTANZE)
  |     |
  |     +-- m-ciclo-principale
  |     |     +-- m-leggi-dati-arpazien (standby, switch ON/OFF, sleep)
  |     |     +-- carica-ed-esegui-processi (core del ciclo)
  |     |     +-- leggi-aggiorna-data-ora-check (keepalive, statistiche)
  |     |
  |     +-- Se fl-richiesto-reload = "S": reimposta ciclo iniziale
  |     +-- Altrimenti: fl-ciclo-iniziale = "N" (se non in standby)
  |
  +-- Se cfg-aglancio-close-db = "S": chiude DB
  +-- C$SLEEP (tm-cfg-aglancio-sleep secondi, default 5-3600)
  +-- m-test-spegnimento (verifica file aglancio-spegni-NN.txt)

fine:
  +-- db-close-tables
  +-- gesdebug-chiudi
  +-- z-close-files
  +-- cancel "POSTA"
  +-- exit program

Logica di business dettagliata

Caricamento ed esecuzione processi (carica-ed-esegui-processi)

Questo e' il cuore della logica di business.

1. Se ciclo iniziale: log "Eseguo il ciclo iniziale"
2. Registra data/ora inizio ciclo (tm-dc-ini-data/ora)

3. CHECK STANDBY:
   a. Verifica fascia oraria (tm-standby-inizio / tm-standby-fine)
      - Gestisce il cambio giorno (es. 23:15 - 05:00)
      - Istanze 80-89, 92, 99 ignorano lo standby orario
   b. Verifica giorno della settimana (tm-standby-gg-week: stringa 7 chars)
      - Tutti i giorni applicano lo standby giornaliero
   c. Se in standby: esce senza eseguire nulla

4. Se ciclo iniziale: ciclo-check-disponibilita
   (verifica per ogni processo se il .cob esiste su disco)

5. CICLO PROCESSI (m-ciclo-processi):
   Loop su ARPPROC (sequenziale, ID < 100.000):

   Per ogni processo:
   a. Legge/crea ARPSTPRC (stato runtime)
   b. Filtra per istanza corrente (a-stpr-istanza = w-aglancio-istanza)
   c. Conta processi totali
   d. Se non disponibile (fl-disp = "N"): skip
   e. Se attivo (fl-att = "S") o forzato (forzo-ese = "S"):
      - Conta processi attivi
      - check-tempo-attesa -> fl-is-timeout?
      - Se timeout: call-a-stpr-prg (esegue il processo)
        * IMPORTANTE: dopo l'esecuzione, riprende dal processo successivo
          (w-id-processo-start = a-proc-id + 1) e rientra nel loop
          esterno (fl-ciclo-terminato). Questo gestisce il caso in cui
          un processo SWN apre un secondo DB e invalida il cursore.

6. Aggiorna ISTANZESYNC con contatori processi
7. Calcola durata ciclo (COGS62) e logga

Verifica tempo di esecuzione (check-tempo-attesa)

Due modalita' di scheduling:

Modo T (Intervalli)

Prossima = ultima_esecuzione + N_minuti
- Confronta w-tempo-sched (ARPSTPRC sched-data/ora) con w-tempo-attuale
- Se w-tempo-sched <= w-tempo-attuale -> timeout
- Tempo default se non configurato: 60 minuti

Modo O (Orari fissi)

1. Scansiona ARPPRCSCHED per tutte le righe del processo
2. Per ogni schedulazione attiva (fl-canc <> "C", fl-attiva <> "N"):
   - calcola-tempo-sched-ipotetico:
     a. Prende ora schedulazione (a-prcs-ora)
     b. Se ora < ora attuale: sposta al giorno successivo
     c. Se day-of-week <> 0: avanza fino al giorno giusto
     d. Se day-of-month <> 0: avanza fino al giorno del mese
   - Seleziona la schedulazione piu' vicina (minimo ipotetico)
3. Se nessuna schedulazione trovata: processo non eseguito

Lancio processo (call-a-stpr-prg)

1. Log: "Innesco processo PROG (NOME - Operazione: OPE)"

2. Pre-esecuzione:
   - Imposta ARPSTPRC: stato = "I" (in corso), forzo-ese = "N"
   - Salva date precedenti in prec-data/prec-ora
   - Imposta att-data/ora = data/ora corrente
   - Aggiorna ISTANZESYNC: ultimo-id-avviato = a-proc-id

3. Prepara util-agprg:
   - agprg-esporta-tutto = da ARPSTPRC
   - agprg-ope = a-proc-operazione
   - agprg-id-processo = a-proc-id

4. Se istanza con DB secondario: stop thread keep-alive

5. CALL a-proc-prg USING stringhe util-agprg
      ON OVERFLOW -> log errore critico (es2000)
   CANCEL a-proc-prg

6. Se istanza con DB secondario: riavvia thread keep-alive

7. Post-esecuzione:
   - Calcola durata processo (COGS62)
   - Aggiorna ARPSTPRC:
     * stato = "A" (in attesa)
     * att-data/ora = data/ora corrente
     * Calcola prossima esecuzione
     * Reset esporta-tutto = "N"
     * Statistiche: durata-ultimo, n-cicli-oggi, durata-tot-oggi, durata-media-oggi
     * Se cambio data: sposta oggi -> ieri, azzera oggi
   - Aggiorna ISTANZESYNC: ultimo-id-eseguito = a-proc-id

Calcolo prossima esecuzione ad intervalli

COGS62: data_attuale + (tempo_attesa * 60 secondi) = prossima data/ora

Calcolo prossima esecuzione a orari fissi

Per ogni riga ARPPRCSCHED:
  1. Parti da data/ora ultima esecuzione
  2. Se a-prcs-ora >= ora_attuale: usa oggi con a-prcs-ora
     Altrimenti: sposta al giorno successivo
  3. Se day-of-week specificato: avanza fino a quel giorno (loop GESDATE)
  4. Se day-of-month specificato: avanza fino a quel giorno del mese
  5. Risultato: data/ora ipotetica
Seleziona il minimo tra tutte le ipotetiche -> prossima esecuzione

Gestione standby

Standby orario

- RAZI-STANDBY-INIZIO (HHMM) / RAZI-STANDBY-FINE (HHMM)
- Gestione cambio giorno:
  Se inizio > fine (es. 2315 > 0500):
    standby se ora >= inizio OR ora <= fine
  Se inizio <= fine (es. 1200 < 1500):
    standby se ora >= inizio AND ora <= fine
- Istanze 80-89, 92, 99: standby orario ignorato

Standby giornaliero

- RAZI-GG-WEEK-STOP: stringa 7 caratteri ("1234567")
  Ogni carattere rappresenta un giorno (1=Lun...7=Dom)
  Se il giorno corrente e' presente -> standby
- Si applica a TUTTE le istanze (nessuna eccezione)

Gestione spegnimento

Da file (m-test-spegnimento)

1. Cerca file aglancio-spegni-NN.txt
2. Se esiste:
   - m-richiesto-spegnimento = "S" (interrompe il main loop)
   - Cancella file spegni
   - Cancella file alive
   - NON cancella file version
   - Log "Richiesto spegnimento da remoto"

Da DB (switch ON/OFF in leggi-aggiorna-data-ora-check)

Legge ARPAZIEN.razi-switch-onoff:
- "ON": attivazione da AreaGate
  -> razi-attiva-sincro = "S", cfg-attiva-areaapp = "S"
  -> Aggiorna COGCNF locale
- "OFF": spegnimento da AreaGate
  -> razi-attiva-sincro = "N", cfg-attiva-areaapp = "N"
  -> Aggiorna COGCNF locale
- In entrambi i casi: reset razi-switch-onoff = " "

Reload (razi-aglancio-reload)

Se razi-aglancio-reload = 1:
- fl-richiesto-reload = "S" -> il main loop reimpostera' ciclo iniziale
- Verifica e aggiorna sleep se cambiato da remoto
- razi-aglancio-reload = 2 (flag di conferma)

Gestione keepalive

Thread keep-alive (m-keep-alive)

Thread background in loop infinito: 1. Sleep per tm-cfg-aglancio-sleep secondi 2. Lock thread (thread safety) 3. Set priorita' a 10 4. Crea cartella controllo (C$MAKEDIR) se non esiste 5. Verifica spegnimento rapido: se m-richiesto-spegnimento = "S" -> esce 6. Crea/verifica file aglancio-alive-NN.txt (heartbeat) 7. Crea/verifica file aglancio-check-NN.txt (status marker) 8. Unlock thread

Nota: il commento nel codice (righe 684-700) discute la possibilita' di forzare lo stop-run dal thread keep-alive quando AGLANCIO e' bloccato in un sottoprocesso. Questa funzionalita' e' stata disabilitata per il rischio di corruzione dati.

Statistiche

Per istanza (ISTANZESYNC)

Ad ogni fine ciclo: - a-ist-n-cicli-oggi += 1 - a-ist-durata-tot-oggi += durata_ultimo_ciclo - a-ist-durata-media-oggi = totale / n_cicli - Keepalive: data/ora corrente

Al cambio data: - Sposta oggi -> ieri - Salva in AGLSTORICOISTANZA (storico giornaliero) - Azzera contatori oggi

Per processo (ARPSTPRC)

Ad ogni esecuzione: - a-stpr-durata-ultimo = secondi - a-stpr-n-cicli-oggi += 1 - a-stpr-durata-tot-oggi += durata - a-stpr-durata-media-oggi = totale / n_cicli - Minimo durata = 1 secondo (evita divisioni per zero)


Tabelle database (PostgreSQL KPN)

In lettura/scrittura

Tabella Operazioni Campi chiave
ARPAZIEN Read/Rewrite razi-azi (PK). Config globale: attiva-sincro, standby, switch-onoff, sleep, reload, versioni
ARPPROC Read sequenziale a-proc-id (PK). Catalogo processi: prg, nome, des, modo-sched, tempo-std, operazione, padre-id
ARPSTPRC Read/Write/Rewrite a-stpr-id + a-stpr-azi (PK). Stato runtime: fl-attivazione, stato (A/I), att/sched/prec data-ora, tempo-attesa, direzione, esporta-tutto, forzo-ese, errori, statistiche
ARPPRCSCHED Read sequenziale a-prcs-id + a-prcs-azi + a-prcs-ora + a-prcs-day-of-week + a-prcs-day-of-month. Schedulazioni orarie fisse
ISTANZESYNC Read/Write/Rewrite a-ist-azi + a-ist-istanza (PK). Keepalive, contatori, versione, ultimo processo avviato/eseguito, fl-spenta, statistiche giornaliere
AGLSTORICOISTANZA Read/Write/Rewrite a-agsi-azi + a-agsi-istanza + a-agsi-data (PK). Snapshot giornaliero statistiche

File COBOL

File Utilizzo
COGCNF Configurazione locale (via RNEWCONF)
FEURTAB Tabella ausiliari (COGFILES)

File di controllo

Directory: ext-arc-dir/controllo/

File Suffisso istanza Creato da Funzione
aglancio-alive-NN.txt Si Keep-alive thread Heartbeat (creato/verificato ogni ciclo)
aglancio-check-NN.txt Si Keep-alive thread Status marker
aglancio-spegni-NN.txt Si GESSTPRC Trigger spegnimento (letto e cancellato)
aglancio-version.txt No AGLANCIO k-versione-x-script ("0003")
aglancio-istanze.txt No AGLANCIO/GESSTPRC Elenco numeri istanze attive
lancio-ambienti-version.txt No Script esterno Versione script di lancio
aglancio-istanze.error No Script esterno Trigger per reload istanze

Configurazione (COGCNF via RNEWCONF)

Pack Gruppo Chiave Tipo Default
C areaapp cod-azienda Stringa(6) -
C abilita attiva-areaapp S/N -
C areaapp db-log-level Numerico(2) -
C areaapp aglancio-sleep-seconds Numerico(6) 5 se 0
C AREAAPP AGLANCIO-ATTIVO S/N -
C AREAAPP AGLANCIO-CLOSE-DB S/N -

La stringa di connessione DB viene recuperata tramite CALL "SWGETS".


Copybook e moduli

Copybook specifiche

Copybook Contenuto
aglancio.select SELECT per file di servizio
aglancio.fd FD record file
aglancio.wrk Working-storage con dati runtime, SQL, processi
aglancio.decla DECLARATIVES gestione I/O
aglancio.prc Procedure SQL per tabelle PostgreSQL

Copybook standard

wstato, wopenf, wgrave, wnscr, cogazien, utils62, utilswgets, utilgesdate, utilgesdebug, utilncnf, utilagprg, l-copiaf, k-tipi-cogtabel, k-personal

Chiamate esterne

Programma Funzione
RNEWCONF Lettura configurazione
SWGETS Stringa connessione DB
COGS62 Calcolo differenze temporali
GESDATE Operazioni su date (info, somma giorni)
COPIAF Verifica esistenza file programma (.cob)
GESDEBUG Logging strutturato con prefisso istanza
C$SLEEP Pausa tra i cicli
C$NARG Conteggio argomenti linkage
C$MAKEDIR Creazione cartella controllo
POSTA Notifiche (cancellato in chiusura)
SWN* I 138 programmi di sincronizzazione (CALL dinamico via a-proc-prg)

Logging

AGLANCIO utilizza GESDEBUG con un override locale (local-gesdebug-linkage-common) che antepone il prefisso di istanza a ogni messaggio:

I-0: Messaggio...        (istanza 0)
I-5: Messaggio...        (istanza 5)
I99: Messaggio...        (istanza 99)

Livelli: S=trace, E=errore, W=warning, I=info, CRITICO (es2000).

L'istanza 99 (w-istanza-debug) produce logging aggiuntivo a livello trace per ogni processo esaminato.


Diagramma di sequenza - Lancio processo

AGLANCIO          ARPPROC          ARPSTPRC        SWN_XXX         ISTANZESYNC
    |                 |                |               |                |
    |--- Read next -->|                |               |                |
    |<-- processo ----|                |               |                |
    |                 |--- Read ------>|               |                |
    |                 |<-- stato ------|               |                |
    |                 |                |               |                |
    | [check: istanza? attivo? timeout?]               |                |
    |                 |                |               |                |
    |--- Rewrite: stato="I" --------->|               |                |
    |--- Rewrite: ultimo-id-avviato --|---------------|--------------->|
    |                 |                |               |                |
    |--- CALL --------|----------------|-------------->|                |
    |                 |                |               |--- sync -->    |
    |<-- return ------|----------------|---------------|                |
    |                 |                |               |                |
    |--- Rewrite: stato="A" --------->|               |                |
    |    + prossima esecuzione        |               |                |
    |    + statistiche                |               |                |
    |--- Rewrite: ultimo-id-eseguito -|---------------|--------------->|
    |                 |                |               |                |

Note implementative

  1. Ciclo a ripresa: dopo l'esecuzione di un processo SWN che apre un DB secondario, il cursore su ARPPROC viene invalidato. Per questo il ciclo esterno (m-ciclo-processi) riprende da w-id-processo-start = a-proc-id + 1, gestendo il caso in cui un solo processo viene eseguito per iterazione.

  2. Thread keep-alive: gira in background con priorita' 10 e crea i file di heartbeat. Se AGLANCIO e' bloccato in un SWN, il keep-alive continua a funzionare (tranne per istanze con DB secondario dove viene fermato).

  3. Check disponibilita' programmi: al ciclo iniziale, verifica per ogni processo se il file .cob esiste su disco (COPIAF fileinfo). Aggiorna a-stpr-processo-disponibile di conseguenza.

  4. Gestione sleep = 0: se il tempo di sleep non e' configurato, AGLANCIO lo segnala come errore critico e usa un fallback di 120 secondi.

  5. Script lancio_ambienti: AGLANCIO collabora con uno script esterno che gestisce il lancio e il monitoraggio delle istanze. La comunicazione avviene tramite i file nella cartella controllo.

  6. DB secondario: le istanze 92 e 99 originariamente usavano un DB separato (w-istanza-db-secondario). Il codice per fermere il keep-alive e' ancora attivo, ma il flag w-istanza-db-secondario e' forzato a "N" (commentato il codice che lo impostava a "S").

Cache processi (ottimizzazione)

A partire dalla modifica di aprile 2026, il ciclo processi utilizza una cache in working storage (w-cache-processi, max 1000 entry) che memorizza i dati di ARPSTPRC e ARPPROC. La cache viene popolata una sola volta nel paragrafo m-cerca-istanze-attive tramite x-popola-cache-processo e riutilizzata in m-ciclo-processi tramite x-copia-cache-su-a-stpr. Dopo l'esecuzione di ogni processo, la cache viene aggiornata da x-aggiorna-cache-dopo-esec.

Questo evita scansioni ripetute delle tabelle remote (ARPPROC, ARPSTPRC) ad ogni ciclo dello scheduler, migliorando le prestazioni in scenari con molti processi configurati. In caso di overflow (>1000 processi), viene emesso un log critico e i processi in eccesso non vengono caricati.