Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Task monad #1802

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Introduce Task monad #1802

wants to merge 1 commit into from

Conversation

jypma
Copy link
Contributor

@jypma jypma commented Mar 18, 2025

This commit introduces Task, a data structure that represents a recipe, or program, for producing a value of type T (or failing with an exception). It is similar in semantics to RunnableGraph[T], but intended as first-class building block.

It has the following properties:

  • A task can have resources associated to it, which are guaranteed to be released if the task is cancelled or fails
  • Tasks can be forked so multiple ones can run concurrently
  • Such forked tasks can be cancelled

A Task can be created from a RunnableGraph which has a KillSwitch, by connecting a Source and a Sink through a KillSwitch, or by direct lambda functions.

Open discussion points and TODOs (in order of highest architectural impact):

  • Current cancellation of a graph through KillSwitch doesn't communicate back a trigger when the graph is actually done cancelling. It would be very nice to have that, but this might need deeper changes in pekko.
  • I've currently stuffed it inside the stream module, but it should probably have its own.
  • We need to add resource safety (by means of a new TaskDef: case class FinallyDef[T](base: TaskDef[T], cleanup: TaskDef[_]), which can then guarantee cleanup even under cancellation signals.
  • Add many more combinators (plain zip, race, ...)
  • Add .delay() and general scheduling by hooking in the scheduling features of Materializer
  • Scala DSL

Fixes #1801 .

}
future.onComplete { res =>
childFiber.complete(res)
}(scala.concurrent.ExecutionContext.global)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • we need to avoid hardcoding the global context
  • even if comes to setting up a config in the reference.conf that defines an executioncontext created specifically for this
  • might be nicer if it was controlled by an implicit param though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing, this one was temporary, that's why it's explicit :) I'll replace it with executor. The intent is to make the executor pluggable (probably by picking a dispatcher from the Materializer), I just haven't decided for the API on that yet.

This commit introduces Task, a data structure that represents a
recipe, or program, for producing a value of type T (or failing with
an exception). It is similar in semantics to RunnableGraph[T], but
intended as first-class building block.

It has the following properties:
- A task can have resources associated to it, which are guaranteed to
be released if the task is cancelled or fails
- Tasks can be forked so multiple ones can run concurrently
- Such forked tasks can be cancelled

A Task can be created from a RunnableGraph which has a KillSwitch, by
connecting a Source and a Sink through a KillSwitch, or by direct
lambda functions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Task monad based on Materializer
2 participants