Destinazioni
Flowlyze supporta due modalità distinte di gestione della destinazione dati attiva e passiva consentendo una flessibilità elevata nell'integrazione con sistemi esterni e nella definizione delle strategie di elaborazione.
Le modalità di gestione delle destinazioni sono due:
- Attiva (push): Flowlyze invia i dati direttamente alla destinazione e garantisce la consegna.
- Passiva (pull): Flowlyze mette i dati a disposizione tramite una coda, e un sistema esterno li preleva autonomamente.
La scelta tra le due modalità dipende dalle esigenze di integrazione e dalla responsabilità che si vuole attribuire a ciascun sistema.
Gestione attiva
Nella gestione attiva, Flowlyze invia i dati direttamente alla destinazione configurata e si occupa di garantirne la consegna corretta.
Il sistema monitora ogni invio, gestisce eventuali tentativi di ritrasmissione e applica meccanismi di conferma per assicurarsi che il dato raggiunga effettivamente il target. In questa modalità Flowlyze agisce come componente responsabile dell'affidabilità del trasporto, riducendo la complessità a carico dei sistemi esterni.
Gestione passiva
Nella gestione passiva, Flowlyze funge da produttore di dati e li mette a disposizione tramite una coda o un meccanismo analogo. I messaggi vengono importati e mantenuti in attesa finché un sistema esterno non li elabora autonomamente, seguendo un modello simile al pattern publisher-subscriber.
Il sistema che consuma i dati effettua letture accompagnate da un acknowledge, tramite il quale notifica l'avvenuta ricezione al fine di garantire un flusso affidabile e una corretta gestione dello stato dei messaggi.
Destinazione HTTP
La destinazione HTTP di Flowlyze consente l'invio di dati verso sistemi esterni tramite richieste HTTP, una per ciascun messaggio presente in coda oppure una per blocco di messaggi. La richiesta viene costruita sulla base dei parametri configurati (metodo, endpoint, intestazioni, query string) mentre il body coincide con il payload JSON derivante dal singolo record.
L'esito dell'operazione è determinato esclusivamente dallo status code restituito dal sistema di destinazione: qualsiasi valore compreso tra 200 e 299 è considerato un successo.
Qualsiasi status code HTTP compreso tra 200 e 299 viene considerato un successo. Tutti gli altri codici (3xx, 4xx, 5xx) vengono trattati come errori e attivano le politiche di retry configurate.
Parametri configurabili
La destinazione HTTP mette a disposizione i seguenti parametri, tutti modificabili:
- URL: endpoint di destinazione della chiamata.
- Method: metodo HTTP utilizzato (es. POST, PUT, PATCH, DELETE).
- Headers: set di intestazioni personalizzate da includere nella richiesta.
- Query Params: parametri di query aggiunti all'URL.
Tutti i campi di tipo stringa supportano l'uso di variabili, sia globali sia locali, permettendo una configurazione dinamica in base al contesto operativo.
Autenticazione
La destinazione HTTP supporta gli stessi protocolli di autenticazione disponibili per la sorgente HTTP (vedi sezione dedicata), consentendo un allineamento coerente delle modalità di sicurezza.
Funzionalità pianificate (TBD)
Sono previste evoluzioni per estendere la flessibilità e le capacità di trasformazione della destinazione HTTP:
- Utilizzo dei campi del messaggio come template dinamici: Applicazione dei valori del messaggio ai parametri di URL, query e headers, con sostituzione diretta durante la generazione della richiesta.
- Riscrittura del body: Possibilità di definire un body personalizzato senza passare per componenti low-code.
- Interpretazione avanzata della risposta: Analisi del contenuto del body di risposta per determinare l'esito dell'operazione, superando il modello basato esclusivamente sullo status code.
- Invio batch di messaggi: Invio di multiple entità in un'unica chiamata, con definizione del modello dati aggregato e capacità di interpretare la risposta per valutare l'esito del singolo messaggio, in modo analogo al comportamento del Custom Adapter ma senza la necessità di un protocollo predefinito.
Destinazione RDBMS
La destinazione RDBMS consente a Flowlyze di collegarsi a qualunque database relazionale accessibile pubblicamente via Internet, senza dipendenze rispetto a uno specifico vendor. È pensata per implementare scenari di sincronizzazione dati, migrazione, consolidamento o integrazione bidirezionale tra sistemi.
Parametri di connessione
Per stabilire la connessione al database, Flowlyze richiede i seguenti parametri:
- URL del server
- Porta
- Username
- Password
La correttezza della connessione può essere verificata direttamente tramite l'apposita funzione di test disponibile nella schermata di configurazione.
Definizione delle query di scrittura
Flowlyze offre una gestione molto granulare delle operazioni SQL grazie a tre tipologie di query che coprono l'intero ciclo di elaborazione:
Le tre fasi (PREPARE → INSERT → FINALIZE) permettono di implementare logiche complesse:
- PREPARE: preparazione ambiente (tabelle temporanee, pulizia)
- INSERT: scrittura dati per ogni record
- FINALIZE: consolidamento e operazioni finali (upsert, stored procedure)
INSERT STATEMENT
Eseguito per ogni riga del set di dati. Consente di utilizzare uno statement SQL parametrico, dove i campi del record sono accessibili tramite:
@nomecampo@nomecampo_sottocampoper oggetti annidati
Generalmente questo statement è usato per eseguire INSERT, ma può essere qualunque comando SQL valido.
PREPARE STATEMENT
Eseguito prima dell'elaborazione di un batch.
Permette operazioni preparatorie come:
- creazione di tabelle temporanee,
- pulizia o inizializzazione di strutture dati,
- generazione di ambienti intermedi per la scrittura.
FINALIZE STATEMENT
Eseguito dopo l'inserimento di tutte le righe del batch.
È tipicamente utilizzato per:
- consolidare i dati nelle tabelle definitive,
- eseguire upsert,
- richiamare stored procedure,
- effettuare ricalcoli o operazioni di normalizzazione.
Esempio 1 — Scrittura in modalità insert or update
Questo esempio illustra un flusso di sincronizzazione clienti in cui un messaggio JSON viene trasformato in una riga della tabella relazionale **CUSTOMER**. Flowlyze esegue la query per ogni record in coda, mappando i campi del messaggio sui campi della tabella. L'obiettivo è dimostrare come un'integrazione semplice possa comunque supportare logiche più complesse come l'upsert (insert or update).
Struttura dati (diagramma Mermaid)
In questo modello:
- Il cliente è rappresentato da un'unica tabella
CUSTOMER. - I dati dell'indirizzo sono appiattiti in colonne dedicate (
ADDRESSSTREET,ADDRESSCITY, ecc.). - Tutte le informazioni anagrafiche e di preferenza sono centralizzate in un unico record per semplificare la gestione.
Intento e motivazioni dell'esempio
L'obiettivo dell'esempio è mostrare come un singolo messaggio JSON:
{
"customer_id": "CUST-482917",
"name": "Jordan Mitchell",
"date_of_birth": "1987-03-12",
"email": "jordan.mitchell@examplemail.com",
"phone": "(415) 555-2894",
"address": {
"street": "742 Market Street",
"unit": "Apt 5B",
"city": "San Francisco",
"state": "CA",
"zip": "94103"
},
"account_status": "Active",
"signup_date": "2023-08-19",
"preferred_contact_method": "Email",
"marketing_opt_in": true,
"notes": "Customer prefers weekend delivery windows."
}
venga convertito in una riga della tabella CUSTOMER tramite il seguente SQL:
INSERT INTO CUSTOMER (
CUSTOMERID,
NAME,
DATEOFBIRTH,
EMAIL,
PHONE,
ADDRESSSTREET,
ADDRESSUNIT,
ADDRESSCITY,
ADDRESSSTATE,
ADDRESSZIP,
ACCOUNTSTATUS,
SIGNUPDATE,
PREFERREDCONTACTMETHOD,
MARKETINGOPTIN,
NOTES
) VALUES (
@customer_id,
@name,
@date_of_birth,
@email,
@phone,
@address__street,
@address__unit,
@address__city,
@address__state,
@address__zip,
@account_status,
@signup_date,
@preferred_contact_method,
@marketing_opt_in,
@notes
);
Punti chiave della mappatura:
- I campi del messaggio sono mappati 1:1 sulle colonne della tabella.
- I valori annidati vengono referenziati tramite notazione a dot (
@address__street). - Il modello "flat" permette di rappresentare tutti i dati più rilevanti in una sola entità.
Per accedere a campi annidati nel JSON, usa la notazione con doppio underscore: @oggetto__campo. Ad esempio, @address__street accede a address.street nel messaggio JSON.
Esempio 2 — Scrittura in modalità transazionale
Questo esempio mostra un flusso di sincronizzazione ordini in cui un singolo messaggio di ordine viene scomposto in più entità relazionali (cliente, indirizzi, testata ordine, righe ordine) e scritto in modo coerente e transazionale. L'obiettivo è garantire che tutti i dati correlati a un ordine vengano inseriti/aggiornati insieme, oppure tutti scartati in caso di errore.
Tutte le operazioni vengono eseguite all'interno di un'unica transazione del database. Se un qualsiasi passaggio fallisce, l'intera transazione viene rollbackata, garantendo la coerenza dei dati.
Struttura dati
Come leggere il modello:
CUSTOMERrappresenta il cliente che effettua l'ordine (dati anagrafici e preferenze di contatto).ORDER_HEADERè la testata dell'ordine (data, stato, pagamenti, importi).ORDER_ITEMrappresenta le singole righe dell'ordine (articoli acquistati).ADDRESScontiene gli indirizzi collegati all'ordine (spedizione e fatturazione), associati sia al cliente sia all'ordine.
Le tabelle TMP_CUSTOMER, TMP_ORDER_HEADER, TMP_ORDER_ITEM e TMP_ADDRESS viste nello SQL sono la versione temporanea di queste stesse entità: fungono da staging area intermedia, usata per costruire un set di dati coerente prima del consolidamento sulle tabelle principali (CUSTOMER, ORDER_HEADER, ORDER_ITEM, ADDRESS).
Esempio di ordine (messaggio in ingresso)
{
"order_id": "ORD-984532",
"order_date": "2025-02-11T14:23:00Z",
"customer": {
"customer_id": "CUST-482917",
"first_name": "Jordan",
"last_name": "Mitchell",
"email": "jordan.mitchell@examplemail.com",
"phone": "+1-415-555-2894",
"alt_phone": "+1-415-555-7331",
"contact_preferences": {
"preferred_method": "Email",
"allow_sms": true,
"allow_calls": false
}
},
"items": [
{
"item_id": "SKU-10482",
"description": "Wireless Bluetooth Headphones",
"quantity": 1,
"unit_price": 89.99
},
{
"item_id": "SKU-55720",
"description": "USB-C Charging Cable 2m",
"quantity": 2,
"unit_price": 12.49
},
{
"item_id": "SKU-88410",
"description": "Laptop Sleeve 13-inch",
"quantity": 1,
"unit_price": 24.99
}
],
"shipping_address": {
"street": "742 Market Street",
"unit": "Apt 5B",
"city": "San Francisco",
"state": "CA",
"zip": "94103"
},
"billing_address": {
"street": "742 Market Street",
"unit": "Apt 5B",
"city": "San Francisco",
"state": "CA",
"zip": "94103"
},
"payment_method": "Credit Card",
"payment_status": "Paid",
"order_status": "Processing",
"currency": "USD",
"shipping_cost": 7.99,
"total_amount": 147.96,
"notes": "Leave the package at the building concierge."
}
Intento e motivazioni dell'esempio (lettura dell'SQL)
L'SQL fornito implementa una scrittura transazionale a più step, allineata con il modello di PREPARE / INSERT / FINALIZE della destinazione RDBMS.
Creazione delle tabelle temporanee (fase PREPARE)
CREATE TEMPORARY TABLE TMP_ADDRESS (...);
CREATE TEMPORARY TABLE TMP_CUSTOMER (...);
CREATE TEMPORARY TABLE TMP_ORDER_HEADER (...);
CREATE TEMPORARY TABLE TMP_ORDER_ITEM (...);
Motivazioni:
- creare una staging area transazionale, isolata dal modello dati finale;
- permettere di caricare e validare i dati dell'ordine (inclusi vincoli di chiave esterna tra TMP_*) prima del consolidamento;
- mantenere il batch "autocontenuto": ogni ordine (o gruppi di ordini) viene caricato in un set di tabelle temporanee coerenti.
In termini Flowlyze, questa parte appartiene alla fase PREPARE STATEMENT.
Scrittura nelle tabelle temporanee (fase INSERT STATEMENT)
Gli INSERT INTO TMP_* mappano direttamente il JSON sulle tabelle temporanee.
Indirizzi di spedizione e fatturazione
INSERT INTO TMP_ADDRESS (...) VALUES (
@shipping_address.id,
@shipping_address.street,
...
@customer__customer_id,
@order_id
);
INSERT INTO TMP_ADDRESS (...) VALUES (
@billing_address__id,
@billing_address__street,
...
@customer__customer_id,
@order_id
);
- Dal messaggio si estraggono due insiemi di dati (spedizione e fatturazione).
- Entrambi gli indirizzi sono collegati allo stesso
CUSTOMER_IDeORDER_ID. - I placeholder (es.
@shipping_address.street) rappresentano i campi del messaggio agganciati alla colonna corrispondente.
Cliente
INSERT INTO TMP_CUSTOMER (...) VALUES (
@customer.customer_id,
@customer.first_name,
@customer.last_name,
@customer.email,
@customer.phone,
@customer.alt_phone,
@customer.contact_preferences.preferred_method,
@customer.contact_preferences__allow_sms,
@customer.contact_preferences__allow_calls
);
- Si estrae l'oggetto
customere lo si normalizza in una riga diTMP_CUSTOMER. - Le preferenze di contatto vengono salvate in colonne dedicate (
PREFERRED_METHOD,ALLOW_SMS,ALLOW_CALLS).
Testata ordine
INSERT INTO TMP_ORDER_HEADER (...) VALUES (
@order_id,
@order_date,
@customer.customer_id,
@payment_method,
@payment_status,
@order_status,
@currency,
@shipping_cost,
@total_amount,
@notes
);
- Collega l'ordine al cliente (
CUSTOMER_ID) e contiene tutte le informazioni di pagamento e stato.
Righe ordine (loop sugli items)
- Per ogni elemento dell'array
itemsviene generato unINSERTinTMP_ORDER_ITEM. - Il costrutto
{{#each items}}indica un template iterativo: Flowlyze genera tantiINSERTquanti sono gli articoli nell'ordine. - Tutte le righe sono legate allo stesso
ORDER_ID, preservando la relazione 1–N tra ordine e righe.
Questa parte costituisce la fase INSERT STATEMENT della destinazione RDBMS, eseguita per ogni messaggio.
Consolidamento nelle tabelle finali (fase FINALIZE STATEMENT)
Dopo aver popolato le tabelle temporanee, l'SQL esegue il consolidamento verso le tabelle definitive (CUSTOMER, ORDER_HEADER, ADDRESS, ORDER_ITEM) usando INSERT ... SELECT ... ON DUPLICATE KEY UPDATE.
Esempio per CUSTOMER:
INSERT INTO CUSTOMER (...columns...)
SELECT
c.CUSTOMER_ID AS EXT_ID,
c.CUSTOMER_ID,
...
FROM TMP_CUSTOMER c
ON DUPLICATE KEY UPDATE
CUSTOMER_ID = VALUES(CUSTOMER_ID),
FIRST_NAME = VALUES(FIRST_NAME),
...
;
Stesso schema per:
ORDER_HEADER(tabella degli ordini),ADDRESS(indirizzi collegati a cliente/ordine),ORDER_ITEM(righe ordine).
Motivazioni chiave:
-
Upsert idempotente:
- Se il record non esiste →
INSERT. - Se il record esiste (stesso PK / chiave univoca) →
UPDATE.
Questo consente di rieseguire il flusso sullo stesso ordine senza creare duplicati, allineando la base dati allo stato più recente del sistema sorgente.
- Se il record non esiste →
-
Atomicità transazionale
- Tutte le operazioni (scrittura su TMP_*, consolidamento su tabelle finali) possono essere eseguite all'interno di un'unica transazione del database.
- Se un qualsiasi passaggio fallisce (es. errore di vincolo, dato incoerente), l'intera transazione può essere rollbackata, mantenendo i dati in uno stato consistente.
-
Separazione tra modellazione logica e origine dati
- Il messaggio JSON ha una struttura "orientata all'evento".
- Il database ha una struttura relazionale normalizzata.
- Le tabelle temporanee fungono da ponte: permettono trasformazioni, controlli, arricchimenti e gestione di vincoli prima dell'upsert definitivo.
-
Portabilità tra RDBMS
-
La sintassi ON DUPLICATE KEY UPDATE è tipica di MySQL, ma la logica di insert or update è replicabile su altri database:
- ON CONFLICT DO UPDATE in PostgreSQL,
- MERGE INTO ... WHEN MATCHED / NOT MATCHED in SQL Server (MSSQL) e Oracle.
-
In Flowlyze, la struttura PREPARE / INSERT / FINALIZE resta la stessa; cambia solo il dialetto SQL usato nel FINALIZE per adattarsi al RDBMS.
-
La sintassi ON DUPLICATE KEY UPDATE è specifica di MySQL. Per altri database:
- PostgreSQL: usa
ON CONFLICT DO UPDATE - SQL Server / Oracle: usa
MERGE INTO ... WHEN MATCHED / NOT MATCHED
Flat File
La destinazione Flat File consente di esportare un set di dati in uno o più file, secondo una logica completamente disaccoppiata dal formato del file, esattamente come avviene per la sorgente Flat File.
Il flusso definisce dove scrivere (location) e come formattare i dati (format), mentre Flowlyze gestisce la serializzazione e il trasferimento verso il sistema di destinazione.
Parametri di base
La destinazione Flat File espone i seguenti parametri principali:
-
Directory: Percorso remoto in cui i file verranno creati (directory FTP/SFTP/FTPS).
-
Filename: Nome del file da generare. Supporta placeholder e variabili del flusso, permettendo la costruzione dinamica del nome (es.
orders_{{date}}.csv). -
Location Type: Indica il canale di trasferimento utilizzato (es. SFTP, FTP…).
-
Granularity: Definisce il livello di granularità della scrittura, ovvero quanti file verranno generati. La selezione imposta un suffisso che viene inserito prima dell'estensione nel FileName
- Batch: un file per batch di esecuzione (singola esecuzione del flusso dati)
- Daily: un file per giorno
- RequestId: un file per gruppo di messaggi elaborati (parametro configurato nelle opzioni di BufferSize)
- Single With Time: per singolo messaggio,
- Single:nessuna granularità predefinita. Viene creato un file con nome FileName senza aggiunta di suffissi.
-
Connessione: Parametri di accesso al server di destinazione:
- host
- porta
- username
- password
Location Type
Attualmente la destinazione supporta tutte le varianti del protocollo FTP:
- FTP
- SFTP
- FTPS
- Amazon S3 (TBD)
- Azure Blob Storage (TBD)
Format Type
I formati attualmente disponibili sono:
- CSV
- JSON
Di seguito le configurazioni specifiche per ciascuno.
Format Settings — CSV
Parametri disponibili:
- Has headers: Indica se il file deve includere la riga di intestazione delle colonne.
- Culture: Cultura utilizzata per la rappresentazione di numeri e date (es.
it-IT→ usa virgola come separatore decimale,en-US→ punto decimale). - Delimiter: Delimitatore di colonna (
,,;,\t, …). - Quote: Carattere per racchiudere i campi testuali. Usare
\0per non applicare alcun quoting.
Format Settings — JSON
Parametri disponibili:
- Array field name: Indica il nome del campo che conterrà l'array.Se valorizzato: il JSON è scritto come oggetto, es. `
{ "data": [ {...}, {...} ] }`Se vuoto: viene scritto direttamente l'array in root: `[ {...}, {...} ]`
Mapping (solo CSV)
La destinazione Flat File permette di definire una mappatura delle colonne del file CSV. Attraverso la mappatura è possibile descrivere con precisione come verrà generato ogni campo del file.
Per ciascuna colonna è possibile specificare:
- Nome della colonna: Il nome riportato nell'intestazione (se
has headers = true). - Valore di default: Utilizzato se il campo non è presente nel messaggio.
- Tipo del campo:
string,int,decimal,datetime(influisce sulla formattazione e sulla cultura applicata). - Formato del campo: Esempi:
#.00per formattare decimali con due cifre,yyyy-MM-ddper date.
- Read format: Formato atteso in input, utile quando si devono convertire valori stringa in date o numeri strutturati durante la scrittura.
Custom Adapter
Oltre ai connettori standard (source e destination), Flowlyze può essere esteso tramite App esterne chiamate Custom Adapter.
Non esistono vincoli sulla tecnologia utilizzata: l'unico requisito è il supporto al protocollo HTTP, seguendo le regole definite dal protocollo di comunicazione.
Nel contesto del protocollo, il ruolo di System Integrator è svolto da Flowlyze, che invia richieste HTTP al Custom Adapter ed elabora le risposte.
Architettura e flussi di integrazione
Modalità di esecuzione
Il Custom Adapter prevede due modalità operative:
Modalità sincrona
- Flowlyze invia i dati in batch (ad esempio 1000 righe per volta) via API.
- Il Custom Adapter elabora il batch entro la singola chiamata HTTP e restituisce un payload standard che, per ogni messaggio, riporta:
- esito dell'elaborazione,
- eventuali errori e metadati.
- La chiamata è soggetta a timeout e a limitazioni sulla durata massima (tipicamente 30 secondi).
Questa modalità è adatta a integrazioni veloci, idempotenti e con volumi limitati per singolo batch.
Modalità asincrona
- Flowlyze invia i dati in batch come nel caso sincrono, ma il Custom Adapter può processarli in modo differito (job in background, code interne, ecc.).
- Nella risposta iniziale il Custom Adapter segnala che l'elaborazione è asincrona.
- Flowlyze effettua polling sul sistema di destinazione (tramite l'azione
progress) fino al completamento del job.
Questa modalità è ideale per elaborazioni più pesanti o lente, dove non è realistico concludere tutto entro il timeout di una singola richiesta HTTP.
La modalità sincrona ha un timeout tipico di 30 secondi. Se l'elaborazione richiede più tempo, utilizza la modalità asincrona.
Protocollo di comunicazione sincrono
Ogni sistema esterno che voglia ricevere dati da Flowlyze tramite Custom Adapter deve esporre uno o più endpoint HTTP.
Tutti gli endpoint condividono la stessa struttura di base del body:
{
"action": "execute",
"payload": { ... }
}
action: tipo di richiesta. I valori previsti sono:"execute"→ avvia l'elaborazione dei messaggi,"progress"→ (utilizzato nel flusso asincrono) richiede lo stato di avanzamento.
payload: contenuto specifico della richiesta, che varia in base all'azione.
Endpoint di esecuzione
`POST <dominio>/system-integrator/handler1 (action "execute")`
Questo endpoint viene chiamato da Flowlyze per consegnare un batch di messaggi da elaborare.
Request
{
"action": "execute",
"payload": {
"requestId": "<guid>",
"messages": [
{
"msgId": "<guid>",
"msg": {
"...": "..."
},
"meta": {
"...": "..."
}
}
],
"meta": {
"...": "..."
}
}
}
Significato dei campi:
payload.requestIdIdentificatore univoco della richiesta (batch) inviato da Flowlyze.payload.messagesArray dei messaggi da processare.payload.messages[i].msgIdIdentificatore univoco del singolo messaggio all'interno del batch.payload.messages[i].msgPayload effettivo del messaggio (record dati da elaborare).payload.messages[i].metaMetadati riferiti al singolo messaggio (contesto, configurazioni specifiche, ecc.).payload.meta`` Metadati condivisi da tutto il batch (es. stringhe di connessione, credenziali, endpoint downstream, parametri di configurazione).
Vincoli temporali e di esito
- Il sistema esterno deve processare la richiesta entro 30 secondi dall'invio.
- Obbligo HTTP 200:
- Se il sistema risponde con uno status diverso da
200, l'intera richiesta viene considerata fallita, e tutti i messaggi del batch risultano non elaborati. - Le politiche di retry configurate in Flowlyze si occuperanno di reinviare il batch o i messaggi non processati, secondo configurazione.
- Se il sistema risponde con uno status diverso da
Response sincrona
Se l'elaborazione viene gestita in modalità sincrona, il Custom Adapter risponde con:
{
"requestId": "<requestId>",
"isAsync": false,
"messages": [
{
"msgId": "<guid>",
"status": "success",
"date": "<date>",
"meta": { }
}
]
}
-
requestId`` Deve coincidere con quello ricevuto nella richiesta. -
isAsyncfalseindica che l'elaborazione è stata gestita tutta all'interno di questa chiamata. -
messagesArray di esiti per ogni messaggio inviato. -
messages[i].msgIdDeve corrispondere a unmsgIdprecedentemente inviato da Flowlyze. -
messages[i].statusStato dell'elaborazione del singolo messaggio:"success"→ messaggio elaborato correttamente,"error"→ elaborazione fallita,"in_progress"→ usato solo in scenari asincroni, quando l'elaborazione non è ancora terminata.
-
messages[i].dateData/ora di fine elaborazione in formato ISO8601. -
messages[i].metaEventuali metadati restituiti dal sistema esterno (es. ID di risorsa creata, messaggi di errore, log sintetico).
In caso di errore di elaborazione, i messaggi con status = "error" verranno gestiti da Flowlyze secondo le policy di retry configurate (nuovi tentativi, dead-letter, logging, ecc.).
Protocollo di comunicazione asincrono
In modalità asincrona:
-
Flowlyze invia una richiesta
action = "execute"identica al caso sincrono. -
Il Custom Adapter:
- risponde con
HTTP 200, - imposta
isAsync: true, - può marcare i messaggi come
"in_progress"finché l'elaborazione non è conclusa.
- risponde con
-
Flowlyze effettua chiamate successive con
action = "progress"per aggiornare lo stato dei messaggi associati a uno specificorequestId. -
Il Custom Adapter restituisce via via lo stato aggiornato (
success/error) per ognimsgId.
La struttura del body rimane allineata al contratto descritto in precedenza (stesso requestId, stessa lista messages con stato aggiornato).
Manifesto e discovery degli endpoint
Per permettere a Flowlyze di scoprire in modo dinamico quali handler sono esposti da un Custom Adapter, il sistema esterno deve pubblicare un manifesto in un endpoint ben noto.
Endpoint di discovery
**GET <dominio>/.well-known/system-integrator.json **
Risponde con un JSON della forma:
{
"version": 1,
"handlers": {
"handler1": "<dominio>/system-integrator/handler1",
"handler2": "<dominio>/system-integrator/handler2"
}
}
versionVersione del manifesto, utilizzata per compatibilità futura.handlersMappa[nome handler] → [endpoint handler]. Ogni handler rappresenta un punto di ingresso per l'elaborazione dei dati provenienti da un subscriber/flow diverso. In questo modo, un unico Custom Adapter può servire più flussi Flowlyze con logiche dedicate.handlers.<handler>URL dell'endpoint a cui Flowlyze invia le richiesteexecute progressrelative a quello specifico handler.
Vincoli:
- L'endpoint di discovery DEVE essere sempre esposto esattamente su
/.well-known/system-integrator.json. - Gli URL degli altri endpoint (handler) sono liberi, a discrezione del sistema esterno; l'esempio con
/system-integrator/handler1e/system-integrator/handler2rappresenta solo una convenzione consigliata.
Librerie
Vedi sezione Piattaforme\Custom per librerie e template di progetto
Null
La destinazione Null è una destinazione fittizia utilizzata quando non è necessario — o non è ancora disponibile — un vero sistema di destinazione.
Il suo unico scopo è ricevere i dati e registrarli nei log, senza effettuare alcuna elaborazione, trasformazione o invio verso sistemi esterni.
Questa destinazione risulta utile in diversi scenari, ad esempio:
- fase di sviluppo o test di un flusso, quando la destinazione reale non è pronta;
- verifica del corretto mapping e della serializzazione dei messaggi;
- diagnosi di comportamenti anomali a monte del flusso, isolando il problema.
Flowlyze conserva il messaggio nei log interni, permettendo di confermare la corretta ricezione e di analizzare facilmente il contenuto. Nessun altro processing viene eseguito.
La destinazione Null è particolarmente utile durante lo sviluppo e il debugging, permettendo di verificare che i dati arrivino correttamente al punto di destinazione senza dover configurare un sistema esterno.