2017-12-15 1 views
1

Wenn ein Knoten seine eigene spezifische Geschäftslogik auf einer Seite eines Ablaufs ausführen möchte, wie kann dies implementiert werden?Können beide Seiten eines Corda-Flusses in separaten Cordapps existieren?

Zum Beispiel, wenn ein Unternehmen eine interne Firma API anrufen möchte, um die eingehenden Transaktionsdaten zu validieren, kann es dies innerhalb des Flusses tun? Wenn ja, muss der Fluss generisch geschrieben werden, so dass alle Unternehmen, die die gleiche Cordapp (und den gleichen Flow) verwenden, ihre eigenen internen APIs aufrufen. Vielleicht ist die API-URL in einer lokalen Konfigurationsdatei gespeichert.

Oder ist eine andere Option, jedes Unternehmen separate Cordapps zu haben, die für sie spezifische Flüsse enthalten, die mit Flüssen in anderen Cordapps kommunizieren können, die für andere Unternehmen spezifisch sind. Dies scheint sehr schnell sehr komplex zu werden.

Antwort

3

Sicher. Ich habe eine ganze Menge Zeug dazu geschrieben, das ich hier einfügen kann!

Strukturierung CorDapps

CorDapps in gemeinsame und private Elemente aufgeteilt werden kann:

Geteilt CorDapp Elemente

Typischerweise werden die gemeinsamen Elemente eines CorDapp umfassen:

  • Datenstrukturen und benutzerdefinierte Typen, die comp Die Status- und Vertragsdefinitionen müssen für alle Knoten verfügbar sein, die eine Transaktion mit einem oder mehreren Statusobjekten der CorDapp überprüfen müssen
  • Abstrakte Ablaufdefinitionen werden verwendet um eine gemeinsame Darstellung eines Flusses zu definieren, während die tatsächliche Implementierung (die privat sein kann) versteckt wird. Dies liegt daran, dass InitiatedBy-Flow-Annotationen den FlowLogic-Subtyp für den entsprechenden InitatingFlow auf dem Klassenpfad erfordern, sodass ein Flow-Initiator registriert werden kann.
  • Shared Utility-Funktionen, die Knotendienste verwenden, werden normalerweise aus Flows verwendet und nehmen häufig einen ServiceHub-Parameter es ist sinnvoller, dies zu tun, als einen anderen Flow zu schreiben oder Ihre bestehenden Flüsse mit Wiederholungen derselben Methode zu überlagern.
  • Geteilte Flüsse werden häufig in Situationen benötigt, in denen ein einfacher Workflow erforderlich ist, der keine Anpassung erfordert und ausgeführt wird out von allen Parteien mit der CorDapp

Es ist im Allgemeinen ratsam, die gemeinsamen CorDapp JARs zu halten so klein wie möglich, weil die JAR, die die Status- und Vertragsdefinitionen enthält, sich im Netzwerk mit Transaktionen bewegt, die Status des in der JAR definierten Typs enthalten. Nachgeschaltete Überprüfer von Transaktionen müssen möglicherweise Transaktionen überprüfen, die Zustände enthalten, mit denen sie nicht Transaktionen durchführen, sodass sie die Flüsse ihres Klassenpfads nicht benötigen. Daher ist es sinnvoll, die Status- und Vertragsdefinitionen (und alle Abhängigkeiten) getrennt von allem anderen zusammenzufassen.

Privat CorDapp Elemente

Privat Elemente eines corDapp umfassen in der Regel:

  • Bespoke Flow-Implementierungen
  • Corda Dienstleistungen
  • Irgendwelche Typdefinitionen, die für die oben

als ment Wie oben erwähnt, können CorDapp-Entwickler abstrakte Darstellungen ihrer Flüsse teilen und die Implementierung privat halten. Das Fluss-Framework ermöglicht es Parteien, ihre eigenen Flüsse zu implementieren, vorausgesetzt, dass sie einer gemeinsamen Schnittstelle entsprechen, das heißt, sowohl der InitiatingFlow als auch der InitiatedBy Fluss senden und empfangen die gleichen Typen an den erwarteten Punkten im Fluss.

Solange die Flüsse dies tun, kann der Rest der Implementierung angepasst werden. Beispiel: Benutzerdefinierte private Implementierungen greifen möglicherweise auf interne Systeme zu oder verwenden proprietäre Typen und sollten daher nicht mit den gemeinsamen Elementen von CorDapp gepackt werden.

Fluss Versionierung

Neben der Entwicklung der Plattform strömt, die ausgeführt werden auf der Oberseite der Plattform kann auch entwickeln. Jede Strömung, von der Sie andere Strömungen initiieren will, muss mit dem @InitiatingFlow Anmerkung Anmerkungen versehen werden, die wie folgt definiert ist:

annotation class InitiatingFlow(val version: Int = 1) 

Hinweis, die optionale Version Eigenschaft, die standardmäßig auf 1, um die Version des Stroms zu bestimmen. Dieser ganzzahlige Wert, der momentan nur für Entwickler gedacht ist, sollte immer dann erhöht werden, wenn ein Flow freigegeben wird, der Änderungen enthält, die nicht rückwärtskompatibel zu früheren Versionen sind. Eine nicht rückwärtskompatible Änderung ändert die Schnittstelle des Flusses.

Gegenwärtig wird die Handhabung der Versionsverwaltung den CorDapp-Entwicklern überlassen. In Zukunft wird die Plattform jedoch vorgeschriebene Regeln implementieren.

Was ist die Schnittstelle für eine Menge von Flüssen?

Die Flussschnittstelle definiert die Sequenz von Senden und Empfangen zwischen einem InitiatingFlow- und einem InitiatedBy-Fluss sowie die gesendeten und empfangenen Typen.Es ist am besten mit einem Sequenzdiagramm dargestellt:

oben

enter image description here

Im Diagramm der InitiatingFlow:

  1. Sendet ein Int
  2. erhält einen String
  3. ein String Sendet
  4. Empfängt einen CustomType

Der InitiatedBy Fluss tut das Gegenteil:

  1. Empfängt ein Int
  2. einen String Sendet
  3. empfängt ein String
  4. ein CustomType Sendet

sowohl die IntiatingFlow und die InitiatedBy Ströme Providing konform zu der durch die Schnittstelle definierten Reihenfolge, der Rest der Flüsse kann in irgendeiner Weise implementiert werden und kann proprietäre Geschäftslogik enthalten wird nicht mit anderen Parteien geteilt. In der Tat ist dies die beabsichtigte Möglichkeit, Ströme zu schreiben.

Für ein Beispiel tatsächlich, wie man über das Tun dies gehen würde, bitte hier: https://github.com/sollecitom/corda-foreign-exchange-example/blob/master/buyer-api/src/main/kotlin/net/corda/examples/fx/buyer/BuyCurrencyFlowDefinitions.kt

Dies wird durch eine der Corda Entwickler und in der Datei oben geschrieben wurde, gibt es eine abstrakte Flussdefinition, die eine hat private Umsetzung nur dem Käufer bekannt.

+0

Ich sehe aus dem Beispiel, dass sie eine abstrakte Klasse für den gemeinsamen Initiierungsfluss verwenden. Ist es möglich, das Gleiche auf der Akzeptorseite des Flusses zu tun? Wenn dies der Fall ist, sollte die Annotation @InitiatedBy in der abstrakten Klasse oder in der privaten Implementierung des Akzeptorflusses sein. – BrianRice

Verwandte Themen