Skip to content

Latest commit

 

History

History
96 lines (91 loc) · 5.19 KB

1-backend.md

File metadata and controls

96 lines (91 loc) · 5.19 KB
shortTitleshortDescriptionexpandTextanchorTargeticon
Server-side
High-throughput HTTP servers and clients. Safe, scalable, and principled concurrency. Reliable data validation with powerful transformations.
Creating Services
creating-services
icon5.svg

Principled Concurrency

Scala's expressivity and compiler-enforced safety makes it easier to construct reliable concurrent code.

With Scala, your programs take full advantage of multi-core and distributed architectures, ensure safe access to resources, and apply back-pressure to data producers according to your processing rate.

One popular open-source option for managing concurrency in Scala is Cats Effect, combined with http4s for defining servers and routing. Click below to see other solutions.

libraries for Concurrency and distribution
Express high-level concurrency with http4s and Cats Effect
// HTTP server routing definition val service = HttpRoutes.of: case GET -> Root / "weather" => // route '/weather' for winner <- fetch1.race(fetch2).timeout(10.seconds) response <- Ok(WeatherReport.from(winner)) yield response 

def fetch1 = fetchWeather(server1) // expensive Network IO def fetch2 = fetchWeather(server2) // expensive Network IO

A Mature Ecosystem of Libraries

Use the best of Scala, or leverage libraries from the Java and JavaScript ecosystems.

Build with monolithic or microservice architectures. Retain resource-efficiency. Persist your data to any kind of database. Transform, validate, and serialize data into any format (JSON, protobuf, Parquet, etc.).

Whether you compile for the Node.js or Java platform, Scala's interop with both gives you access to even more widely-proven libraries.

Find the right library for your next Scala project
Compute accross distributed nodes with Akka actors
def Device(lastTemp: Option[Double]): Behavior[Message] = Behaviors.receiveMessage: case RecordTemperature(id, value, replyTo) => replyTo ! TemperatureRecorded(id) Device(lastTemp = Some(value)) 
case ReadTemperature(id, replyTo) => replyTo ! RespondTemperature(id, lastTemp) Behaviors.same 

Case Study: Reusable Code with Tapir

Harness the “Code as Data” Paradigm: define once, use everywhere.

Scala's rich type system and metaprogramming facilities give the power to automatically derive helpful utilities from your code.

One such example library is Tapir, letting you use Scala as a declarative language to describe your HTTP endpoints. From this single source of truth, you can automatically derive their server implementation, their client implementation, and both human-readable and machine-readable documentation.

Because everything is derived from a type-safe definition, endpoint invocations are checked to be safe at compile-time, across the frontend and backend.

Read more in the Tapir docs
Describe service endpoints as data with Tapir
// type-safe endpoint definition val reportEndpoint = endpoint .in("api" / "report" / path[String]("reportId")) .out(jsonBody[Report]) 

// derived Docs, Server and Client val apiDocs = docsReader .toOpenAPI(reportEndpoint, "Fetch Report", "1.0.0") val server = serverBuilder(port = "8080") .addEndpoint(reportEndpoint.handle(fetchReport)) .start() val client = clientReader .toRequest(reportEndpoint, "http://localhost:8080") val report: Future[Report] = client("5ca1a-78fc8d6") // call like any function

close