I missed out `Saga` last time when doing the big `...
# arrow-contributors
y
I missed out
Saga
last time when doing the big
ResourceScope
cleanup. Looking at it a bit, I think
Saga
should be deprecated.
ResourceScope
should just have a
saga
method like so:
Copy code
public suspend inline fun <A> ResourceScope.saga(
  action: suspend () -> A,
  crossinline compensation: suspend (A) -> Unit,
): A = action().also { a -> 
  onRelease { 
    if (it !is ExitCase.Completed) compensation(a) 
  } 
}
and that does the trick perfectly. Am I missing something?
s
We worked together on a more generalised abstraction
Scope/scope { }
which basically only implement
onRelease
, and everything can be implemented on top of it.
CoroutineScope
,
ResourceScope
,
SageScope
, (suspend)
Raise<Error>
, and everything that creates some kind-of scope and does something at the end. All of these just add state on top, and do something with it during the finalisation of the scope. So in theory your entire application could just we
scope { }
but that means everything stays open. And you'd need to do things like:
Copy code
scope appScope@ {
   val ds = appScope.install({ dataSource(...) }) { _, ds -> ds.close() }
   scope saga@ {
       saga({ ds.insert(..) }) { ds.rollback(..) }
       throw RuntimeException("Boom")
   }
}
Which of course works, but I think using explicit (typed) scopes makes things a bit easier and clear.
y
This has been slowly making its way into the code. Recently, we got
ManagedSupervisorScope
and
ManagedScope
, which do
supervisorScope
and
coroutineScope
respectively. This would be the next step of it then. I see what you mean about the nested scopes getting a bit confusing, but I think this is true when using resources and wanting a resource with limited lifetime, so you nest scopes to get that limited lifetime. We could also have
interface SagaScope { fun compensate(compensation: suspend (Throwable) -> Unit) }
and
ResourceScope
is an extension of it. I kinda like that, we already do the same with
AutoCloseScope
, but here we don't have a real reason to have such a secondary interface (while for auto close, the fact it's not
suspend
is relevant). I'm not sure how well
Raise
fits into that. The fact it handles exceptions means it doesn't really fit with everything else.
a
I am somehow opposed to this from an API point of view. Although it's true that the underlying mechanism could be shared, I think that keeping
ResourceScope
,
SagaScope
,
AutoCloseScope
and all of those separate help with the developer experience.
1