@golemio/pid 6.0.1-dev.2901184022 → 6.0.1-dev.2912471131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/docs/architecture/diagrams/context.mmd +114 -0
  2. package/docs/architecture/diagrams/context.svg +1 -0
  3. package/docs/architecture/diagrams/platform-ingestion.mmd +94 -0
  4. package/docs/architecture/diagrams/platform-ingestion.svg +1 -0
  5. package/docs/architecture/diagrams/platform-serving.mmd +81 -0
  6. package/docs/architecture/diagrams/platform-serving.svg +1 -0
  7. package/docs/architecture/index.md +105 -0
  8. package/docs/assets/logos/README.md +38 -0
  9. package/docs/assets/logos/arriva.svg +9 -0
  10. package/docs/assets/logos/azure-blob-storage.svg +1 -0
  11. package/docs/assets/logos/azure-kubernetes-service.svg +1 -0
  12. package/docs/assets/logos/azure-table-storage.svg +1 -0
  13. package/docs/assets/logos/catch.png +0 -0
  14. package/docs/assets/logos/cd-telematika.png +0 -0
  15. package/docs/assets/logos/ceske-drahy.svg +15 -0
  16. package/docs/assets/logos/chaps.png +0 -0
  17. package/docs/assets/logos/citymove.png +0 -0
  18. package/docs/assets/logos/cloudflare.png +0 -0
  19. package/docs/assets/logos/dpp.svg +119 -0
  20. package/docs/assets/logos/envoy.svg +1 -0
  21. package/docs/assets/logos/golemio.svg +1 -0
  22. package/docs/assets/logos/google-maps.svg +78 -0
  23. package/docs/assets/logos/grafana-loki.png +0 -0
  24. package/docs/assets/logos/grafana.svg +57 -0
  25. package/docs/assets/logos/mikroelektronika.png +0 -0
  26. package/docs/assets/logos/nodejs.svg +39 -0
  27. package/docs/assets/logos/pid-litacka.svg +17 -0
  28. package/docs/assets/logos/pid.svg +1 -0
  29. package/docs/assets/logos/postgresql.svg +22 -0
  30. package/docs/assets/logos/rabbitmq.svg +54 -0
  31. package/docs/assets/logos/ropid.svg +1 -0
  32. package/docs/assets/logos/seznam.svg +115 -0
  33. package/docs/assets/logos/telmax.png +0 -0
  34. package/docs/assets/logos/typescript.svg +1 -0
  35. package/docs/assets/logos/valkey.svg +58 -0
  36. package/docs/assets/logos/varnish.svg +21 -0
  37. package/docs/asyncapi.yaml +5 -3
  38. package/docs/cache/types/redis.md +1 -1
  39. package/docs/implementation_documentation.md +40 -42
  40. package/docs/index.md +382 -0
  41. package/docs/jis/index.md +84 -94
  42. package/docs/openapi-input.yaml +3 -2
  43. package/docs/openapi-output.yaml +3 -1
  44. package/package.json +2 -2
  45. package/docs/architecture/pid_architecture_overview.drawio +0 -177
package/docs/jis/index.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Dokumentace propisu VYMI (JIS) dat do datové platformy
2
2
 
3
- Data událostí a infotextů jsou z aplikace VYMI aktivně posílána (push) do datové platformy Golemio, vždy ihned po změně v datech. Dále existuje možnost pasivního načtení (pull) dat z VYMI do Golemia, které je provedeno po manuální akci vývojáře a slouží například pro případ, že by došlo k výpadku aktivního posílání. Oba způsoby jsou zjednodušeně znázorněny na následujících dvou sekvenčních diagramech a podrobněji popsány v dalších sekcích.
3
+ Data událostí a infotextů jsou z aplikace VYMI aktivně posílána (push) do datové platformy Golemio, vždy ihned po změně v datech. Dále existuje pasivní načítání (pull) dat z VYMI do Golemia, které spouští pravidelně cron (každou minutu) nebo manuálně vývojář a slouží pro případ, že by došlo k výpadku aktivního posílání. Oba způsoby jsou zjednodušeně znázorněny na následujících dvou sekvenčních diagramech a podrobněji popsány v dalších sekcích.
4
4
 
5
5
  Sekvenční diagram znázorňující proces aktivního posílání (push) dat:
6
6
 
@@ -20,11 +20,11 @@ Sekvenční diagram znázorňující proces pasivního načítání (pull) dat:
20
20
  sequenceDiagram
21
21
  participant vymi as Aplikace VYMI
22
22
  participant golemio as Datová platforma Golemio
23
- actor developer as Vývojář
23
+ actor developer as Vývojář nebo cron
24
24
 
25
25
  developer->>golemio: Vyžádání načtení dat událostí nebo infotextů
26
- golemio->>vymi: Pasivní načtení (pull) dat událostí nebo infotextů z VYMI
27
- vymi->>golemio: Data událostí nebo infotextů
26
+ golemio->>vymi: Pasivní načtení (pull) dat událostí nebo infotextů z VYMI (s ETagem posledního načtení)
27
+ vymi->>golemio: Data událostí nebo infotextů (nebo HTTP 304, pokud se nezměnila)
28
28
  ```
29
29
 
30
30
  ## Změny dat ve VYMI
@@ -40,6 +40,7 @@ flowchart LR
40
40
  vymi_create_event("`Vytvoření události`");
41
41
  vymi_update_event("`Úprava události`");
42
42
  vymi_update_event_after_duplicate("`Uložení události po duplikaci`");
43
+ vymi_disable_event("`Zneplatnění (smazání) nebo obnovení události`");
43
44
  vymi_create_infotext("`Vytvoření infotextu`");
44
45
  vymi_update_infotext("`Úprava infotextu`");
45
46
  vymi_update_infotext_after_duplicate("`Uložení infotextu po duplikaci`");
@@ -47,6 +48,7 @@ flowchart LR
47
48
  %% invisible unicode char ‎ due to https://github.com/orgs/community/discussions/106690
48
49
  vymi_api_post_event["`HTTP POST s Ory Kratos session tokenem na http‎://api-vymi.golemio.cz/v1/events`"];
49
50
  vymi_api_put_event["`HTTP PUT s Ory Kratos session tokenem na http‎://api-vymi.golemio.cz/v1/events/{eventId}`"];
51
+ vymi_api_put_event_disable["`HTTP PUT s Ory Kratos session tokenem na http‎://api-vymi.golemio.cz/v1/events/{eventId}/disable nebo /enable`"];
50
52
  vymi_api_post_infotext["`HTTP POST s Ory Kratos session tokenem na http‎://api-vymi.golemio.cz/v1/events/{eventId}/infotexts`"];
51
53
  vymi_api_put_infotext["`HTTP PUT s Ory Kratos session tokenem na http‎://api-vymi.golemio.cz/v1/events/{eventId}/infotexts/{infotextId}`"];
52
54
  end
@@ -54,6 +56,7 @@ flowchart LR
54
56
  subgraph "VYMI Back End"
55
57
  vymi_events_controller_create["`V1EventsController.createEvent`"];
56
58
  vymi_events_controller_update["`V1EventsController.updateEvent`"];
59
+ vymi_events_controller_disable["`V1EventsController.disableEvent / enableEvent`"];
57
60
  vymi_infotexts_controller_create["`V1EventInfotextsController.createInfotext`"];
58
61
  vymi_infotexts_controller_update["`V1EventInfotextsController.updateInfotext`"];
59
62
  end
@@ -64,28 +67,33 @@ flowchart LR
64
67
  vymi_create_event --> vymi_api_post_event;
65
68
  vymi_update_event --> vymi_api_put_event;
66
69
  vymi_update_event_after_duplicate --> vymi_api_put_event;
70
+ vymi_disable_event --> vymi_api_put_event_disable;
67
71
  vymi_create_infotext --> vymi_api_post_infotext;
68
72
  vymi_update_infotext --> vymi_api_put_infotext;
69
73
  vymi_update_infotext_after_duplicate --> vymi_api_put_infotext;
70
74
 
71
75
  vymi_api_post_event -- "`Přes VYMI Ory Oathkeeper`" --> vymi_events_controller_create;
72
76
  vymi_api_put_event -- "`Přes VYMI Ory Oathkeeper`" --> vymi_events_controller_update;
77
+ vymi_api_put_event_disable -- "`Přes VYMI Ory Oathkeeper`" --> vymi_events_controller_disable;
73
78
  vymi_api_post_infotext -- "`Přes VYMI Ory Oathkeeper`" --> vymi_infotexts_controller_create;
74
79
  vymi_api_put_infotext -- "`Přes VYMI Ory Oathkeeper`" --> vymi_infotexts_controller_update;
75
80
 
76
81
  vymi_events_controller_create -- "`UPSERT do tabulek vymi-alerts.public.events a vymi-alerts.public.event_routes`" --> vymi_pg;
77
82
  vymi_events_controller_update -- "`UPSERT do tabulek vymi-alerts.public.events a vymi-alerts.public.event_routes`" --> vymi_pg;
78
- vymi_infotexts_controller_create -- "`UPSERT do tabulek vymi-alerts.public.infotexts a vymi-alerts.public.infotext_stops`" --> vymi_pg;
79
- vymi_infotexts_controller_update -- "`UPSERT do tabulek vymi-alerts.public.infotexts a vymi-alerts.public.infotext_stops`" --> vymi_pg;
83
+ vymi_events_controller_disable -- "`Nastavení / zrušení deleted_at v tabulkách vymi-alerts.public.events a vymi-alerts.public.infotexts (soft delete události i jejích infotextů)`" --> vymi_pg;
84
+ vymi_infotexts_controller_create -- "`UPSERT do tabulek vymi-alerts.public.infotexts, vymi-alerts.public.infotext_stops a vymi-alerts.public.infotext_presets`" --> vymi_pg;
85
+ vymi_infotexts_controller_update -- "`UPSERT do tabulek vymi-alerts.public.infotexts, vymi-alerts.public.infotext_stops a vymi-alerts.public.infotext_presets`" --> vymi_pg;
80
86
  ```
81
87
 
82
88
  ## Aktivní posílání (push) dat
83
89
 
84
- Po uložení změn událostí a infotextů do VYMI PostgreSQL databáze dojde vždy k aktivnímu poslání (push) "aktuálních" dat z VYMI back end služby do Golemia za pomoci HTTP POST dotazu na Golemio Vehicle Positions (VP) Input Gateway (IG).
85
- - u událostí se posílá pouze konkrétní nově vytvořená nebo upravená událost, nikoliv celý seznam aktuálních událostí.
86
- - všechny infotexty, které mají `status` `PUBLISHED`, `visibility` `PUBLIC` a zároveň `active_period_end` je `NULL` nebo >= aktuální čas, neboli lidsky všechny aktivní, budoucí a publikované (ne-draft) infotexty.
90
+ Po uložení změn událostí a infotextů do VYMI PostgreSQL databáze (vytvoření, úprava, zneplatnění nebo obnovení události; vytvoření nebo úprava infotextu) dojde vždy k aktivnímu poslání (push) "aktuálních" dat z VYMI back end služby do Golemia za pomoci HTTP POST dotazu na Golemio Vehicle Positions (VP) Input Gateway (IG).
91
+ - u událostí se posílá pouze konkrétní nově vytvořená, upravená, zneplatněná nebo obnovená událost (pole s nejvýše jednou položkou; pokud událost nesplňuje podmínky exportu uvedené v sekci [pasivního načítání](#pasivní-načítání-pull-dat), např. je draft, pošle se prázdné pole), nikoliv celý seznam aktuálních událostí. Po úpravě, zneplatnění nebo obnovení události se navíc pošle i celý seznam infotextů.
92
+ - u infotextů se vždy posílá celý seznam: všechny infotexty, které mají `status` `PUBLISHED`, `visibility` `PUBLIC`, nejsou smazané (`deleted_at` je `NULL`), mají alespoň jednu aktivní zastávku a zároveň `active_period_end` je `NULL` nebo >= aktuální čas (u infotextu, který konec aktivity dědí z události, se použije `active_period_end` události), neboli lidsky všechny aktivní, budoucí a publikované (ne-draft) infotexty.
87
93
 
88
- VP Input Gateway data přijme a zašle do odpovídající RabbitMQ fronty, odkud je převezme VP Integration Engine, který data zapíše do VP PostgreSQL databáze.
94
+ Selhání odeslání VYMI pouze zaloguje a neopakuje ho; výpadek pokryje nejbližší pasivní načítání (pull).
95
+
96
+ VP Input Gateway data zvaliduje JSON schématem (`JISEventsJsonSchema`, resp. `JISInfotextsJsonSchema`; při chybě vrací HTTP 422, jinak HTTP 204) a zašle do odpovídající RabbitMQ fronty (události s příznakem `shouldTriggerWebhooks: true`), odkud je převezme VP Integration Engine, který data zapíše do VP PostgreSQL databáze (viz [Chování databáze v Golemio](#chování-databáze-v-golemio)). Po uložení události se odešle [webhook](#webhook-výstup-updateeventwebhooktask), po uložení infotextů se přenačte Redis cache infotextů.
89
97
 
90
98
  Proces je podrobněji znázorněn na následujícím diagramu (detailnější prvky aplikační struktury jsou vynechány).
91
99
 
@@ -95,6 +103,7 @@ flowchart TB
95
103
  subgraph "VYMI Back End"
96
104
  vymi_events_controller_create["`V1EventsController.createEvent`"];
97
105
  vymi_events_controller_update["`V1EventsController.updateEvent`"];
106
+ vymi_events_controller_disable["`V1EventsController.disableEvent / enableEvent`"];
98
107
  vymi_infotexts_controller_create["`V1EventInfotextsController.createInfotext`"];
99
108
  vymi_infotexts_controller_update["`V1EventInfotextsController.updateInfotext`"];
100
109
 
@@ -112,17 +121,20 @@ flowchart TB
112
121
  subgraph "Golemio"
113
122
  subgraph "Golemio VP Input Gateway"
114
123
  golemio_events_controller["`JISEventsController`"];
115
- golemio_infotexts_controller["`JisInfotextsController`"];
124
+ golemio_infotexts_controller["`JISInfotextsController`"];
116
125
  end
117
126
 
118
127
  subgraph "Golemio RabbitMQ"
119
128
  golemio_rabbit_refresh_events["`Fronta vehicle-positions.jis.refreshJISEvents`"];
120
129
  golemio_rabbit_refresh_infotexts["`Fronta vehicle-positions.jis.refreshJISInfotexts`"];
130
+ golemio_rabbit_update_event_webhook["`Fronta vehicle-positions.jis.updateEventWebhook`"];
131
+ golemio_rabbit_refresh_infotexts_cache["`Fronta vehicle-positions.jis.refreshJISInfotextsCache`"];
121
132
  end
122
133
 
123
134
  subgraph "Golemio VP Integration Engine"
124
135
  golemio_refresh_events_task["`RefreshJISEventsTask`"];
125
136
  golemio_refresh_infotexts_task["`RefreshJISInfotextsTask`"];
137
+ golemio_update_event_webhook_task["`UpdateEventWebhookTask`"];
126
138
  golemio_refresh_infotexts_cache_task["`RefreshJISInfotextsCacheTask`"];
127
139
  end
128
140
 
@@ -130,14 +142,18 @@ flowchart TB
130
142
  vp_redis[("`VP Redis (Valkey)`")];
131
143
  end
132
144
 
145
+ webhook_targets["`Konzumenti webhooku (module.pid.jis.webhooks.eventUpdate.targets.\*)`"];
146
+
133
147
  vymi_events_controller_create --> vymi_get_events;
134
148
  vymi_events_controller_update --> vymi_get_events;
135
149
  vymi_events_controller_update --> vymi_get_infotexts;
150
+ vymi_events_controller_disable --> vymi_get_events;
151
+ vymi_events_controller_disable --> vymi_get_infotexts;
136
152
  vymi_infotexts_controller_create --> vymi_get_infotexts;
137
153
  vymi_infotexts_controller_update --> vymi_get_infotexts;
138
154
 
139
- vymi_get_events <-- "`SELECT aktuálních událostí z tabulek vehicle-positions.pid.jis_events a vehicle-positions.pid.jis_events_ropidgtfs_routes`" --> vymi_pg;
140
- vymi_get_infotexts <-- "`SELECT aktuálních infotextů z tabulek vehicle-positions.pid.jis_infotexts a vehicle-positions.pid.jis_infotexts_ropidgtfs_stops`" --> vymi_pg;
155
+ vymi_get_events <-- "`SELECT aktuálních událostí z tabulek vymi-alerts.public.events, vymi-alerts.public.event_routes, vymi-alerts.public.routes a vymi-alerts.public.event_attachments`" --> vymi_pg;
156
+ vymi_get_infotexts <-- "`SELECT aktuálních infotextů z tabulek vymi-alerts.public.infotexts, vymi-alerts.public.infotext_stops a vymi-alerts.public.infotext_presets`" --> vymi_pg;
141
157
 
142
158
  vymi_get_events --> golemio_api_post_events;
143
159
  vymi_get_infotexts --> golemio_api_post_infotexts;
@@ -145,38 +161,40 @@ flowchart TB
145
161
  golemio_api_post_events -- "`Přes Golemio Access Proxy`" --> golemio_events_controller;
146
162
  golemio_api_post_infotexts -- "`Přes Golemio Access Proxy`" --> golemio_infotexts_controller;
147
163
 
148
- golemio_events_controller --> golemio_rabbit_refresh_events;
164
+ golemio_events_controller -- "`shouldTriggerWebhooks: true`" --> golemio_rabbit_refresh_events;
149
165
  golemio_infotexts_controller --> golemio_rabbit_refresh_infotexts;
150
166
 
151
167
  golemio_rabbit_refresh_events --> golemio_refresh_events_task;
152
168
  golemio_rabbit_refresh_infotexts --> golemio_refresh_infotexts_task;
153
169
 
154
170
  golemio_refresh_events_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_events a vehicle-positions.pid.jis_events_ropidgtfs_routes`" --> vp_pg;
155
- golemio_refresh_infotexts_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_infotexts a vehicle-positions.pid.jis_infotexts_ropidgtfs_stops`" --> vp_pg;
156
- golemio_refresh_infotexts_task --> golemio_refresh_infotexts_cache_task;
171
+ golemio_refresh_events_task -- "`Jen pokud byla událost uložena`" --> golemio_rabbit_update_event_webhook;
172
+ golemio_rabbit_update_event_webhook --> golemio_update_event_webhook_task;
173
+ golemio_update_event_webhook_task -- "`HTTP POST`" --> webhook_targets;
157
174
 
158
- golemio_refresh_infotexts_cache_task -- "`Aktualizace cache jisCache:infotexts:* a jisCache:stop-infotexts:*`" --> vp_redis;
175
+ golemio_refresh_infotexts_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_infotexts, vehicle-positions.pid.jis_infotexts_ropidgtfs_stops a vehicle-positions.pid.jis_infotexts_presets, smazání chybějících`" --> vp_pg;
176
+ golemio_refresh_infotexts_task --> golemio_rabbit_refresh_infotexts_cache;
177
+ golemio_rabbit_refresh_infotexts_cache --> golemio_refresh_infotexts_cache_task;
178
+
179
+ golemio_refresh_infotexts_cache_task <-- "`SELECT infotextů se zastávkami`" --> vp_pg;
180
+ golemio_refresh_infotexts_cache_task -- "`Aktualizace cache jisCache:$setId:infotexts a jisCache:$setId:stops-infotexts`" --> vp_redis;
159
181
  ```
160
182
 
161
183
  Formát zasílaných dat je dále více popsán v implementační dokumentaci ([události](../implementation_documentation.md#jis-events-1), [infotexty](../implementation_documentation.md#jis-infotexts-1)), stejně tak jako odkazy na [Input Gateway OpenAPI](../implementation_documentation.md#input-api) a popis [uložení dat](../implementation_documentation.md#uložení-dat) včetně databázového schema a popisu retence. Data infotextů jsou dále cachovány - tento proces je popsán v dokumentaci [Redis cache](../cache/types/redis.md#cache-pro-api-přestupních-tabulí-transfer-boards).
162
184
 
163
185
  ## Pasivní načítání (pull) dat
164
186
 
165
- V případě potřeby (např. nedojde-li kvůli chybě k aktivnímu poslání dat) lze využít pasivní načtení (pull) dat z VYMI REST API do Golemia. Pro spuštění načtení může vývojář zaslat prázdnou zprávu do správné RabbitMQ fronty, kterou zkonzumuje VP Integration Engine a za pomoci HTTP GET dotazu získá data z VYMI back end služby.
187
+ V případě potřeby (např. nedojde-li kvůli chybě k aktivnímu poslání dat) lze využít pasivní načtení (pull) dat z VYMI REST API do Golemia. Pro spuštění načtení může vývojář zaslat prázdnou zprávu do RabbitMQ fronty `vehicle-positions.jis.fetchJISEvents` (události), resp. `vehicle-positions.jis.fetchJISInfotexts` (infotexty), kterou zkonzumuje VP Integration Engine a za pomoci HTTP GET dotazu získá data z VYMI back end služby. Získaná data zvaliduje stejným JSON schématem jako při aktivním posílání a zašle do fronty `refreshJISEvents`, resp. `refreshJISInfotexts`, odkud jsou zpracována stejně jako při aktivním posílání. Události z pasivního načítání mají příznak `shouldTriggerWebhooks: false`, tj. [webhook](#webhook-výstup-updateeventwebhooktask) se při nich neodesílá.
166
188
 
167
- Kromě manuálního spuštění vývojářem je nyní navíc aktivní cron task, který každou minutu automaticky spouští pasivní načítání dat z VYMI do Golemia. Tento mechanismus zajišťuje vyšší odolnost proti výpadkům v aktivním posílání (push) dat.
189
+ Kromě manuálního spuštění vývojářem je nyní navíc aktivní cron task, který každou minutu automaticky spouští pasivní načítání dat z VYMI do Golemia (routing keys `cron.vehicle-positions.jis.fetchJISEvents` a `cron.vehicle-positions.jis.fetchJISInfotexts`). Tento mechanismus zajišťuje vyšší odolnost proti výpadkům v aktivním posílání (push) dat.
168
190
 
169
- Při pasivním načítání dat z VYMI do Golemia se využívá mechanismus ETag, který umožňuje rozpoznat, zda se od posledního načtení data změnila. Díky tomu se při opakovaném dotazu přenášejí pouze nová nebo upravená data, zatímco v případě beze změny se vrací pouze informace o tom, že obsah zůstal stejný. Tento přístup zmenšuje objem přenášených dat a snižuje zátěž na databázi a server. ETagy jsou spravovány zvlášť pro události a pro infotexty, aby se změny každého typu vyhodnocovaly nezávisle.
191
+ Při pasivním načítání dat z VYMI do Golemia se využívá mechanismus ETag, který umožňuje rozpoznat, zda se od posledního načtení data změnila. Díky tomu se při opakovaném dotazu přenášejí pouze nová nebo upravená data, zatímco v případě beze změny se vrací pouze informace o tom, že obsah zůstal stejný. Tento přístup zmenšuje objem přenášených dat a snižuje zátěž na databázi a server. ETagy jsou spravovány zvlášť pro události a pro infotexty, aby se změny každého typu vyhodnocovaly nezávisle. ETag poslední odpovědi se ukládá v Redis (`jisMetadata:events`, `jisMetadata:infotexts`) a posílá se v hlavičce `If-None-Match`; při odpovědi HTTP 304 Not Modified se načítání ukončí bez dalšího zpracování.
170
192
 
171
193
  Při pasivním načítání se z VYMI vždy přenačítají pouze aktuální (aktivní) události a infotexty:
172
- - všechny události, které mají `status` `PUBLISHED`, a zároveň `updated_at` hodnotu z posledních 24 hodin nebo `active_period_end` je `NULL` nebo >= aktuální čas, neboli lidsky všechny publikované (ne-draft) události, které jsou aktivní nebo byly upraveny v posledním dnu;
173
- - všechny infotexty, které mají `status` `PUBLISHED`, `visibility` `PUBLIC` a zároveň `active_period_end` je `NULL` nebo >= aktuální čas, neboli lidsky všechny aktivní, budoucí a publikované (ne-draft) infotexty.
194
+ - všechny události, které mají `status` `PUBLISHED` a zároveň `display_period_end` nebo `active_period_end` je `NULL` nebo >= aktuální čas, nebo mají `updated_at` z posledních 24 hodin, neboli lidsky všechny publikované (ne-draft) události, které jsou zobrazované, aktivní nebo byly upraveny v posledním dnu; zahrnuty jsou i smazané (zneplatněné) události s vyplněným `deleted_at`;
195
+ - všechny infotexty se stejnými podmínkami jako při aktivním posílání (viz výše).
174
196
 
175
- ## Chování databáze v Golemio
176
-
177
- Události – v Golemio databázi se uchovávají všechny historické i aktuální události. Staré záznamy se nepromazávají.
178
-
179
- Infotexty – v Golemio databázi se uchovávají pouze aktivní infotexty. Neaktivní se při každém přenačtení promazávají.
197
+ Obsah exportu je shodný s daty aktivního posílání (`EventFacade.getFilteredCustomFormatList`, resp. `InfotextFacade.getFilteredCustomFormatList`). ETag generuje VYMI back end (Express) z těla odpovědi.
180
198
 
181
199
  Proces je podrobněji znázorněn na následujícím diagramu (detailnější prvky aplikační struktury jsou vynechány).
182
200
 
@@ -200,6 +218,7 @@ flowchart TB
200
218
  golemio_rabbit_fetch_infotexts["`Fronta vehicle-positions.jis.fetchJISInfotexts`"];
201
219
  golemio_rabbit_refresh_events["`Fronta vehicle-positions.jis.refreshJISEvents`"];
202
220
  golemio_rabbit_refresh_infotexts["`Fronta vehicle-positions.jis.refreshJISInfotexts`"];
221
+ golemio_rabbit_refresh_infotexts_cache["`Fronta vehicle-positions.jis.refreshJISInfotextsCache`"];
203
222
  end
204
223
 
205
224
  subgraph "Golemio VP Integration Engine"
@@ -218,14 +237,17 @@ flowchart TB
218
237
  vp_redis[("`VP Redis (Valkey)`")];
219
238
  end
220
239
 
221
- vymi_get_events <-- "`SELECT aktuálních událostí z tabulek vehicle-positions.pid.jis_events a vehicle-positions.pid.jis_events_ropidgtfs_routes`" --> vymi_pg;
222
- vymi_get_infotexts <-- "`SELECT aktuálních infotextů z tabulek vehicle-positions.pid.jis_infotexts a vehicle-positions.pid.jis_infotexts_ropidgtfs_stops`" --> vymi_pg;
240
+ vymi_get_events <-- "`SELECT aktuálních událostí z tabulek vymi-alerts.public.events, vymi-alerts.public.event_routes, vymi-alerts.public.routes a vymi-alerts.public.event_attachments`" --> vymi_pg;
241
+ vymi_get_infotexts <-- "`SELECT aktuálních infotextů z tabulek vymi-alerts.public.infotexts, vymi-alerts.public.infotext_stops a vymi-alerts.public.infotext_presets`" --> vymi_pg;
223
242
 
224
243
  golemio_rabbit_fetch_events --> golemio_fetch_events_task;
225
244
  golemio_rabbit_fetch_infotexts --> golemio_fetch_infotexts_task;
226
245
  golemio_rabbit_refresh_events --> golemio_refresh_events_task;
227
246
  golemio_rabbit_refresh_infotexts --> golemio_refresh_infotexts_task;
228
247
 
248
+ golemio_fetch_events_task <-- "`ETag jisMetadata:events`" --> vp_redis;
249
+ golemio_fetch_infotexts_task <-- "`ETag jisMetadata:infotexts`" --> vp_redis;
250
+
229
251
  golemio_fetch_events_task --> golemio_api_get_events;
230
252
  golemio_fetch_infotexts_task --> golemio_api_get_infotexts;
231
253
 
@@ -235,84 +257,52 @@ flowchart TB
235
257
  vymi_exports_controller_get_events --> vymi_get_events;
236
258
  vymi_exports_controller_get_infotexts --> vymi_get_infotexts;
237
259
 
238
- vymi_get_events --> golemio_rabbit_refresh_events;
239
- vymi_get_infotexts --> golemio_rabbit_refresh_infotexts;
260
+ golemio_fetch_events_task -- "`Data z VYMI (ne při HTTP 304), shouldTriggerWebhooks: false`" --> golemio_rabbit_refresh_events;
261
+ golemio_fetch_infotexts_task -- "`Data z VYMI (ne při HTTP 304)`" --> golemio_rabbit_refresh_infotexts;
240
262
 
241
263
  golemio_refresh_events_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_events a vehicle-positions.pid.jis_events_ropidgtfs_routes`" --> vp_pg;
242
- golemio_refresh_infotexts_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_infotexts a vehicle-positions.pid.jis_infotexts_ropidgtfs_stops`" --> vp_pg;
243
- golemio_refresh_infotexts_task --> golemio_refresh_infotexts_cache_task;
264
+ golemio_refresh_infotexts_task -- "`UPSERT do tabulek vehicle-positions.pid.jis_infotexts, vehicle-positions.pid.jis_infotexts_ropidgtfs_stops a vehicle-positions.pid.jis_infotexts_presets, smazání chybějících`" --> vp_pg;
265
+ golemio_refresh_infotexts_task --> golemio_rabbit_refresh_infotexts_cache;
266
+ golemio_rabbit_refresh_infotexts_cache --> golemio_refresh_infotexts_cache_task;
244
267
 
245
- golemio_refresh_infotexts_cache_task -- "`Aktualizace cache jisCache:infotexts:* a jisCache:stop-infotexts:*`" --> vp_redis;
268
+ golemio_refresh_infotexts_cache_task <-- "`SELECT infotextů se zastávkami`" --> vp_pg;
269
+ golemio_refresh_infotexts_cache_task -- "`Aktualizace cache jisCache:$setId:infotexts a jisCache:$setId:stops-infotexts`" --> vp_redis;
246
270
  ```
247
271
 
248
- Zdroj a formát dat pro aktivní stahování jsou dále více popsány v implementační dokumentaci ([události](../implementation_documentation.md#jis-events), [infotexty](../implementation_documentation.md#jis-infotexts)), stejně tak jako [worker a tasky](../implementation_documentation.md#jisworker) a popis [uložení dat](../implementation_documentation.md#uložení-dat) včetně databázového schema a popisu retence.
272
+ Zdroj a formát dat pro pasivní načítání jsou dále více popsány v implementační dokumentaci ([události](../implementation_documentation.md#jis-events), [infotexty](../implementation_documentation.md#jis-infotexts)), stejně tak jako [worker a tasky](../implementation_documentation.md#jisworker) a popis [uložení dat](../implementation_documentation.md#uložení-dat) včetně databázového schema a popisu retence.
249
273
 
250
- ## Datový model událostí — vybraná pole
274
+ ## Chování databáze v Golemio
251
275
 
252
- ### `cause_detail`
276
+ Zpracování každé zprávy probíhá v jedné databázové transakci; při chybě (validace, databáze) se zpráva zahodí bez opakování a data zůstanou beze změny. Retence (promazávání) JIS dat v `DataRetentionWorker` neprobíhá.
253
277
 
254
- Volitelné textové upřesnění příčiny události (`cause_detail`). Může být `null`. Dostupné v custom-format exportu (`/v1/jis/events/custom-format`) i v GTFS-RT alert feedu jako rozšíření. Struktura:
255
- ```json
256
- { "cs": "Nehoda na křižovatce", "en": null }
257
- ```
278
+ Události – v Golemio databázi se uchovávají všechny historické i aktuální události. Staré záznamy se nepromazávají. Událost smazaná ve VYMI (`deleted_at`) zůstává uložena se sloupcem `deleted_timestamp` a z výstupů (custom-format export, `alerts.pb`) je vyfiltrována.
279
+ - zpráva s jedinou událostí (aktivní posílání; VYMI posílá vždy nejvýše jednu událost) se uloží, jen pokud událost v databázi ještě není, nebo má novější `last_modified_timestamp` než uložený `updated_timestamp`, nebo se změnil `deleted_at`; jinak se jako zastaralá přeskočí (ochrana proti souběhu) a webhook se neodešle;
280
+ - zpráva s více událostmi (pasivní načítání) se uloží celá (UPSERT), bez porovnání časů;
281
+ - vazby událostí na linky (`jis_events_ropidgtfs_routes`) se u událostí ze zprávy nahradí aktuálním stavem, chybějící vazby se smažou.
258
282
 
259
- ### `cause` — anglický překlad
283
+ Infotexty – v Golemio databázi se uchovávají pouze aktivní infotexty. Každá zpráva obsahuje úplný seznam aktuálních infotextů:
284
+ - infotexty, které nemají ani zastávky (`informed_entity.stops`), ani presety (`informed_entity.presets`), se neukládají;
285
+ - infotexty (včetně vazeb na zastávky `jis_infotexts_ropidgtfs_stops` a presety `jis_infotexts_presets`), které v přijatém seznamu chybí, se smažou; prázdný seznam smaže všechny infotexty;
286
+ - existující infotext se přepíše, pokud je jeho `last_modified_timestamp` >= času posledního zápisu v Golemiu (`updated_at`), nebo se změnil `active_period`;
287
+ - po každém uložení se celá Redis cache infotextů `jisCache:*` přenačte (task `RefreshJISInfotextsCacheTask`).
260
288
 
261
- Pole `cause` obsahuje překlad příčiny události do češtiny i do angličtiny. Anglická hodnota je zahrnuta i ve výstupu GTFS-RT alert feedu (pole `Alert.cause` v `pid_feed.pb` i `alerts.pb`).
289
+ ## Výstupy dat
262
290
 
263
- ### Německá jazyková mutace (`de`)
291
+ ### Události — custom-format export (`GET /v1/jis/events/custom-format`)
264
292
 
265
- Pole `header_text`, `description_text`, `description_html` a `cause` mají v `/v1/jis/events/custom-format` a v odchozím webhooku i německou mutaci (`de`), kterou VYMI od issue [vymi-general#348](https://gitlab.com/operator-ict/golemio/jis/vymi-alerts/vymi-general/-/work_items/348) propaguje spolu s `cs`/`en`. Německé hodnoty pole `header_text`/`description_text`/`description_html` dodává přímo VYMI; hodnoty pole `cause` jsou naopak — stejně jako `cs`/`en` — mapované staticky v Golemiu (`JISEventTranslationHelper.causeToDe`), zatím jako provizorní překlady s prefixem `TMP:`, než budou nahrazeny finálními hodnotami.
293
+ Endpoint je interní (přístup jen s příslušnou rolí v Golemio Access Proxy). Vrací uložené události kromě smazaných (`deleted_timestamp`); interní události (`type` `INTERNAL`) jsou ve výchozím stavu vynechány a vrátí se jen při explicitním dotazu `type=INTERNAL`. Volitelné filtry: `organizationNames` (porovnává se po převodu na velká písmena), `type` a zobrazovací okno `displayPeriodStart`/`displayPeriodEnd` — událost je vrácena, pokud její `display_period` okno zasahuje do požadovaného intervalu (`display_period_end` je `NULL` nebo >= `displayPeriodStart` a zároveň `display_period_start` <= `displayPeriodEnd`):
266
294
 
267
- Pole `cause_detail`, `effect_detail`, `url` a jednotlivé `effects` němčinu nemají a nezískají ji — VYMI je vůbec neposílá s `de` hodnotou (validace na VYMI straně to explicitně zakazuje).
295
+ ![Filtrování událostí podle zobrazovacího okna](./diagram_display_start_end.svg)
268
296
 
269
- Na vstupu (IG, `POST /v1/jis/events`) je pole `de` u `header_text`/`effect_detail`/`description_text`/`description_html`/`url` sice ve schématu obecně povoleno (sdílí jeden validátor), ale v praxi ho VYMI vyplňuje jen u `header_text`/`description_text`/`description_html` — viz předchozí odstavec.
297
+ ### Události — GTFS-RT `alerts.pb`
270
298
 
271
- ### `attachments` (přílohy)
299
+ Feed generuje `GenerateFilesTask` (`GtfsRealTimeWorker`) a obsahuje jen události, které mají `type` `INCIDENT`, organizaci z `module.pid.jis.gtfsRt.events.allowedOrgs.*`, nejsou smazané a `active_period_end` je `NULL` nebo >= aktuální čas. Entita má id `alert-{id události}`, `informedEntity` obsahuje `routeId` GTFS-známých tras (viz [asymetrie](#asymetrie-gtfs-rt-protobuf-alertspb-vs-custom-format-webhook-výstup)), `url` je v případě nevyplněné hodnoty nahrazeno odkazem na detail mimořádnosti na webu PID. Texty jsou jen v `cs`/`en`.
272
300
 
273
- Pole `attachments` obsahuje dokumenty a odkazy přiložené k události (VYMI `kind: document|link`; vložené obrázky (`inline_image`) se nepropagují). Každá příloha má tvar:
274
- ```json
275
- { "url": "https://example.com/doc.pdf", "name": { "cs": "Dokument ke stažení", "en": "Document to download", "de": "Herunterladen" } }
276
- ```
277
- `name` může chybět i být prázdný objekt, pokud VYMI název přílohy nevyplnila. Pole je dostupné v `/v1/jis/events/custom-format` a v odchozím webhooku; do GTFS-RT alert feedu se nepropaguje.
278
-
279
- ### `effects` (pole příčin dopadu)
280
-
281
- Pole `effects` může obsahovat 1–3 unikátní řetězcové hodnoty. Pouze `effects[0]` se mapuje na standardní GTFS-RT `Alert.effect`; zbývající hodnoty jsou dostupné výhradně v custom-format exportu.
282
-
283
- ### `informed_entity.routes[].route_details` (snímek GTFS atributů trasy)
284
-
285
- Vedle kompatibilního identifikátoru `id` může VYMI u každé trasy poslat volitelné pole `route_details`
286
- (`route_id`, `route_short_name`, `route_long_name` — může být `null`, `route_type`). Jde o snímek GTFS
287
- atributů trasy v okamžiku, kdy VYMI událost odeslala — je zahrnut i pro trasy, které v aktuálním GTFS
288
- JŘ už neexistují nebo jsou neaktivní. Pole je v PID vstupním schématu (`JISEventsJsonSchema`) volitelné
289
- (není v `required` u položky `routes[]`), aby starší VYMI verze bez tohoto pole neselhávaly na validaci —
290
- je ale u nového VYMI producenta odesíláno vždy.
291
-
292
- `route_details` se ukládá tak, jak přišlo, do sloupce `jis_events_ropidgtfs_routes.route_details` (JSONB,
293
- nullable). Čtecí modely (custom-format export `/v1/jis/events/custom-format` a webhook `UpdateEventWebhookTask`)
294
- jsou **snapshot-first**: pokud je `route_details` u dané trasy vyplněné, použije se přímo bez dotazu do GTFS
295
- dat. Teprve u starších řádků, které vznikly před zavedením tohoto sloupce a mají `route_details = null`, se
296
- provede fallback dohledání aktuální GTFS trasy (`ropidgtfs_routes`) podle `id`. Pokud není k dispozici ani
297
- snímek, ani odpovídající GTFS trasa, je daná trasa z výstupu vynechána (chování shodné s obdobím před
298
- zavedením snímku, žádná regrese).
299
-
300
- ### Asymetrie GTFS-RT protobuf (`alerts.pb`) vs. custom-format / webhook výstup
301
-
302
- `getCurrentIncidents` (zdroj pro `alerts.pb`) používá vůči `ropidgtfs_routes` `required: true` (inner join) —
303
- událost, jejíž všechny trasy jsou v aktuálním GTFS neznámé nebo neaktivní, je z protobuf feedu úplně
304
- vynechána; u smíšené události (část tras GTFS zná, část ne) zůstanou v `alerts.pb` jen GTFS-známé trasy.
305
- Custom-format export a webhook naproti tomu GTFS-neznámé trasy zobrazují (díky `route_details` snímku).
306
- Tato asymetrie je záměrná — `alerts.pb` konzumují GTFS-RT klienti, kteří GTFS-neznámou trasu stejně neumí
307
- spárovat s jízdním řádem; custom-format/webhook konzumenti (např. web PID.cz) naopak potřebují zrušené/
308
- neaktivní linky zobrazit i bez GTFS záznamu.
309
-
310
- ### Webhook výstup (`UpdateEventWebhookTask`)
311
-
312
- Kromě uložení do databáze `UpdateEventWebhookTask` po přijetí události z VYMI odešle HTTP POST na cílové
313
- adresy nakonfigurované v `module.pid.jis.webhooks.eventUpdate.targets.*`. Tělo požadavku má stejný tvar jako
314
- `EventCustomFormat` (viz [openapi-output.yaml](../openapi-output.yaml)), navíc obsahuje pole
315
- `deleted_timestamp` (čas smazání události, nebo `null`) — to `/v1/jis/events/custom-format` nevrací a slouží
316
- konzumentům webhooku k rozpoznání smazaných událostí bez nutnosti dalšího dotazu. Trasy v `informed_entity.routes`
317
- jsou stejně jako u custom-format výstupu snapshot-first s GTFS fallbackem pro starší řádky bez snímku;
318
- při výpadku webhooku je fallbackem pro konzumenta dotaz na `/v1/jis/events/custom-format`.
301
+ ### Infotexty — GTFS-RT `pid_display_alerts.pb`
302
+
303
+ Experimentální feed pro e-paper displeje, generovaný stejným taskem. Obsahuje infotexty navázané na uloženou událost (`event_id` → `jis_infotexts.jis_event_id`), které jsou právě aktivní (včetně časového okna `repeat`) a mají zastávky. Na každé zastávce zůstanou jen infotexty s nejvyšší závažností (`JISInfotextStopSuppressionFilter`). Entita má id `alert-{id infotextu}`, `informedEntity` obsahuje `stopId`, `severityLevel` je `WARNING` pro `display_type` `INLINE` a `SEVERE` pro `GENERAL`; `descriptionText` pochází z infotextu, ostatní pole (`cause`, `cause_detail`, `effect`, `url`, `header_text`) z navázané události (i typu `INTERNAL`).
304
+
305
+ ### Infotexty — API odjezdových a přestupních tabulí
306
+
307
+ - `/v2/pid/departureboards`, `/v3/pid/transferboards` a `/v3/pid/infotexts` čtou infotexty z PostgreSQL; u odjezdových tabulí s parametrem `preset` se vrací jen infotexty navázané na daný preset (`jis_infotexts_presets.route_name`);
308
+ - `/v4/pid/transferboards` čte infotexty z Redis cache `jisCache:*`.
@@ -11,9 +11,9 @@ info:
11
11
  email: golemio@operatorict.cz
12
12
  url: https://golemio.cz
13
13
  servers:
14
- - url: https://api.golemio.cz/v2
14
+ - url: https://api.golemio.cz/input-gateway/v1
15
15
  description: Main (production) server
16
- - url: https://rabin.golemio.cz/v2
16
+ - url: https://rabin.golemio.cz/input-gateway/v1
17
17
  description: Test (development) server
18
18
  tags:
19
19
  - name: 🛤 Vehicle Positions
@@ -549,6 +549,7 @@ components:
549
549
  - INCIDENT
550
550
  - DISRUPTION
551
551
  - SERVICE_CHANGE
552
+ - INTERNAL
552
553
  header_text:
553
554
  type: object
554
555
  properties:
@@ -2085,11 +2085,12 @@ paths:
2085
2085
  schema:
2086
2086
  type: string
2087
2087
  example: "INCIDENT"
2088
- description: Type of events to filter by.
2088
+ description: Type of events to filter by. Events of type INTERNAL are excluded from the response unless explicitly requested with this parameter.
2089
2089
  enum:
2090
2090
  - INCIDENT
2091
2091
  - DISRUPTION
2092
2092
  - SERVICE_CHANGE
2093
+ - INTERNAL
2093
2094
  responses:
2094
2095
  200:
2095
2096
  description: OK
@@ -4111,6 +4112,7 @@ components:
4111
4112
  - INCIDENT
4112
4113
  - DISRUPTION
4113
4114
  - SERVICE_CHANGE
4115
+ - INTERNAL
4114
4116
  header_text:
4115
4117
  type: object
4116
4118
  properties:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@golemio/pid",
3
- "version": "6.0.1-dev.2901184022",
3
+ "version": "6.0.1-dev.2912471131",
4
4
  "description": "Golemio PID Module",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -63,7 +63,7 @@
63
63
  "coverage:only": "c8 npm run test:only -- --reporter min",
64
64
  "code-coverage": "run-s prepare-db typecheck build coverage:only",
65
65
  "format:check-staged": "pretty-quick --staged --pattern '**/*.ts'",
66
- "generate-docs": "typedoc --out docs/typedoc src",
66
+ "generate-docs": "typedoc --tsconfig tsconfig.build.json --out docs/typedoc src",
67
67
  "lint": "eslint --cache \"{src,test}/**/*.ts\"",
68
68
  "validate-dependencies": "dependency-cruiser --config .dependency-cruiser.cjs src"
69
69
  },
@@ -1,177 +0,0 @@
1
- <mxfile modified="2023-05-23T09:47:11.166Z" host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.8 Chrome/112.0.5615.165 Electron/24.2.0 Safari/537.36" etag="4dM1wg4TBuCNhn9Dqkni" version="21.2.8" type="device">
2
- <diagram id="WI9T0HZ2pTsCkuznbFz-" name="Page-1">
3
- <mxGraphModel dx="1418" dy="828" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
4
- <root>
5
- <mxCell id="0" />
6
- <mxCell id="1" parent="0" />
7
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-39" value="" style="rounded=1;whiteSpace=wrap;html=1;movable=0;resizable=0;rotatable=0;deletable=0;editable=0;locked=1;connectable=0;" vertex="1" parent="1">
8
- <mxGeometry x="164.8" y="90" width="975.2" height="760" as="geometry" />
9
- </mxCell>
10
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-20" value="" style="rounded=1;whiteSpace=wrap;html=1;align=left;" vertex="1" parent="1">
11
- <mxGeometry x="380" y="127.4" width="140" height="198" as="geometry" />
12
- </mxCell>
13
- <mxCell id="AcxdMaKK0mU5kZiv2lnr-9" value="Azure Blob&lt;br&gt;Storage&lt;br&gt;" style="aspect=fixed;html=1;perimeter=none;align=center;shadow=0;dashed=0;image;fontSize=12;image=img/lib/mscae/BlobBlock.svg;" parent="1" vertex="1">
14
- <mxGeometry x="422" y="396" width="62" height="53" as="geometry" />
15
- </mxCell>
16
- <mxCell id="Yb9yHQ_m3vMcTtYt7nYP-4" value="Cron" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=none;fillColor=#2875E2;shape=mxgraph.azure.scheduler;pointerEvents=1;rotation=0;" parent="1" vertex="1">
17
- <mxGeometry x="803" y="188" width="70" height="80" as="geometry" />
18
- </mxCell>
19
- <mxCell id="Yb9yHQ_m3vMcTtYt7nYP-5" value="Azure Flexible PostgreSQL" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=none;fillColor=#2875E2;shape=mxgraph.azure.sql_database_sql_azure;rotation=0;" parent="1" vertex="1">
20
- <mxGeometry x="615.25" y="560" width="70" height="80" as="geometry" />
21
- </mxCell>
22
- <mxCell id="Yb9yHQ_m3vMcTtYt7nYP-6" value="Uživatelé" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=none;fillColor=#00BEF2;shape=mxgraph.azure.user;" parent="1" vertex="1">
23
- <mxGeometry x="1213.25" y="564.5" width="47.5" height="50" as="geometry" />
24
- </mxCell>
25
- <mxCell id="Yb9yHQ_m3vMcTtYt7nYP-7" value="Input Gateway" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=api" parent="1" vertex="1">
26
- <mxGeometry x="425" y="145.2" width="50" height="48" as="geometry" />
27
- </mxCell>
28
- <mxCell id="Yb9yHQ_m3vMcTtYt7nYP-8" value="Output Gateway" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=api" parent="1" vertex="1">
29
- <mxGeometry x="800" y="560" width="80" height="70" as="geometry" />
30
- </mxCell>
31
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-1" value="Data Proxy" style="pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;fillColor=#2875E2;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;outlineConnect=0;shape=mxgraph.veeam.2d.proxy_appliance;" vertex="1" parent="1">
32
- <mxGeometry x="210" y="192" width="74.8" height="78" as="geometry" />
33
- </mxCell>
34
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-2" value="API key Management" style="verticalLabelPosition=bottom;html=1;verticalAlign=top;align=center;strokeColor=none;fillColor=#2875E2;shape=mxgraph.azure.access_control;" vertex="1" parent="1">
35
- <mxGeometry x="1016" y="384" width="50" height="50" as="geometry" />
36
- </mxCell>
37
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-3" value="Integration Engine" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=pod;rotation=0;" vertex="1" parent="1">
38
- <mxGeometry x="601" y="380" width="80" height="70" as="geometry" />
39
- </mxCell>
40
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-5" value="Permission proxy" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=role;rotation=0;" vertex="1" parent="1">
41
- <mxGeometry x="1002" y="562" width="80" height="70" as="geometry" />
42
- </mxCell>
43
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-8" value="TCP Input Gateway" style="sketch=0;html=1;dashed=0;whitespace=wrap;fillColor=#2875E2;strokeColor=#ffffff;points=[[0.005,0.63,0],[0.1,0.2,0],[0.9,0.2,0],[0.5,0,0],[0.995,0.63,0],[0.72,0.99,0],[0.5,1,0],[0.28,0.99,0]];verticalLabelPosition=bottom;align=center;verticalAlign=top;shape=mxgraph.kubernetes.icon;prIcon=master" vertex="1" parent="1">
44
- <mxGeometry x="425" y="233.2" width="50" height="48" as="geometry" />
45
- </mxCell>
46
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-9" value="RabbitMQ&lt;br&gt;" style="sketch=0;outlineConnect=0;fontColor=#232F3E;gradientColor=none;fillColor=#2875E2;strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.mq_broker;fillStyle=auto;rotation=0;" vertex="1" parent="1">
47
- <mxGeometry x="601" y="191.4" width="80" height="70" as="geometry" />
48
- </mxCell>
49
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-12" value="Redis" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.cache_node;fillColor=#2875E2;gradientColor=none;" vertex="1" parent="1">
50
- <mxGeometry x="812" y="380" width="60" height="63" as="geometry" />
51
- </mxCell>
52
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-13" value="Url Proxy" style="image;aspect=fixed;html=1;points=[];align=center;fontSize=12;image=img/lib/azure2/ai_machine_learning/Translator_Text.svg;" vertex="1" parent="1">
53
- <mxGeometry x="1016" y="740" width="50" height="50" as="geometry" />
54
- </mxCell>
55
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-17" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
56
- <mxGeometry width="50" height="50" relative="1" as="geometry">
57
- <mxPoint x="528.5" y="229" as="sourcePoint" />
58
- <mxPoint x="588.5" y="229" as="targetPoint" />
59
- </mxGeometry>
60
- </mxCell>
61
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-21" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
62
- <mxGeometry width="50" height="50" relative="1" as="geometry">
63
- <mxPoint x="300" y="233.20000000000002" as="sourcePoint" />
64
- <mxPoint x="360" y="233.20000000000002" as="targetPoint" />
65
- </mxGeometry>
66
- </mxCell>
67
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-22" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
68
- <mxGeometry width="50" height="50" relative="1" as="geometry">
69
- <mxPoint x="790" y="230" as="sourcePoint" />
70
- <mxPoint x="700" y="229" as="targetPoint" />
71
- </mxGeometry>
72
- </mxCell>
73
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-23" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
74
- <mxGeometry width="100" height="100" relative="1" as="geometry">
75
- <mxPoint x="640" y="370" as="sourcePoint" />
76
- <mxPoint x="640" y="295" as="targetPoint" />
77
- </mxGeometry>
78
- </mxCell>
79
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-24" value="cache pro výpočty" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
80
- <mxGeometry y="-30" width="100" height="100" relative="1" as="geometry">
81
- <mxPoint x="691" y="412" as="sourcePoint" />
82
- <mxPoint x="791" y="412" as="targetPoint" />
83
- <mxPoint as="offset" />
84
- </mxGeometry>
85
- </mxCell>
86
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-26" value="cache pro requesty" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
87
- <mxGeometry y="-60" width="100" height="100" relative="1" as="geometry">
88
- <mxPoint x="841" y="553" as="sourcePoint" />
89
- <mxPoint x="841" y="473" as="targetPoint" />
90
- <mxPoint as="offset" />
91
- </mxGeometry>
92
- </mxCell>
93
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-28" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
94
- <mxGeometry width="100" height="100" relative="1" as="geometry">
95
- <mxPoint x="1040" y="550" as="sourcePoint" />
96
- <mxPoint x="1040" y="470" as="targetPoint" />
97
- </mxGeometry>
98
- </mxCell>
99
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-29" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
100
- <mxGeometry width="100" height="100" relative="1" as="geometry">
101
- <mxPoint x="890" y="600" as="sourcePoint" />
102
- <mxPoint x="990" y="600" as="targetPoint" />
103
- </mxGeometry>
104
- </mxCell>
105
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-31" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
106
- <mxGeometry width="100" height="100" relative="1" as="geometry">
107
- <mxPoint x="1040" y="733" as="sourcePoint" />
108
- <mxPoint x="1040" y="653" as="targetPoint" />
109
- </mxGeometry>
110
- </mxCell>
111
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-32" value="" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
112
- <mxGeometry width="50" height="50" relative="1" as="geometry">
113
- <mxPoint x="1090" y="600" as="sourcePoint" />
114
- <mxPoint x="1190" y="600" as="targetPoint" />
115
- </mxGeometry>
116
- </mxCell>
117
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-33" value="Informační tabule&lt;br&gt;" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.hardware_board;fillColor=#00BEF2;gradientColor=none;" vertex="1" parent="1">
118
- <mxGeometry x="1202" y="714.75" width="84" height="100.5" as="geometry" />
119
- </mxCell>
120
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-34" value="" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
121
- <mxGeometry width="50" height="50" relative="1" as="geometry">
122
- <mxPoint x="1080" y="760" as="sourcePoint" />
123
- <mxPoint x="1190" y="760" as="targetPoint" />
124
- </mxGeometry>
125
- </mxCell>
126
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-35" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
127
- <mxGeometry width="100" height="100" relative="1" as="geometry">
128
- <mxPoint x="690" y="594.5" as="sourcePoint" />
129
- <mxPoint x="790" y="594.5" as="targetPoint" />
130
- </mxGeometry>
131
- </mxCell>
132
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-37" value="Realtime data" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
133
- <mxGeometry width="50" height="50" relative="1" as="geometry">
134
- <mxPoint x="40" y="240" as="sourcePoint" />
135
- <mxPoint x="200" y="240" as="targetPoint" />
136
- </mxGeometry>
137
- </mxCell>
138
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-38" value="Periodická aktualizace dat (jízdní řády apob.)" style="endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
139
- <mxGeometry width="50" height="50" relative="1" as="geometry">
140
- <mxPoint x="580" y="470" as="sourcePoint" />
141
- <mxPoint x="50" y="564.5" as="targetPoint" />
142
- <Array as="points">
143
- <mxPoint x="460" y="565" />
144
- </Array>
145
- </mxGeometry>
146
- </mxCell>
147
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-40" value="Datová platforma Golemio" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
148
- <mxGeometry x="870" y="90" width="180" height="30" as="geometry" />
149
- </mxCell>
150
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-43" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1">
151
- <mxGeometry width="100" height="100" relative="1" as="geometry">
152
- <mxPoint x="640.5" y="554" as="sourcePoint" />
153
- <mxPoint x="640.5" y="474" as="targetPoint" />
154
- </mxGeometry>
155
- </mxCell>
156
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-50" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
157
- <mxGeometry width="50" height="50" relative="1" as="geometry">
158
- <mxPoint x="450" y="330" as="sourcePoint" />
159
- <mxPoint x="450" y="390" as="targetPoint" />
160
- </mxGeometry>
161
- </mxCell>
162
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-53" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
163
- <mxGeometry width="50" height="50" relative="1" as="geometry">
164
- <mxPoint x="840" y="720" as="sourcePoint" />
165
- <mxPoint x="840" y="660" as="targetPoint" />
166
- </mxGeometry>
167
- </mxCell>
168
- <mxCell id="dkLkBtVoeD-QzUvh4KKE-54" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;" edge="1" parent="1">
169
- <mxGeometry width="50" height="50" relative="1" as="geometry">
170
- <mxPoint x="590" y="420" as="sourcePoint" />
171
- <mxPoint x="496" y="420" as="targetPoint" />
172
- </mxGeometry>
173
- </mxCell>
174
- </root>
175
- </mxGraphModel>
176
- </diagram>
177
- </mxfile>