# Architettura

## Architettura generale

In questo e nei diagrammi che seguono è stato seguito il [Modello C4](https://c4model.com/) per la rappresentazione dei diagrammi architetturali. &#x20;

{% @mermaid/diagram content="C4Context
title System Context diagram for Opencity Italia

Enterprise\_Boundary(b0, "DatacenterBoundary") {

System\_Boundary(b1, "CmsBoundary"){
System(EzSystem, "CMS Core", "Permette ai redattori di gestire i contenuti e di pubblicarli secondo il modello prescelto.")
System(SolrService, "CMS Search Engine", "Permette la ricerca rapida dei contenuti del sito.")
}

System\_Boundary(b2, "ServicesBoundary"){
SystemQueue\_Ext(KafkaService, "Kafka", "Gestione asincrona di messaggi")

```
System(ServicesCore, "Servizi Digitali Core", "Gestione pratiche a istanza e appuntamenti")
System(AnalyticsSubsystem, "Analytics", "Gestione statistiche e rapporti")
System(PaymentsIntegrations, "Sistemi di pagamento", "Integrazioni con gli intermediari di pagamento PagoPA")
System(DocumentsIntegrations, "Sistemi di protocollazione", "Integrazioni con i sistemi di protocollazione")
```

}

System\_Ext(MailServer, "E-mail system", "Un servizio di invio e-mail.")
SystemDb\_Ext(PostgreSql, "PostgreSQL Database", "Main data persistence")
SystemDb\_Ext(MongoDb, "MongoDB Document Database", "Forms data persistence")

}

BiRel(ServicesCore, KafkaService, "Send messages")
Rel(AnalyticsSubsystem, KafkaService, "Read messages")
BiRel(PaymentsIntegrations, KafkaService, "Send & Read messages")
BiRel(DocumentsIntegrations, KafkaService, "Send & Read messages")

Person\_Ext(Citizen, "Visitatore del sito")
Person(RedattoreSito, "Redattore", "Gestisce i contenuti")
Person(AmministratoreSito, "Amministratore", "Gestisce utenti e impostazioni")
Person(ServicesOperator, "Operatore Servizi Digitali", "Gestisce pratiche e appuntamenti")

BiRel(Citizen, EzSystem, "Visits")
BiRel(RedattoreSito, EzSystem, "Uses")

Rel(EzSystem, MailServer, "Sends e-mails", "SMTP")
Rel(EzSystem, RedattoreSito, "Sends e-mails to")
Rel(ServicesCore, MailServer, "Sends e-mails", "SMTP")
Rel(ServicesCore, MongoDb, "Store forms")

Rel(EzSystem, PostgreSql, "Read\&Write data")
Rel(ServicesCore, PostgreSql, "Read\&Write data")

UpdateElementStyle(Citizen, $fontColor="white", $bgColor="grey", $borderColor="grey")
UpdateRelStyle(Citizen, EzSystem, $textColor="blue", $lineColor="blue", $offsetX="5")
UpdateRelStyle(EzSystem, MailServer, $textColor="blue", $lineColor="blue", $offsetY="-10")

UpdateRelStyle(SystemAA, SystemC, $textColor="blue", $lineColor="blue", $offsetY="-40", $offsetX="-50")
UpdateRelStyle(SystemC, customerA, $textColor="red", $lineColor="red", $offsetX="-50", $offsetY="20")

UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")

" %}

## Sito istituazionale

L'architettura del CMS è una classica architettura monolitica con un core in PHP e una persistenza principale (PostgreSQL) a cui si affiancano un motore di ricerca (Solr) e un layer di cache http (Varnish)

### Container diagram

{% @mermaid/diagram content="    C4Container
title Container diagram per il sito istituzionale

```
System_Ext(email_system, "E-Mail System", "An external e-mail delivery", $tags="v1.0")

Container_Boundary(c1, "CMS") {
    Container(cms-core, "CMS Core", "PHP, Docker container", "Core del CMS")        
    ContainerDb(solr, "SOLR", "Java, Docker container", "Motore di ricerca")
    ContainerDb_Ext(redis, "Redis", "Key-value store", "Persistenza temporanea per le sessioni utente")
    ContainerDb_Ext(postgresql, "PostgreSQL", "Database-as-a-service", "Persistenza princiapale dell'applicativo")
}

Rel(cms-core, solr, "indexes", "HTTP")
Rel(cms-core, postgresql, "store", "SQL")
Rel(cms-core, redis, "store", "custom")
UpdateRelStyle(cms-core, solr, $offsetY="20")
Rel(cms-core, email_system, "send", "SMTP")
```

UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")" %}

## Servizi digitali e area personale

L'architettura ha subito varie trasformazioni nel tempo e non può dirsi ancora definitiva, ma alcune caratteristiche sono ormai consolidate:&#x20;

* la decomposizione in microservizi con storage indipendenti e API ReST
* il sistema di scambio di messaggi basato su Kafka per rendere asincrone le interazioni tra i microservizi

{% @mermaid/diagram content="    C4Container
title Container diagram per i servizi digitali

```
Container_Boundary(c1, "Core") {
    Container(app-core, "", "", "")        
}

Container_Boundary(c2, "Analytics") {
    Container(analytics, "", "", "")        
}

Container_Boundary(c3, "Pagamenti") {
    Container(pagamenti, "", "", "")        
}
Container_Boundary(c4, "Protocolli") {
    Container(protocolli, "", "", "")        
}

SystemQueue_Ext(kafka, "Kafka", "Gestione asincrona di messaggi")

BiRel(app-core, kafka, "R/W Messages")
BiRel(analytics, kafka, "Read Messages")
BiRel(protocolli, kafka, "R/W Messages")
BiRel(pagamenti, kafka, "R/W Messages")
```

UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="2")

" %}

### Vista dettagliata di Services Core

Questa parte del sistema ha la maggior parte delle responsabilità relative alle pratiche al sistema di appuntamenti. E' costitutito da un core in symfony e da alcuni servizi al contorno che svolgono funzioni specifiche.

* **Kafka API**, è una istanza del server open-source Vector fornisce una interfaccia HTTP per Kafka
* **Gotenberg** è un tool opensource che la piattaforma utilizza per la creazione dei PDF
* **Form Server** è la nostra implementazione del server open-source Form.io, di cui usiamo nel core le librerie Javascript per il rendering delle form.
* **Form Builder** è una Single-Page-App in angular che include la libreria di Form.io per la creazione delle form. E' un servizio dedicato agli amministratori della piattaforma per la gestione di una libreria di componenti condivisi e riusabili dagli Enti nella creazione dei loro moduli: anagrafiche, definizione di immobili, autoveicoli etc...

{% @mermaid/diagram content="    C4Container
title Container diagram per il Core dei servizi digitali

```
Container_Boundary(c1, "Core") {
    Container(vector, "Kafka API", "Vector instance", "")
    Container(payment-updater, "Payments Updater", "Legge msg su Pagamenti e aggiorna le pratiche", "")
    Container(document-updater, "Documents Updater", "Legge msg su Documenti e aggiorna le pratiche", "")
    Container(app-core, "Services Core", "", "")
    Container(form-server, "Form Server", "", "")        
    Container(gotenberg, "PDF Generator", "Gotenberg Instance", "")
    Container(form-builder, "Form UI", "Angular SPA", "")
    Container(pdnd-connector, "PDND Connector", "Interagisce per conto dell'Ente con la piattaforma PDND", "")
}

SystemQueue_Ext(kafka, "Kafka", "Distributed message system")
SystemDb_Ext("postgresql", "PostgreSQL", "Main relational db")
SystemDb_Ext("redis", "Redis", "Key-value store")
SystemDb_Ext("mongo", "MongoDB", "Document database")

Rel(app-core, gotenberg, "Creates PDF from modules")
Rel(app-core, form-server, "Saves modules definitions")
Rel(app-core, pdnd-connector, "PDND e-services management")

Rel(app-core, vector, "Emit applications messages", "HTTP")
Rel(vector, kafka, "")

Rel(app-core, redis, "Sessions data", "")
UpdateRelStyle(app-core, redis, $offsetY="0", $offsetX="0")

Rel(app-core, postgresql, "", "")
UpdateRelStyle(app-core, postgresql, $offsetY="0", $offsetX="0")

Rel(form-server, mongo, "modules definition")
Rel(form-builder, form-server, "")


Rel(kafka, payment-updater, "Read topic payments")
Rel(payment-updater, app-core, "Update applications")

Rel(kafka, document-updater, "")
Rel(document-updater, app-core, "")

```

UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="2")

" %}

### Vista di dettaglio del sotto-sistema dei Pagamenti

TBD

### Vista di dettaglio del sotto-sistema dei Documenti

TBD

### Vista di dettaglio del sotto-sistema degli Analytics

{% @mermaid/diagram content="C4Container
title Container diagram per sistema di Analytics

```
Container_Boundary(c1, "Analytics") {
    
    Container(services-aggregator, "Services aggregator", "", "")
    Container(bookings-aggregator, "Bookings Aggregator", "", "")   
    Container(first-avail-aggregator, "First-Availability Aggregator", "", "")   
    Container(charts-exporter, "ChartJs Exporter", "API", "HTTP")   
    Container(grafana, "Grafana", "Internal data-visualization tool", "")   
}

SystemQueue_Ext(kafka, "Kafka", "Distributed message system")
SystemDb_Ext("clickhouse", "ClickHouse", "OLAP Database")

Rel(kafka, services-aggregator, "")
Rel(kafka, bookings-aggregator, "")
Rel(kafka, first-avail-aggregator, "")

Rel(services-aggregator, clickhouse, "")
Rel(bookings-aggregator, clickhouse, "")
Rel(first-avail-aggregator, clickhouse, "")

Rel(clickhouse, grafana, "")
Rel(clickhouse, charts-exporter, "")
```

UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="2")
" %}
