Conversation
# Conflicts: # src/main/kotlin/io/github/inductiveautomation/kindling/cache/hsql/CacheView.kt # src/main/kotlin/io/github/inductiveautomation/kindling/utils/Sql.kt # src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt
paul-griffith
left a comment
There was a problem hiding this comment.
Some mostly minor stuff. Still hoping to find time for some exploration to see if there's a "better" way to do this, but may merge this and get it into a release ~sooner if that doesn't work out
| // 8.3 | ||
|
|
||
| fun ByteArray.deserializeStoreAndForward(flavor: String): List<GeneratedMessageV3> { | ||
| val parseFunction: (ByteArray) -> GeneratedMessageV3 = when (flavor) { |
There was a problem hiding this comment.
I think there's a better pattern to explore here where we fully instantiate the underlying S+F serdes delegates instead of relying on the "raw" proto classes, especially because if we can do that we can rely on them having a built in JSON representation format we can display and not have to generate our own toDetail impls
There was a problem hiding this comment.
fully instantiate the underlying S+F serdes delegates
I was able to get this working with the history set, but there is no conversion logic included in the SDK to go from the Alarm Journal protobuf class to its actual normal class.
if we can do that we can rely on them having a built in JSON representation format
Even for the history set, the function to print as json was stupidly not public from what I could tell. Not a huge deal, but I had to use the protobuf JsonFormat.printer().print() on the protobuf-generated class to achieve a JSON output. It looks like the private function that prints these classes as JSON implicitly converts them to the PB-generated class first.
I'm gonna leave this one unresolved, because I just don't see a better way to do it without a bunch of work to write our own delegated classes for these PB classes.
There was a problem hiding this comment.
What I'm talking about is something like this:
Index: src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt b/src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt
--- a/src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt (revision e8c94d4709b2dd0d64a97cfac199ab3bd897d0ac)
+++ b/src/main/kotlin/io/github/inductiveautomation/kindling/utils/StoreAndForward.kt (date 1759881879435)
@@ -6,8 +6,12 @@
import com.inductiveautomation.ignition.gateway.alarming.journal.encoding.AlarmJournalProto
import com.inductiveautomation.ignition.gateway.history.encoding.GenericObjectProto
import com.inductiveautomation.ignition.gateway.history.encoding.HistoryDataProto
+import com.inductiveautomation.ignition.gateway.storeforward.data.PersistentData
import com.inductiveautomation.ignition.gateway.storeforward.deprecated.BasicHistoricalRecord
import com.inductiveautomation.ignition.gateway.storeforward.deprecated.ScanclassHistorySet
+import com.inductiveautomation.ignition.gateway.storeforward.flavor.PersistentFlavor
+import com.inductiveautomation.ignition.gateway.storeforward.data.history.BasicHistoricalRecord as HistoricalRecord
+import com.inductiveautomation.ignition.gateway.storeforward.serialization.DeserializationContext
import io.github.inductiveautomation.kindling.cache.AliasingObjectInputStream
import io.github.inductiveautomation.kindling.cache.hsql.model.AbstractDataset
import io.github.inductiveautomation.kindling.cache.hsql.model.AlarmJournalData
@@ -122,7 +126,18 @@
// 8.3
+object SFDeserializer : DeserializationContext {
+ private val map = mapOf<String, PersistentFlavor<*>>(
+ "history_set" to HistoricalRecord.FLAVOR,
+ )
+
+ override fun fromBytes(bytes: ByteArray, flavorKey: String): PersistentData? {
+ return map[flavorKey]?.serializer()?.fromBytes(bytes, this)
+ }
+}
+
fun ByteArray.deserializeStoreAndForward(flavor: String): List<GeneratedMessageV3> {
+ SFDeserializer.fromBytes(this, flavor)
val parseFunction: (ByteArray) -> GeneratedMessageV3 = when (flavor) {
"history_set" -> {
HistoryDataProto.HistorySetPB::parseFromIn theory, if the individual serializers are good about being "pure" and not implicitly relying on anything from a running gateway/context, this allows us to side step all the proto related logic (except for some generic fallback behavior). This isn't fully baked and I have no idea if it works, this is just me throwing something together in literally five minutes that compiles. I don't think we have to do things this way for this PR, but I do think this is the "right" way to do things here
There was a problem hiding this comment.
@paul-griffith So this works for the history set, but I believe that's the only class in the SDK which has everything defined to be used like that.
It looks like in order to get this strategy working for other classes (assuming the protobuf version exists in the SDK), we'll need to write the class ourselves, and then define the flavor for it, which includes defining the serialization logic ourselves as well. It's possible but a lot of work for each class. It doesn't seem ideal.
This includes a few changes which I did test, though problems might creep up related to backwards compatibility (Hopefully not).
Changes
StoreAndForward.kthsqlandsqlitepackages under the Cache viewer tool's packageUsage
There are 3 ways you can open an 8.3 S&F Cache:
Protobuf
Spotless
$$string interpolation prefix has been added where it was prompted by the IDE.