NexusFabricCereți o prezentare

Cazuri de utilizare

Șase situații pe care echipele le aduc unei platforme de integrare și cum se construiește fiecare pe NexusFabric. Urmează două industrii în care mai multe dintre ele se leagă în același lanț: energia și utilitățile, apoi sectorul public.

Fațadă peste un serviciu vechi

Un serviciu intern răspunde într-o formă pe care apelanții noi nu o pot consuma. Fluxul primește cererea nouă, o traduce, apelează serviciul vechi și compune răspunsul.

  • Ce acoperă

    Statusul backendului poate deveni statusul răspunsului, declarat de flux. Corpul de eroare al backendului e disponibil fluxului, deci o eroare se poate traduce, nu doar propaga. Anteturile răspunsului sunt dictate de flux, iar cele venite de la backend se întorc numai pe listă declarată.

Primire asincronă cu reîncercări

Un sistem trimite evenimente pe care nu le poate aștepta. Platforma le acceptă, le pune în coadă și le livrează mai departe, cu reîncercări.

  • Ce acoperă

    Coada are jurnal propriu: un mesaj acceptat supraviețuiește unei căderi, iar o reîncercare programată supraviețuiește unei reporniri. O livrare care iese pe secvența de tratare a erorii nu se comite ca reușită.

Cerere acum, răspuns peste ore

Un partener primește o cerere și răspunde mai târziu, pe alt canal. Platforma trebuie să știe la ce se referă răspunsul când sosește.

  • Ce acoperă

    Corelarea cerere/răspuns-întârziat se declară în flux și are termen obligatoriu: o așteptare fără capăt e o scurgere, nu o politică. Termenul depășit e reconciliat, iar așteptările deschise se pot lista din linia de comandă. Deduplicarea declarativă împiedică a doua livrare a aceleiași chei să ruleze din nou fluxul.

Integrare între servicii pe gRPC

Două servicii vorbesc gRPC, iar între ele trebuie să stea o traducere, o rutare sau o politică de reîncercare.

  • Ce acoperă

    Ieșirea gRPC lucrează cu descriptori încărcați dinamic, TLS reciproc, o cascadă de adrese și un întrerupător per adresă. Ușa de intrare gRPC rutează apelul prin aceeași poartă și aceeași paranteză de livrare ca ușa HTTP.

Mai multe organizații pe aceeași instalație

Un furnizor de servicii rulează integrări pentru mai mulți clienți, pe aceeași platformă.

  • Ce acoperă

    Tenantul e entitate înregistrată, creată deliberat; o greșeală de tastare nu devine tenant. O referință de bibliotecă se rezolvă în tenantul apelantului. Un tenant necunoscut și unul dezactivat răspund identic din afară. Interfața are roluri cu frontieră impusă, verificată rută cu rută.

Control al schimbării pe integrări

O echipă vrea ca o integrare greșită să pice la publicare, nu la primul mesaj de luni dimineață.

Fluxul pe care îl revizuiește echipa dumneavoastră. tests/battery/corpus/meridian/01-shipment-intake.flow.md. Pasul de ieșire, liniile 34-40, e lăsat afară.
## Step: check-booking
```validate
$.shipmentId != null    | "shipmentId is required"                    | syntactic
$.hubCode != null       | "hubCode is required"                       | syntactic
$.parcelCount > 0       | "parcelCount must be greater than zero"
$.weightKg > 0          | "weightKg must be greater than zero"
```

…

## Step: acknowledge
response_status: 202
```ntd
{
  "status": "ACCEPTED",
  "shipmentId": "{{ $.echo.shipmentId }}",
  "waybill": "{{ $.echo.waybill }}",
  "hubCode": "{{ $.echo.hubCode }}",
  "parcelCount": {{ $.echo.parcelCount }}
}
```
$ nexus validate flows/01-shipment-intake.flow.md
ok  flows/01-shipment-intake.flow.md
    flow:   shipment-intake
    tenant: meridian
    steps:  3
Un flux cu o construcție XSLT în afara subsetului acceptat: refuzat la publicare, nu executat altfel. tests/battery/corpus/acme/stricate/p10-xslt-necoborabil.flow.md, în întregime.
---
flowmarkdown_version: 0.1
flow: p10-xslt-necoborabil
tenant: acme
effects: []
---
## Step: x
```xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <xsl:template match="*">
    <copiat><xsl:value-of select="."/></copiat>
  </xsl:template>
</xsl:stylesheet>
```
$ nexus validate flows/p10-xslt-necoborabil.flow.md
error: step 'x': this XSLT sheet is outside the subset this platform compiles, and there is no XSLT engine at run time — unsupported XSLT construct <xsl:apply-templates>: recursive template application requires a runtime XSLT engine. Rewrite the step as `ntd`: it expresses the same transformations, and its failures are visible here rather than at the first message. `descendants()` covers `//name` searches, `string()` takes an element's text, and `{{ if }}` / `{{ for }}` cover `xsl:choose` and `xsl:for-each`
error: 1 validation error(s)
  • Ce acoperă

    Un XSLT în afara subsetului acceptat, un bloc de rutare cu formă greșită, un nume de flux ilegal sau un status literal invalid sunt refuzuri la publicare. O cheie de configurare declarată pe care instalația nu o oferă oprește pornirea, cu cheia numită.

  • Când ceva nu merge

    Refuzul vine la publicare, nu la primul mesaj de luni dimineață.

Energie și utilități

O companie de utilități are un portal pentru clienți, un sistem de măsurare și unul de facturare și schimbă cereri cu sistemele unor parteneri pe care nu le administrează. Unii parteneri vorbesc SOAP. Un partener care nu primește răspuns trimite aceeași cerere din nou, iar confirmarea lui poate sosi după câteva ore, pe alt apel.

  • O cerere trimisă de două ori nu se prelucrează de două ori

    Fluxul declară cheia după care două livrări sunt aceeași cerere. A doua livrare cu aceeași cheie nu mai rulează fluxul. Dacă prima a ieșit pe secvența de tratare a erorii, nu s-a comis ca reușită, deci o cerere corectată, retrimisă cu aceeași cheie, rulează.

  • Confirmarea SOAP venită târziu își găsește cererea

    Cererea deschide o corelare cu termen obligatoriu, iar confirmarea care sosește mai târziu este legată de ea. O așteptare care își depășește termenul e reconciliată. Plicul SOAP 1.1 sau 1.2 se despachetează, fluxul lucrează pe conținutul Body-ului, iar răspunsul pleacă în plicul aceleiași versiuni.

Cum se construiește lanțul

  1. Transformările se compilează la publicare: un XSLT în afara subsetului acceptat e refuzat, nu executat altfel.
  2. O cerere SOAP trece prin aceeași poartă ca oricare alta, iar un refuz e 401 sau 403 HTTP simplu, niciodată un SOAP Fault.
  3. Plicul SOAP 1.1 sau 1.2 se despachetează, iar fluxul lucrează pe conținutul Body-ului.
  4. validate refuză explicit, la prima regulă falsă; condition filtrează tăcut.
  5. A doua livrare a aceleiași chei nu mai rulează fluxul.
  6. Apelul către sistemul din spate deschide o corelare cu termen obligatoriu; termenul depășit e reconciliat.
  7. Răspunsul pleacă în plicul aceleiași versiuni, iar un flux care eșuează întoarce SOAP Fault, nu un corp de succes.
  8. O livrare care iese pe secvența de tratare a erorii nu se comite ca reușită, deci un duplicat corectat rulează.

Un exemplu de flux

Fluxul primește o cerere SOAP, deschide o așteptare la sistemul din spate și răspunde tot în SOAP. web/src/content/samples/acme-request-awaiting-confirmation.flow.md, în întregime.
---
flowmarkdown_version: 0.1
flow: request-awaiting-confirmation
tenant: acme
effects: [http_egress]
config: [PARTNER_ENDPOINT]
soap_operation: SubmitRequest
soap_namespace: urn:acme:requests
log_level: event_only
log_project: Acme
log_scenario: request-awaiting-confirmation
---

**A SOAP request in, a wait opened on the system behind, a SOAP answer out.** The caller speaks
SOAP 1.1. The platform unwraps the envelope, and the flow works on the `Body` content.

The flow builds a JSON request for the system behind it and sends it. That call opens a
correlation on the reference the system behind returns, with a deadline of four hours. The
confirmation that comes back later, on another call, is matched to this wait; a wait that
passes its deadline is reconciled.

The answer leaves in a SOAP 1.1 envelope, the version the caller used.

## Step: build-request
```ntd
{
  "requestId": "{{ $.requestId }}",
  "reference": "{{ $.reference }}",
  "supplyPoint": "{{ $.supplyPoint }}",
  "source": "soap-intake"
}
```

## Step: notify-system
effects: [http_egress]
endpoint: {{ ctx.PARTNER_ENDPOINT }}/requests
method: POST
content_type: application/json
correlation_open: "{{ $.reference }}"
correlation_state: { "requestId": "{{ $.requestId }}" }
correlation_deadline_ms: 14400000

## Step: answer-caller
```ntd
<SubmitRequestResponse>
  <code>100</code>
  <reference>{{ $.reference }}</reference>
  <status>{{ $.status }}</status>
</SubmitRequestResponse>
```
$ nexus validate web/src/content/samples/acme-request-awaiting-confirmation.flow.md
ok  web/src/content/samples/acme-request-awaiting-confirmation.flow.md
    flow:   request-awaiting-confirmation
    tenant: acme
    steps:  3

Sector public

Un serviciu pentru cetățean depinde adesea de date pe care le țin alte instituții. Sistemele lor se apelează între ele prin SOAP sau REST, iar mesajele poartă date personale. Fiecare apelant trebuie să se identifice înainte ca mesajul lui să fie citit, iar o eroare nu trebuie să repete ce conținea mesajul.

  • Sistemele altor instituții apelează prin SOAP sau REST, pe aceeași ușă închisă

    Metoda de autentificare se declară pentru fiecare tenant, iar o metodă pe care binarul instalat nu o poate executa e refuzată la înregistrare. Poarta e închisă implicit și rulează înaintea corpului: un apelant neautentificat nu provoacă nicio citire de corp și nicio parsare. O cerere SOAP trece prin aceeași poartă, iar un refuz e 401 sau 403 HTTP simplu, niciodată un SOAP Fault.

  • Un mesaj de eroare descrie forma datelor, nu datele personale

    Un mesaj de eroare de rulare poartă forma, nu conținutul: executorul nu inserează nicio valoare în mesajele lui de eroare. Corpul de eroare al unui backend ajunge la dispoziția fluxului, iar anteturile sensibile sunt reținute la captură. Un refuz atribuibil intră în lanțul de audit cu subiectul lui și nu poartă niciodată credențiala.

Cum se construiește lanțul

  1. Metoda de autentificare e proprietate declarată a tenantului; o metodă pe care binarul instalat nu o poate executa e refuzată la înregistrare.
  2. Poarta e închisă implicit: nexus serve cere o credențială, iar --no-auth e explicit și zgomotos.
  3. Poarta rulează înaintea corpului: un apelant neautentificat nu provoacă nicio citire de corp și nicio parsare.
  4. O cerere SOAP trece prin aceeași poartă, neschimbată, iar un refuz e 401 sau 403 HTTP simplu, niciodată un SOAP Fault.
  5. Un refuz atribuibil intră în lanțul de audit cu subiectul lui, nu poartă niciodată credențiala și consumă din plafonul apelantului.
  6. Corpul de eroare al unui backend ajunge la dispoziția fluxului, iar anteturile sensibile sunt reținute la captură.
  7. Un mesaj de eroare de rulare poartă forma, nu conținutul: executorul nu inserează nicio valoare în mesajele lui de eroare.

Un exemplu de flux

Mesajul fiecărei reguli numește un câmp, niciodată valoarea primită. web/src/content/samples/acme-application-check.flow.md, în întregime.
---
flowmarkdown_version: 0.1
flow: application-check
tenant: acme
effects: []
log_level: event_only
log_project: Acme
log_scenario: application-check
---

**An application checked at the door, and an error body that repeats no submitted value.** The
three `validate` rules check that the application names itself and counts its documents. Each
message names the field it checks; none quotes the value received.

The `## Fault:` section writes the error body as a problem document: the status, the message of
the rule that refused, and the name of the step.

## Step: check-application
```validate
$.applicationId != null  | "applicationId is required"              | syntactic
$.documentCount != null  | "documentCount is required"              | syntactic
$.documentCount > 0      | "documentCount must be greater than zero"
```

## Step: accept
```ntd
{ "status": "ACCEPTED", "applicationId": "{{ $.applicationId }}" }
```

## Fault: error-response
fault_header_content_type: application/problem+json
```ntd
{
  "title": "Application refused",
  "status": {{ number(ctx.fault_response_status) }},
  "detail": "{{ $.fault_error }}",
  "step": "{{ $.fault_step }}"
}
```
$ nexus validate web/src/content/samples/acme-application-check.flow.md
ok  web/src/content/samples/acme-application-check.flow.md
    flow:   application-check
    tenant: acme
    steps:  2