All Downloads are FREE. Search and download functionalities are using the official Maven repository.

almond.interpreter.api.CommHandler.scala Maven / Gradle / Ivy

The newest version!
package almond.interpreter.api

import java.util.UUID
import java.nio.charset.StandardCharsets

/** Kind of message broker between the Jupyter UI and the kernel.
  *
  * See https://jupyter-client.readthedocs.io/en/5.2.3/messaging.html#custom-messages.
  *
  * Typically available in the implicit scope of user code run via the kernel.
  *
  * Can be used by users to send messages to custom code running in the browser, and receive
  * messages from it.
  *
  * Registering a target with name `"target_name"` allows to receive messages from frontends. From
  * the Jupyter classic UI, one can send messages to this target via code like
  * {{{
  *   var comm = Jupyter.notebook.kernel.comm_manager.new_comm("target_name", '{"a": 2, "b": false}');
  *   comm.open();
  *   comm.send('{"c": 2, "d": {"foo": [1, 2]}}');
  * }}}
  */
abstract class CommHandler extends OutputHandler.UpdateHelpers {

  import CommHandler.Comm

  def registerCommTarget(name: String, target: CommTarget): Unit
  def unregisterCommTarget(name: String): Unit
  def registerCommId(id: String, target: CommTarget): Unit
  def unregisterCommId(id: String): Unit

  @throws(classOf[IllegalArgumentException])
  def commOpen(targetName: String, id: String, data: Array[Byte], metadata: Array[Byte]): Unit
  @throws(classOf[IllegalArgumentException])
  def commMessage(id: String, data: Array[Byte], metadata: Array[Byte]): Unit
  @throws(classOf[IllegalArgumentException])
  def commClose(id: String, data: Array[Byte], metadata: Array[Byte]): Unit

  final def receiver(
    name: String,
    onOpen: (String, Array[Byte]) => Unit = (_, _) => (),
    onClose: (String, Array[Byte]) => Unit = (_, _) => ()
  )(
    // scraps the id (first arg of onOpen / onClose)
    onMessage: Array[Byte] => Unit
  ): Unit = {
    val t = CommTarget(
      (_, data) => onMessage(data),
      (id, data) => onOpen(id, data),
      (id, data) => onClose(id, data)
    )
    registerCommTarget(name, t)
  }

  final def sender(
    targetName: String,
    id: String = UUID.randomUUID().toString,
    data: Array[Byte] = "{}".getBytes(StandardCharsets.UTF_8),
    metadata: Array[Byte] = "{}".getBytes(StandardCharsets.UTF_8),
    onMessage: (String, Array[Byte]) => Unit = (_, _) => (),
    onClose: (String, Array[Byte]) => Unit = (_, _) => ()
  ): Comm = {
    commOpen(targetName, id, data, metadata)
    val t = CommTarget(
      onMessage = (id, data) => onMessage(id, data),
      onOpen = (_, _) => (), // ignore since we open the comm from the kernel
      onClose = (id, data) => onClose(id, data)
    )
    registerCommId(id, t)
    new Comm {
      def message(data: Array[Byte], metadata: Array[Byte]) =
        commMessage(id, data, metadata)
      def close(data: Array[Byte], metadata: Array[Byte]) =
        commClose(id, data, metadata)
    }
  }
}

object CommHandler {

  abstract class Comm {
    def message(data: Array[Byte], metadata: Array[Byte]): Unit
    def close(data: Array[Byte], metadata: Array[Byte]): Unit
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy