Skip to main content

Infrastructure as types: introducing TypeOps

Picture of Łukasz Biały, Scala Dev Advocate

Łukasz Biały

Scala Dev Advocate
Mar 7, 2025|1 min read
Infrastructure_as_types_introducing_TypeOps_image-min.jpg
1val appName = "scala-app"
2val httpPortInContainer = 80
3val httpPort = httpPortInContainer
4val taskDefinition = ecs.TaskDefinition(
5 "scala-app-task",
6 ecs.TaskDefinitionArgs(
7 family = appName,
8 containerDefinitions = List(
9 AppDefinition(
10 name = appName,
11 image = appImage,
12 memory = 512,
13 cpu = 256,
14 portMappings = List(
15 PortMapping(httpPort, httpPortInContainer)
16 )
17 )
18 ).toJson,
19 networkMode = "bridge",
20 requiresCompatibilities = List("EC2"),
21 executionRoleArn = taskExecutionRole.arn
22 )
23)
1ThisBuild / scalaVersion := "3.3.5"
2
3lazy val workerLambda =
4 project.in(file("worker-lambda")).awsLambda
5
6lazy val routerLambda = project.in(file("router-lambda"))
7 .awsLambda
8 .withYagaDependencies(
9 workerLambda.awsLambdaModel()
10 )
11
12lazy val infra = project.in(file("infra"))
13 .withYagaDependencies(
14 workerLambda.awsLambdaInfra(packagePrefix = "worker"),
15 routerLambda.awsLambdaInfra(packagePrefix = "router")
16 )
Infrastructure with workerLambda and routerLambda

1package com.virtuslab.worker_lambda
2
3import yaga.extensions.aws.lambda.LambdaHandler
4
5case class Foo(str: String)
6case class WorkerRequest(foo: Foo)
7case class WorkerResponse(str: String)
8
9class WorkerLambda extends LambdaHandler[Unit, WorkerRequest, WorkerResponse]:
10 println("Initializing WorkerLambda")
11
12 override def handleInput(event: WorkerRequest) =
13 println(s"Received input: $event")
14 WorkerResponse(event.foo.str.reverse)
1package com.virtuslab.router_lambda
2
3import yaga.extensions.aws.lambda.{LambdaClient, LambdaHandle, LambdaHandler}
4import software.amazon.awssdk.services.lambda.{LambdaClient as UnshapedLambdaClient}
5import com.virtuslab.worker_lambda
6
7case class Config(
8 workerLambda: LambdaHandle[worker_lambda.WorkerRequest, worker_lambda.WorkerResponse]
9)
10
11case class RouterRequest(str: String)
12
13class RouterLambda extends LambdaHandler[Config, Qux, String]:
14 val underlyingClient = UnshapedLambdaClient.create()
15 val lambdaClient = LambdaClient(underlyingClient)
16
17 override def handleInput(req: RouterRequest) =
18 val workerLambdaInput = worker_lambda.WorkerRequest(worker_lambda.Foo(str = req.str))
19 val workerResponse = lambdaClient.invokeSyncUnsafe(config.workerLambda, workerLambdaInput)
20 println(s"Response from worker-lambda: $workerResponse")
21 "Processing completed"
1// custom AWS IAM roles skipped for brevity
2
3val workerLambdaResource = WorkerLambda(
4 "workerLambda",
5 FunctionArgs(role = lambdaAssumeRole.arn)
6)
7
8// ...
9
10val routerLambdaResource = RouterLambda(
11 "routerLambda",
12 FunctionArgs(role = routerLambdaRole.arn),
13 config =
14 for workerLambda <- workerLambdaResource
15 yield RouterLambdaConfig(
16 workerLambda = workerLambda.lambdaHandle
17 )
18)

Subscribe to our newsletter and never miss an article