diff --git a/docs/pages/persistence.md b/docs/pages/persistence.md index c0668ca..65666d4 100644 --- a/docs/pages/persistence.md +++ b/docs/pages/persistence.md @@ -4,16 +4,18 @@ title: Persistence --- # Persistence + {: .no_toc } ## Table of contents + {: .no_toc .text-delta } - TOC -{:toc} + {:toc} * **Persist** `StateMachine` - means transform it into serializable representation, such as `Serializable` object or - JSON text, and possibly saving it into some persistent storage like file or sending by network. + JSON text, and possibly saving it into some persistent storage like a file or sending by a network. * **Restoration** - is a process of restoring the `StateMachine` from the serializable representation. There are several kinds or levels of `StateMachine` persistence (serialization). Let's look at sample use cases: @@ -48,31 +50,58 @@ val machine = createStateMachine( } ``` -When the machine had processed necessary events, and you want to save its state configuration, first you have to -get the recorded events: +When the machine had processed your business logic events, and you want to save its state configuration, first you have +to get the recorded events: ```kotlin val recordedEvents = machine.eventRecorder.getRecordedEvents() ``` -`RecordedEvents` object now is ready to be serialized. The library provides an implementation +`RecordedEvents` object now is ready to be serialized. The library provides an implementation of serialization process using `kotlinx.serialization` library starting from `KStateMachine` version `v0.32.0`. -Alternatively you can use some other serialization library to serialize `RecordedEvents` object by your own. + +Initialize serialization format (JSON for instance): + +```kotlin + val jsonFormat = Json { + // use special, library provided SerializersModule for RecordedEvents and its internals + // from kstatemachine-serialization artifact + serializersModule = KStateMachineSerializersModule + SerializersModule { /* ... */ } +} +``` + +And encode (serialize) `RecordedEvents` object: + +```kotlin +val recordedEventsJson = jsonFormat.encodeToString(recordedEvents) +``` + +### Custom serialization library + +Alternatively you can use some other serialization library to serialize `RecordedEvents` class by your own +(you will also need to serialize `SerializableGeneratedEvent` class for internal events generated by the library +itself). ## Restoring StateMachine When a user wants to restore the StateMachine, he deserializes `RecordedEvents` object and -creates StateMachine instance having exactly the same structure as original one. +creates StateMachine instance having exactly the same structure as original one. Typically, both instances are created by the same code. +```kotlin +val restoredRecordedEvents = jsonFormat.decodeFromString(recordedEventsJson) +``` + Calling `restoreByRecordedEvents()` or its blocking analog `restoreByRecordedEventsBlocking()` will process recorded events over just created StateMachine instance. ```kotlin -machine.restoreByRecordedEvents(recordedEvents) +machine2.restoreByRecordedEvents(restoredRecordedEvents) ``` `restoreByRecordedEvents()` method will start the machine if necessary. You can configure restoration process by `restoreByRecordedEvents()` arguments. +The machine should not process any events before its restoration (in such case exception will be thrown) as +it can possibly lead to incorrect restoration result. See [Event recording sample](https://github.com/KStateMachine/kstatemachine/tree/master/samples/src/commonMain/kotlin/ru/nsk/samples/SerializationEventRecordingSample.kt) \ No newline at end of file diff --git a/kstatemachine-serialization/src/commonMain/kotlin/ru/nsk/kstatemachine/serialization/persistence/RecordedEventsSerializer.kt b/kstatemachine-serialization/src/commonMain/kotlin/ru/nsk/kstatemachine/serialization/persistence/RecordedEventsSerializer.kt index f111ad5..cf2b632 100644 --- a/kstatemachine-serialization/src/commonMain/kotlin/ru/nsk/kstatemachine/serialization/persistence/RecordedEventsSerializer.kt +++ b/kstatemachine-serialization/src/commonMain/kotlin/ru/nsk/kstatemachine/serialization/persistence/RecordedEventsSerializer.kt @@ -31,15 +31,10 @@ val KStateMachineSerializersModule = SerializersModule { polymorphic(Event::class) { subclass(SerializableGeneratedEvent::class, SerializableGeneratedEventSerializer) } - - contextual(SerializableGeneratedEventEventTypeStartSerializer) polymorphic(EventType::class) { subclass(EventType.Start::class, SerializableGeneratedEventEventTypeStartSerializer) subclass(EventType.Stop::class, SerializableGeneratedEventEventTypeStopSerializer) - subclass( - EventType.Destroy::class, - SerializableGeneratedEventEventTypeDestroySerializer - ) + subclass(EventType.Destroy::class, SerializableGeneratedEventEventTypeDestroySerializer) } } diff --git a/samples/src/commonMain/kotlin/ru/nsk/samples/SerializationEventRecordingSample.kt b/samples/src/commonMain/kotlin/ru/nsk/samples/SerializationEventRecordingSample.kt index 822933f..878287f 100644 --- a/samples/src/commonMain/kotlin/ru/nsk/samples/SerializationEventRecordingSample.kt +++ b/samples/src/commonMain/kotlin/ru/nsk/samples/SerializationEventRecordingSample.kt @@ -80,7 +80,6 @@ private suspend fun CoroutineScope.restoreStep(jsonFormat: Json, recordedEventsJ */ fun main(): Unit = runBlocking { val jsonFormat = Json { - ignoreUnknownKeys = true // use special, library provided SerializersModule for RecordedEvents and its internals // from kstatemachine-serialization artifact serializersModule = KStateMachineSerializersModule + SerializersModule {