Skip to content

Commit

Permalink
[docs] Improve serialisation doc
Browse files Browse the repository at this point in the history
  • Loading branch information
nsk90 committed Oct 23, 2024
1 parent 5d43c4f commit b81e9db
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 15 deletions.
45 changes: 37 additions & 8 deletions docs/pages/persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<RecordedEvents>(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)
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit b81e9db

Please sign in to comment.