Demo 3: Playground

The Portals playground is a JavaScript-based sandbox capable of running Portals applications that hosts a code editor for writing programs and an output log. It comes with a JavaScript API, and the runtime is executed fully within the browser. The Playground supports most of the core API, and can be used to write multi-dataflow applications and Portal applications, as described in the other two demonstration scenarios.

The Portals Playground is implemented with Scala using the Scala-JS library. Thus, the core runtime (Scala) and the JavaScript runtime share most of the code-base. This enables Portals to run both on lightweight edge devices with the JS runtime, and on cloud instances with the JVM runtime.

The Playground is available at https://portals-project.org/playground/.

Example 1 – Hello VLDB!

The Hello VLDB Example is one of many examples that can be found on the playground website. It simply consists of a generator that generators a single event: “Hello VLDB!”, and a workflow which consumes this generated stream and logs it to the console. The code for this example is shown below.

let builder = PortalsJS.ApplicationBuilder("helloVLDB")
let _ = builder.workflows
  .source(builder.generators.fromArray(["Hello VLDB!"]).stream)
  .logger()
  .sink()
  .freeze()
let helloVLDB = builder.build()
let system = PortalsJS.System()
system.launch(helloVLDB)
system.stepUntilComplete()

Run this example in the playground.

Example 2 – Multi Dataflow

The Multi Dataflow example shows how we can compose together multiple dataflows using workflows, sequencers, and splitters.

let builder = PortalsJS.ApplicationBuilder("MultiDataflow")
let generator = builder.generators.fromArrayOfArrays([["Hello"], ["World"]])
let wf1 = builder.workflows
  .source(generator.stream)
  .map(ctx => x => x.toUpperCase())
  .logger("from wf1: ")
  .sink()
  .freeze()
let wf2 = builder.workflows
  .source(wf1.stream)
  .map(ctx => x => x.toLowerCase())
  .logger("from wf2: ")
  .sink()
  .freeze()
let sequencer = builder.sequencers.random()
let wf3 = builder.workflows
  .source(sequencer.stream)
  .flatMap(ctx => x => x.length > 0 ? [x.slice(1)] : [])
  .logger("from wf3: ")
  .sink()
  .freeze()
let c1 = builder.connections.connect(wf2.stream, sequencer)
let c2 = builder.connections.connect(wf3.stream, sequencer)
let splitter = builder.splitters.empty(wf3.stream)
let split = builder.splits.split(splitter, x => x.length % 2 == 0)
let wf4 = builder.workflows
  .source(split)
  .logger("from wf4: ")
  .sink()
  .freeze()
let multiDataflow = builder.build()
let system = PortalsJS.System()
system.launch(multiDataflow)
system.stepUntilComplete()

More Examples

There are more examples available at https://portals-project.org/playground/.