sdk-java icon indicating copy to clipboard operation
sdk-java copied to clipboard

Scala module

Open doruchiulan opened this issue 4 years ago • 7 comments

I'll go with a top-to-bottom approach with the things I encountered, and how I tried to solve them in my project.

  1. WorkflowClient
  • WorkflowClient.start with io.temporal.workflow.Functions.Func arguments
  • WorkflowClient.start with io.temporal.workflow.Functions.Proc arguments
  • WorkflowClient.execute with io.temporal.workflow.Functions.Func arguments
  • WorkflowClient.execute with io.temporal.workflow.Functions.Proc arguments

Solved this by writing some small wrappers. I don't think this is the way, but the code inside might be useful. These are the only type of functions I needed, didn't convert them all (e.g the ones that take more arguments)

def startAsync(f: T => Unit, arg: T): WorkflowExecution = {
   WorkflowClient.start(new Proc1[T]() {
     override def apply(j: T): Unit = f(j)
   }, t)
 }

 def executeAsyncVoid(f: () => Unit): Future[Unit] = {
   import scala.compat.java8.FutureConverters._

   WorkflowClient.execute(new Proc {
     override def apply(): Unit = f()
   }).toScala.map[Unit](_ => ())
 }

 def executeAsync[T](f: () => T): Future[T] = {
   import scala.compat.java8.FutureConverters._

   WorkflowClient.execute(new Func[T] {
     override def apply(): T = f()
   }).toScala
 }
  1. Scala specific object types serialization/deserialization
  • Option
  • List (basically all Scala collections)

We can probably solve this when Jackson will be integrated in java-sdk

  1. Workflow.await requiring a Supplier, instead of passing a function reference

Again, solved in a simple wrapper

 def await(duration: Duration, f: () => Boolean) {
    Workflow.await(duration, new Supplier[lang.Boolean] {
      override def get(): lang.Boolean = f()
    })
  }
  1. Java way of referencing some method (not sure how this syntax it's called in Java) (Mostly the same as 1. but I put it in a different issue as it's a little bit a different problem)

WorkflowClient.execute(workflow::getGreeting, "World") -> notice the double colon

  1. Accepting Scala Duration type

doruchiulan avatar Apr 28 '20 21:04 doruchiulan

Hey, we have some experience in using cadence with scala and can contribute our experiences and maybe even some code.

Reg 2) Serialization is a tough topic, in general, typeclass-based serialization is more idiomatic and safer in modern scala. But this would be something to have in scala native sdk and so is out of the scope of this issue probably.

1 & 3 are already solved in scala 2.12 and later -> https://www.scala-lang.org/news/2.12.0/#lambda-syntax-for-sam-types

2 & 5 as proposed are not possible without adding scala stdlib as a dependency of java sdk, which doesn't sound plausible. Whereas 2) Is quite hard, the 5) is easily solved by https://github.com/scala/scala-java8-compat#converters-between-scalaconcurrentdurationfiniteduration-and-javatimeduration

Krever avatar Apr 30 '20 09:04 Krever

Hello!

Just wondering about the progress with scala-sdk for Temporal? Any updates?

grouzen avatar Mar 15 '21 10:03 grouzen

Not really using cadence in my current projects, but I'm still keeping an eye on this as this is a project which I really like and which I will happily include in any project that suits it. So if somebody takes over, has a plan/architecture and leads this, I will happily contribute with pieces of code.

doruchiulan avatar Mar 18 '21 15:03 doruchiulan

Hi. Really interested in helping this move forward by creating an integration. Is there a guide I can use to start making the integration possible?

jvican avatar Jan 26 '22 20:01 jvican

Would love the additional support for Scala 👍 it could potentially unlock some interesting use-cases if I can pitch Temporal to my team

ktham avatar Feb 20 '22 18:02 ktham

Hi everyone I’ve implemented Scala SDK, which supports most temporal features. https://github.com/vitaliihonta/zio-temporal

It also allows using protobuf format via ScalaPB.

Currently, it’s tied to ZIO

vitaliihonta avatar Jun 22 '22 10:06 vitaliihonta

I got bit by a problem with the reflection logic that attempts to determine whether Async.function is being passed a method reference in MethodReferenceDisassembler#isAsyncJava. Turns out that a method reference in Scala has a different result from getImplMethodKind. It returns MethodHandleInfo.REF_invokeStatic instead of MethodHandleInfo.REF_invokeInterface. We had to invoke this through a small java shim to get it to function correctly and not execute directly on the local workflow executor.

I think ztemporal may have the same problem. It also appears to me to call Async.function passing a Scala lambda expression.

scoplin avatar Oct 06 '22 22:10 scoplin