airframe-di: Automatically close unreferenced child sessions upon GC
It's easy to create child sessions but sometimes the timing to close child sessions is unclear for some applications.
An idea is closing child sessions automatically if they are collected by GC. To do so, we need to maintain phantom references of created child sessions. airframe-canvas has a similar implementation for collecting allocated off-heap memory buffers.
Hi. I'll share case of using child session.
I tried to use child session when transmissioned metadata to grpc client from server which recieved request with akka-grpc. This make a client to be able to requet using recieved metadata to other grpc server.
Following code is my case which i tried.
// create child session with new design including metadata.
trait ChildSessionSupport {
private val session = bind[Session]
def doWithSession[B](d: Metadata)(func: Session => B): B =
session.withChildSession(newDesign.bind[Metadata].toInstance(d))(func)
}
// call grpc client using implicit child session
trait SampleGprcServer extends UserServicePowerApi with ChildSessionSupport {
private val client = bind[SampleGrpcClient]
def getUserList(in: GetUserListRequest, metadata: Metadata): Future[GetUserListResponse] =
doWithSession(metadata) { implicit session: Session =>
val r = client.getUserList()
// do something
}
}
// invoke request to external grpc server after add header value from child session's metadata.
trait SampleGrpcClient {
private val client = bind[UserServiceClientPowerApi]
final val AlbOidcJwtKey = "x-amzn-oidc-data"
def getUserList()(implicit session: Session): Future[GetUserListResponse] = {
val md = session.build[Metadata]
client.getUserList()
.addHeader(AlbOidcJwtKey -> md.getText(AlbOidcJwtKey)
.getOrElse("x-amzn-oidc-data is unspecified")).invoke(GetUserListRequest)
}
}
As you can see, child session is create per request. So, If finished a process, I hoped child sessions to be close. So. I think nice idea that automatically close unreferenced child sessions upon GC.
I hope my sharing helped.
@takat0-h0rikosh1 Thanks for the example. In this specific case, the child session is automatically closed after executing func code block because withChildSession calls session.shutdown:
def withChildSession[U](d: Design = Design.blanc)(body: Session => U): U = {
val childSession = newChildSession(d)
try {
childSession.start
body(childSession)
} finally {
childSession.shutdown
}
}
I forgot to looks code of withChildSession. Thanks for reply.