Safe Gleichzeitigkeit und Widerstandsfähigkeit für Scala auf dem JVM. Benötigt JDK 21 & Scala 3. Die Gebiete, die wir mit OX decken möchten, sind:
Alle oben genannten sollten die Beobachtbarkeit der orchestrierten Geschäftslogik ermöglichen. Wir wollen das Schreiben einfacher, expressionsorientierter Code im funktionalen Stil ermöglichen. Wir möchten den Syntax-Overhead auf ein Minimum halten, Entwickler-freundliche Stapelspuren und ohne Kompromisse bei der Leistung erhalten.
Einige der oben genannten sind bereits in der API angesprochen, andere stehen in Zukunft auf. Wir würden Ihre Hilfe bei der Gestaltung des Projekts lieben!
Verwenden Sie zum Testen von OX die folgende Abhängigkeit unter Verwendung eines SBT:
" com.softwaremill.ox " %% " core " % " 0.5.3 "
Oder Scala-Cli:
//> using dep " com.softwaremill.ox::core:0.5.3 "
Die Dokumentation finden Sie unter https://ox.softwaremill.com. Scaladocs können unter https://javadoc.io durchsucht werden.
Führen Sie zwei Berechnungen parallel durch:
def computation1 : Int = { sleep( 2 .seconds); 1 }
def computation2 : String = { sleep( 1 .second); " 2 " }
val result1 : ( Int , String ) = par(computation1, computation2)
// (1, "2")
Zeitüberschreitung eine Berechnung:
def computation3 : Int = { sleep( 2 .seconds); 1 }
val result2 : Either [ Throwable , Int ] = either.catching(timeout( 1 .second)(computation3))
// `timeout` only completes once the loosing branch is interrupted & done
Rennen zwei Berechnungen:
def computation4 : Int = { sleep( 2 .seconds); 1 }
def computation5 : Int = { sleep( 1 .second); 2 }
val result3 : Int = raceSuccess(computation4, computation5)
// as before, the loosing branch is interrupted & awaited before returning a result
Strukturierte Parallelität & Überwachung:
// equivalent of par
supervised {
val f1 = fork { sleep( 2 .seconds); 1 }
val f2 = fork { sleep( 1 .second); 2 }
(f1.join(), f2.join())
}
Fehlerbehandlung innerhalb eines strukturierten Parallelitätsbereichs:
supervised {
forkUser :
sleep( 1 .second)
println( " Hello! " )
forkUser :
sleep( 500 .millis)
throw new RuntimeException ( " boom! " )
}
// on exception, all other forks are interrupted ("let it crash")
// the scope ends & re-throws only when all forks complete (no "leftovers")
Eine Berechnung wiederholen:
def computationR : Int = ???
retry( RetryConfig .backoff( 3 , 100 .millis, 5 .minutes, Jitter . Equal ))(computationR)
Wiederholen Sie eine Berechnung:
def computationR : Int = ???
repeat( RepeatConfig .fixedRateForever( 100 .millis))(computationR)
Zuleiten Sie eine Ressource in einem Zielfernrohr:
supervised {
val writer = useCloseableInScope( new java.io. PrintWriter ( " test.txt " ))
// ... use writer ...
} // writer is closed when the scope ends (successfully or with an error)
Erstellen Sie eine App, die bei unterbrochener Unterbrochene mit SIGINT/SIGTMTER SEALS geschaltet wird:
object MyApp extends OxApp :
def run ( args : Vector [ String ])( using Ox ) : ExitCode =
// ... your app's code ...
// might use fork {} to create top-level background threads
ExitCode . Success
Einfache Typ-Safe-Schauspieler:
class Stateful { def increment ( delta : Int ) : Int = ??? }
supervised :
val ref = Actor .create( new Stateful )
// ref can be shared across forks, but only within the concurrency scope
ref.ask(_.increment( 5 ))
Erstellen Sie einen einfachen Fluss und eine Transformation mit einer funktionalen API:
Flow .iterate( 0 )(_ + 1 ) // natural numbers
.filter(_ % 2 == 0 )
.map(_ + 1 )
.intersperse( 5 )
// compute the running total
.mapStateful(() => 0 ) { (state, value) =>
val newState = state + value
(newState, newState)
}
.take( 10 )
.runForeach(n => println(n.toString))
Erstellen Sie Flows, die E/A durchführen und die Parallelität verwalten:
def sendHttpRequest ( entry : String ) : Unit = ???
Flow
.fromInputStream( this .getClass().getResourceAsStream( " /list.txt " ))
.linesUtf8
.mapPar( 4 )(sendHttpRequest)
.runDrain()
Fucken Sie zwei Strömungen zusammen und behandeln Sie den Versagen eines der Zweige ordnungsgemäß:
val f1 = Flow .tick( 123 .millis, " left " )
val f2 = Flow .tick( 312 .millis, " right " )
f1.merge(f2).take( 100 ).runForeach(println)
Integrieren Sie den Fluss mit anderen Komponenten mit einer imperativen API:
def readNextBatch () : List [ String ] = ???
Flow .usingEmit { emit =>
forever :
readNextBatch().foreach(emit.apply)
}
Verwenden Sie vervollständige Hochleistungskanäle für die Kommunikation zwischen den Vorlieben innerhalb von Parallelitätszügen:
val c = Channel .buffered[ String ]( 8 )
c.send( " Hello, " )
c.send( " World " )
c.done()
Wählen Sie aus GO-ähnlichen Kanälen:
val c = Channel .rendezvous[ Int ]
val d = Channel .rendezvous[ Int ]
select(c.sendClause( 10 ), d.receiveClause)
Eithers auspacken und Fehler in einem Gewerkschaftstyp kombinieren:
val v1 : Either [ Int , String ] = ???
val v2 : Either [ Long , String ] = ???
val result : Either [ Int | Long , String ] = either :
v1.ok() ++ v2.ok()
Pipe & Tippen Sie auf Funktionen auf Funktionen, um die Dot-Syntax zu verwenden:
def compute : Int = ???
def computeMore ( v : Int ) : Long = ???
compute
.pipe( 2 * _)
.tap(println)
.pipe(computeMore)
Mehr in den Dokumenten!.
Das breitere Ziel von Scala im Direktstil ist es, Teams schnell und mit Zuversicht Arbeitssoftware zu liefern. Unsere anderen Projekte, einschließlich STTP -Client und Tapir, enthalten auch Integrationen, die direkt auf den direkten Stil zugeschnitten sind.
Darüber hinaus finden Sie auch das GEARS-Projekt, eine experimentelle mehrfach Plattformbibliothek, die auch Skala im direkten Stil abdeckt.
Alle Vorschläge willkommen :)
Um zu kompilieren und zu testen, rennen Sie:
sbt compile
sbt test
Sehen Sie sich die Liste der Probleme und wählen Sie eine aus! Oder melden Sie Ihre eigenen.
Wenn Sie Zweifel daran haben, warum oder wie etwas funktioniert, zögern Sie nicht, eine Frage zum Diskurs oder über GitHub zu stellen. Dies bedeutet wahrscheinlich, dass die Dokumentation, Skaladocs oder Code unklar ist und zum Nutzen aller verbessert werden kann.
Um die Dokumentation zu entwickeln, können Sie das Skript doc/watch.sh
verwenden, das Sphinx mit Python ausführt. Verwenden Sie doc/requirements.txt
um Ihre Python -Umgebung mit pip
einzurichten. Wenn Sie ein NIX -Benutzer sind, führen Sie nix develop
in doc/
um eine Shell mit einer Umgebung aus, in der watch.sh
ausgeführt werden kann. Darüber hinaus können Sie die compileDocumentation
-SBT -Aufgabe verwenden, um zu überprüfen, ob alle Code -Snippets ordnungsgemäß kompiliert werden.
Wenn Sie eine PR bereit haben, schauen Sie sich unseren Leitfaden "Wie man einen guten PR" ansehen. Danke! :)
Wir bieten kommerzielle Entwicklungsdienstleistungen an. Kontaktieren Sie uns, um mehr über uns zu erfahren!
Copyright (C) 2023-2024 Softwaremill https://softwaremill.com.