การพร้อมกันแบบโดยตรงแบบโดยตรงและความยืดหยุ่นสำหรับ Scala บน JVM ต้องใช้ JDK 21 & Scala 3 พื้นที่ที่เราต้องการครอบคลุมด้วย OX คือ:
ทั้งหมดข้างต้นควรอนุญาตให้มีการสังเกตของตรรกะทางธุรกิจที่เตรียมไว้ เรามุ่งมั่นที่จะเปิดใช้งานการเขียนโค้ดที่เน้นการแสดงออกอย่างง่ายในรูปแบบการทำงาน เราต้องการรักษาค่าใช้จ่ายของไวยากรณ์ให้น้อยที่สุดรักษาร่องรอยสแต็กที่เป็นมิตรกับนักพัฒนาและไม่มีประสิทธิภาพลดลง
บางส่วนของข้างต้นได้รับการแก้ไขแล้วใน API บางคนกำลังจะมาถึงในอนาคต เราชอบความช่วยเหลือของคุณในการสร้างโครงการ!
ในการทดสอบวัวใช้การพึ่งพาต่อไปนี้โดยใช้ SBT:
" com.softwaremill.ox " %% " core " % " 0.5.3 "
หรือ scala-cli:
//> using dep " com.softwaremill.ox::core:0.5.3 "
เอกสารสามารถดูได้ที่ https://ox.softwaremill.com, scaladocs สามารถเรียกดูได้ที่ https://javadoc.io
เรียกใช้การคำนวณสองแบบพร้อมกัน:
def computation1 : Int = { sleep( 2 .seconds); 1 }
def computation2 : String = { sleep( 1 .second); " 2 " }
val result1 : ( Int , String ) = par(computation1, computation2)
// (1, "2")
หมดเวลาการคำนวณ:
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
การแข่งขันสองการคำนวณ:
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
มีโครงสร้างพร้อมกันและการกำกับดูแล:
// equivalent of par
supervised {
val f1 = fork { sleep( 2 .seconds); 1 }
val f2 = fork { sleep( 1 .second); 2 }
(f1.join(), f2.join())
}
การจัดการข้อผิดพลาดภายในขอบเขตพร้อมกันที่มีโครงสร้าง:
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")
ลองคำนวณใหม่:
def computationR : Int = ???
retry( RetryConfig .backoff( 3 , 100 .millis, 5 .minutes, Jitter . Equal ))(computationR)
ทำซ้ำการคำนวณ:
def computationR : Int = ???
repeat( RepeatConfig .fixedRateForever( 100 .millis))(computationR)
จัดสรรทรัพยากรในขอบเขต:
supervised {
val writer = useCloseableInScope( new java.io. PrintWriter ( " test.txt " ))
// ... use writer ...
} // writer is closed when the scope ends (successfully or with an error)
สร้างแอพที่ปิดอย่างหมดจดเมื่อถูกขัดจังหวะด้วย 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
นักแสดงที่ปลอดภัยประเภทง่าย:
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 ))
สร้าง Flow & Transform ง่าย ๆ โดยใช้ 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))
สร้างกระแสที่ทำงาน I/O และจัดการพร้อมกัน:
def sendHttpRequest ( entry : String ) : Unit = ???
Flow
.fromInputStream( this .getClass().getResourceAsStream( " /list.txt " ))
.linesUtf8
.mapPar( 4 )(sendHttpRequest)
.runDrain()
ผสานการไหลสองครั้งจัดการความล้มเหลวของทั้งสองสาขา:
val f1 = Flow .tick( 123 .millis, " left " )
val f2 = Flow .tick( 312 .millis, " right " )
f1.merge(f2).take( 100 ).runForeach(println)
รวมการไหลเข้ากับส่วนประกอบอื่น ๆ โดยใช้ API ที่จำเป็น:
def readNextBatch () : List [ String ] = ???
Flow .usingEmit { emit =>
forever :
readNextBatch().foreach(emit.apply)
}
ใช้ช่องทางประสิทธิภาพสูงที่สมบูรณ์สำหรับการสื่อสารระหว่างฟอร์กภายในขอบเขตพร้อมกัน:
val c = Channel .buffered[ String ]( 8 )
c.send( " Hello, " )
c.send( " World " )
c.done()
เลือกจากช่องเหมือนไป:
val c = Channel .rendezvous[ Int ]
val d = Channel .rendezvous[ Int ]
select(c.sendClause( 10 ), d.receiveClause)
แกะ eithers และรวมข้อผิดพลาดในประเภทสหภาพ:
val v1 : Either [ Int , String ] = ???
val v2 : Either [ Long , String ] = ???
val result : Either [ Int | Long , String ] = either :
v1.ok() ++ v2.ok()
PIPE & TAP ค่าไปยังฟังก์ชั่นเพื่อใช้ dot-syntax:
def compute : Int = ???
def computeMore ( v : Int ) : Long = ???
compute
.pipe( 2 * _)
.tap(println)
.pipe(computeMore)
เพิ่มเติมในเอกสาร!.
เป้าหมายที่กว้างขึ้นของ Scala สไตล์ตรงทำให้ทีมสามารถส่งมอบซอฟต์แวร์การทำงานได้อย่างรวดเร็วและมีความมั่นใจ โครงการอื่น ๆ ของเรารวมถึงไคลเอนต์ STTP และ Tapir รวมถึงการรวมเข้าด้วยกันโดยตรงกับสไตล์โดยตรง
นอกจากนี้ยังตรวจสอบโครงการ Gears ซึ่งเป็นห้องสมุดหลายแพลตฟอร์มทดลองยังครอบคลุมสกาล่าแบบโดยตรง
คำแนะนำทั้งหมดยินดีต้อนรับ :)
เพื่อรวบรวมและทดสอบวิ่ง:
sbt compile
sbt test
ดูรายการปัญหาและเลือกหนึ่ง! หรือรายงานของคุณเอง
หากคุณมีข้อสงสัยเกี่ยวกับ สาเหตุ หรือ วิธี การทำงานอย่างไรอย่าลังเลที่จะถามคำถามเกี่ยวกับวาทกรรมหรือผ่าน GitHub นี่อาจหมายความว่าเอกสาร, scaladocs หรือรหัสไม่ชัดเจนและสามารถปรับปรุงเพื่อประโยชน์ของทั้งหมด
ในการพัฒนาเอกสารคุณสามารถใช้สคริปต์ doc/watch.sh
ซึ่งเรียกใช้สฟิงซ์โดยใช้ Python ใช้ doc/requirements.txt
เพื่อตั้งค่าสภาพแวดล้อม Python ของคุณด้วย pip
อีกทางเลือกหนึ่งหากคุณเป็นผู้ใช้ NIX ให้เรียกใช้ nix develop
ใน doc/
เพื่อเริ่มต้นเชลล์ด้วยสภาพแวดล้อมที่อนุญาตให้เรียกใช้ watch.sh
นอกจากนี้คุณสามารถใช้งาน compileDocumentation
SBT เพื่อตรวจสอบว่าตัวอย่างโค้ดทั้งหมดคอมไพล์อย่างถูกต้อง
เมื่อคุณมีการประชาสัมพันธ์ให้ดูที่คู่มือ "วิธีเตรียมการประชาสัมพันธ์ที่ดี" ของเรา ขอบคุณ! -
เราให้บริการพัฒนาเชิงพาณิชย์ ติดต่อเราเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับเรา!
ลิขสิทธิ์ (c) 2023-2024 Softwaremill https://softwaremill.com