SAFECT STYAT DIRECT CONDURANCE ET RÉSILIENCE POUR Scala sur le JVM. Nécessite JDK 21 et Scala 3. Les zones que nous aimerions couvrir avec du bœuf sont:
Tout ce qui précède devrait permettre l'observabilité de la logique commerciale orchestrée. Nous visons à permettre l'écriture de code simple et orienté vers l'expression dans le style fonctionnel. Nous aimerions maintenir la surcharge de syntaxe au minimum, en préservant des traces de pile adaptées aux développeurs et sans compromettre les performances.
Certains des éléments ci-dessus sont déjà traités dans l'API, certains arrivent à l'avenir. Nous aimerions votre aide pour façonner le projet!
Pour tester le bœuf, utilisez la dépendance suivante, en utilisant l'un ou l'autre SBT:
" com.softwaremill.ox " %% " core " % " 0.5.3 "
Ou Scala-Cli:
//> using dep " com.softwaremill.ox::core:0.5.3 "
La documentation est disponible sur https://ox.softwaremill.com, Scaladocs peut être parcouru sur https://javadoc.io.
Exécutez deux calculs en parallèle:
def computation1 : Int = { sleep( 2 .seconds); 1 }
def computation2 : String = { sleep( 1 .second); " 2 " }
val result1 : ( Int , String ) = par(computation1, computation2)
// (1, "2")
Timeout un calcul:
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
Race deux calculs:
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
Concurrence et supervision structurées:
// equivalent of par
supervised {
val f1 = fork { sleep( 2 .seconds); 1 }
val f2 = fork { sleep( 1 .second); 2 }
(f1.join(), f2.join())
}
Gestion des erreurs dans une lunette de concurrence structurée:
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")
Reessayez un calcul:
def computationR : Int = ???
retry( RetryConfig .backoff( 3 , 100 .millis, 5 .minutes, Jitter . Equal ))(computationR)
Répétez un calcul:
def computationR : Int = ???
repeat( RepeatConfig .fixedRateForever( 100 .millis))(computationR)
Allouer une ressource dans une portée:
supervised {
val writer = useCloseableInScope( new java.io. PrintWriter ( " test.txt " ))
// ... use writer ...
} // writer is closed when the scope ends (successfully or with an error)
Créez une application qui s'arrête proprement lorsqu'elle est interrompue avec Sigint / Sigterm:
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
ACTEURS DE TYPE SIMPLE:
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 ))
Créez un flux et transformée simple à l'aide d'une API fonctionnelle:
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))
Créer des flux qui effectuent des E / S et gérent la concurrence:
def sendHttpRequest ( entry : String ) : Unit = ???
Flow
.fromInputStream( this .getClass().getResourceAsStream( " /list.txt " ))
.linesUtf8
.mapPar( 4 )(sendHttpRequest)
.runDrain()
Fusionner deux flux, gérer correctement la défaillance des deux branches:
val f1 = Flow .tick( 123 .millis, " left " )
val f2 = Flow .tick( 312 .millis, " right " )
f1.merge(f2).take( 100 ).runForeach(println)
Intégrez le flux avec d'autres composants à l'aide d'une API impérative:
def readNextBatch () : List [ String ] = ???
Flow .usingEmit { emit =>
forever :
readNextBatch().foreach(emit.apply)
}
Utilisez des canaux à haute performance terminés pour la communication inter-fourche dans des lunettes de concurrence:
val c = Channel .buffered[ String ]( 8 )
c.send( " Hello, " )
c.send( " World " )
c.done()
Sélectionnez parmi les canaux de type Go-Like:
val c = Channel .rendezvous[ Int ]
val d = Channel .rendezvous[ Int ]
select(c.sendClause( 10 ), d.receiveClause)
Déballez des erreurs et combinez des erreurs dans un type d'union:
val v1 : Either [ Int , String ] = ???
val v2 : Either [ Long , String ] = ???
val result : Either [ Int | Long , String ] = either :
v1.ok() ++ v2.ok()
Valeurs de tuyaux et de robinet sur les fonctions pour utiliser la syntax à points:
def compute : Int = ???
def computeMore ( v : Int ) : Long = ???
compute
.pipe( 2 * _)
.tap(println)
.pipe(computeMore)
Plus dans les documents!.
L'objectif plus large de Scala de style direct est de permettre aux équipes de livrer rapidement des logiciels de travail et en toute confiance. Nos autres projets, y compris le client STTP et Tapir, incluent également des intégrations directement adaptées à un style direct.
De plus, consultez également le projet Gears, une bibliothèque expérimentale multiplateforme couvrant également Scala de style direct.
Toutes les suggestions sont les bienvenues :)
Pour compiler et tester, exécuter:
sbt compile
sbt test
Voir la liste des problèmes et choisissez-en un! Ou signalez le vôtre.
Si vous avez des doutes sur le pourquoi ou comment quelque chose fonctionne, n'hésitez pas à poser une question sur le discours ou via Github. Cela signifie probablement que la documentation, les scaladocs ou le code ne sont pas claires et peuvent être améliorées au profit de tous.
Afin de développer la documentation, vous pouvez utiliser le script doc/watch.sh
, qui exécute Sphinx à l'aide de Python. Utilisez doc/requirements.txt
pour configurer votre environnement Python avec pip
. Alternativement, si vous êtes un utilisateur NIX, exécutez nix develop
dans doc/
pour démarrer un shell avec un environnement permettant d'exécuter watch.sh
. De plus, vous pouvez utiliser la tâche SBT compileDocumentation
pour vérifier que tous les extraits de code se compilent correctement.
Lorsque vous avez un RP prêt, jetez un œil à notre guide "Comment préparer un bon PR". Merci! :)
Nous proposons des services de développement commercial. Contactez-nous pour en savoir plus sur nous!
Copyright (C) 2023-2024 Softwaremill https://softwaremill.com.