В качестве первой попытки я написал следующий (нерабочий) код:
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, я мог бы положиться на глобальный одноэлементный объект. Интересно, однако, может ли это привести к конфликтным проблемам со многими потоками, обращающимися к различным средам выполнения приложений.