Как написать сериализатор Kryo для SiddhiAppRuntime? - PullRequest
0 голосов
/ 04 марта 2020

В качестве первой попытки я написал следующий (нерабочий) код:

package com.my.alerting.siddhi

import com.esotericsoftware.kryo.io.{Input, Output}
import com.esotericsoftware.kryo.{Kryo, Serializer}
import io.siddhi.core.SiddhiAppRuntime

class SiddhiAppRuntimeSerializer extends Serializer[SiddhiAppRuntime] {
  override def write(kryo: Kryo, output: Output, runtime: SiddhiAppRuntime): Unit = {
    val runtimeSnapshot = runtime.snapshot()
    output.writeInt(runtimeSnapshot.length)
    output.writeBytes(runtimeSnapshot)
  }

  override def read(kryo: Kryo, input: Input, `type`: Class[SiddhiAppRuntime]): SiddhiAppRuntime = {
    val runtimeSnapshotLength = input.readInt()
    val runtimeSnapshot = input.readBytes(runtimeSnapshotLength)
    val runtime = `type`.newInstance()
    runtime.restore(runtimeSnapshot)

    runtime
  }
}

Но я понимаю, что не могу создать новый экземпляр времени выполнения, такой как val runtime = тип .newInstance(), поэтому Я пытаюсь что-то еще:

override def write(kryo: Kryo, output: Output, runtime: SiddhiAppRuntime): Unit = {
  val app = runtime.getSiddhiApp.toString
  val runtimeSnapshot = runtime.snapshot()
  output.writeString(app)
  output.writeInt(runtimeSnapshot.length)
  output.writeBytes(runtimeSnapshot)
 }
override def read(kryo: Kryo, input: Input, `type`: Class[SiddhiAppRuntime]): SiddhiAppRuntime = {
  val app = input.readString()
  val runtimeSnapshotLength = input.readInt()
  val runtimeSnapshot = input.readBytes(runtimeSnapshotLength)
  val manager = new SiddhiManager()
  val runtime = manager.createSiddhiAppRuntime(app)
  runtime.restore(runtimeSnapshot)

  runtime
 }

Однако вышеприведенный подход также не работает, потому что runtime.getSiddhiApp.toString не возвращает весь код приложения Siddhi, как я ожидал, поэтому я не могу использовать эту строку для создания SiddhiAppRuntime с помощью менеджера. Другая проблема заключается в необходимости создания SiddhiManager в методе read ... которого я бы предпочел избегать, если это возможно.

Пожалуйста, кто-нибудь может помочь с этим?

ОБНОВЛЕНИЕ: Это лучшее решение, которое я нашел до сих пор:

import com.esotericsoftware.kryo.io.{Input, Output}
import com.esotericsoftware.kryo.{Kryo, Serializer}
import io.siddhi.core.{SiddhiAppRuntime => SiddhiRuntime}

// A simple wrapper necessary because of https://github.com/siddhi-io/siddhi/issues/1630
case class SiddhiAppRuntime(app: String, runtime: SiddhiRuntime)

class SiddhiAppRuntimeSerializer() extends Serializer[SiddhiAppRuntime] with Serializable {

  override def write(kryo: Kryo, output: Output, appRuntime: SiddhiAppRuntime): Unit = {
    val runtimeSnapshot = appRuntime.runtime.snapshot()

    output.writeString(appRuntime.app)
    output.writeInt(runtimeSnapshot.length)
    output.writeBytes(runtimeSnapshot)
  }

  override def read(kryo: Kryo, input: Input, `type`: Class[SiddhiAppRuntime]): SiddhiAppRuntime = {
    val app                   = input.readString()
    val runtimeSnapshotLength = input.readInt()
    val runtimeSnapshot       = input.readBytes(runtimeSnapshotLength)

    // Isn't there a way to avoid this??
    val siddhiManager = new SiddhiManager()

    val runtime = siddhiManager.createSiddhiAppRuntime(app)
    runtime.restore(runtimeSnapshot)

    SiddhiAppRuntime(app, runtime)
  }

Однако, оно все еще полагается на объект SiddhiManager, которого я бы хотел избежать. Вместо этого сериализатор должен зависеть от существующего SiddhiManager. Я предполагаю, что, поскольку Сиддхи рекомендует иметь один SiddhiManager для каждой виртуальной машины Java, я мог бы положиться на глобальный одноэлементный объект. Интересно, однако, может ли это привести к конфликтным проблемам со многими потоками, обращающимися к различным средам выполнения приложений.

...