Passing an implicit ExecutionContext to contained objects / called methods

I am creating an asynchronous library using Scala 2.10 futures. The library constructor accepts a sequence of user objects that implement a particular attribute, and then the method in the library class sends some data one at a time to user-defined objects. I want the user to provide an ExecutionContext for asynchronous operations when setting up the main instance, and then for this context so that it is passed to user-defined objects as needed. Simplified (pseudo?) Code:

 case class Response(thing: String) class LibraryObject(stack: Seq[Processor])(implicit context: ExecutionContext) { def entryPoint(data: String): Future[Response] = { val response = Future(Response("")) stack.foldLeft(response) { (resp, proc) => proc.process(data, resp) } } } trait Processor { def process(data: String, resp: Future[Response]): Future[Response] } 

You can use something like this:

 class ThingProcessor extends Processor { override def process(data: String, response: Future[Response]) = { response map { _.copy(thing = "THE THING") } } } class PassThroughProcessor extends Processor { override def process(request: Request, response: Future[Response]) = { response } } object TheApp extends App { import ExecutionContext.Implicits.global val stack = List( new ThingProcessor, new PassThroughProcessor ) val libObj = new LibraryObject(stack) val futureResponse = libObj.entryPoint("http://some/url") // ... } 

I get a compilation error for ThingProcessor :

Cannot find implicit ExecutionContext, either one is required or Import ExecutionContext.Implicits.global

My question is how do I implicitly supply an ExecutionContext that the LibraryObject has user-defined objects ( ThingProcessor and PassThroughProcessor ) or their methods, without making the user (who will write the classes) worry about this - that is, I would prefer that the user does not have to print:

 class MyFirstProcessor(implicit context: ExecutionContext) 

or

 override def process(...)(implicit context: ExecutionContext) = { ... } 
+6
source share
1 answer

The implicit domain includes companion objects and type parameters of the base classes.

Or, library.submit (new library.Processor {def process () ...}).

This works, but was not my first thought, which should have been smarter:

 import concurrent._ import concurrent.duration._ class Library(implicit xc: ExecutionContext = ExecutionContext.global) { trait Processor { implicit val myxc: ExecutionContext = xc def process(i: Future[Int]): Future[Int] } def submit(p: Processor) = p process future(7) } object Test extends App { val library = new Library val p = new library.Processor { def process(i: Future[Int]) = for (x <- i) yield 2 * x } val res = library submit p val z = Await result (res, 10.seconds) Console println z } 

Update:

 import concurrent._ import concurrent.duration._ import java.util.concurrent.Executors class Library()(implicit xc: ExecutionContext = ExecutionContext.global) { trait Processor { implicit val myxc: ExecutionContext = xc def process(i: Future[Int]): Future[Int] } def submit(p: Processor) = p process future(7) } object ctx { val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor } object library1 extends Library object library2 extends Library()(ctx.xc) object p extends library1.Processor { def process(i: Future[Int]) = for (x <- i) yield 2 * x } object q extends library2.Processor { def process(i: Future[Int]) = for (x <- i) yield 3 * x } object Test extends App { val res = library1 submit p //val oops = library2 submit p //val oops = library1 submit q val z = Await result (res, 10.seconds) Console println z Console println (Await result (library2 submit q, 10.seconds)) ctx.xc.shutdownNow() } 

It's not that much:

 class Library(implicit xc: ExecutionContext = ExecutionContext.global) { def submit(p: Processor): Future[Int] = p dueProcess future(7) } trait Processor { implicit var myxc: ExecutionContext = _ def dueProcess(i: Future[Int])(implicit xc: ExecutionContext) = { myxc = xc process(i) } protected def process(i: Future[Int]): Future[Int] } object ctx { val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor } object Test extends App { def db() = Console println (new Throwable().getStackTrace mkString ("TRACE [\n ", "\n ", "\n]")) val library = new Library()(ctx.xc) val p = new Processor { protected def process(i: Future[Int]) = for (x <- i) yield { db(); 2 * x } } val res = library submit p val z = Await result (res, 10.seconds) Console println z ctx.xc.shutdownNow() } 
+5
source

Source: https://habr.com/ru/post/950226/


All Articles