Skip to content

Commit 8332f05

Browse files
committed
fix(EntityDiff): excluded fields missing from Deleted#previous
1 parent 8c464de commit 8332f05

File tree

4 files changed

+37
-25
lines changed

4 files changed

+37
-25
lines changed

integrations/builtin/src/main/kotlin/me/snoty/integration/builtin/diff/DiffNodeHandler.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging
44
import io.github.oshai.kotlinlogging.slf4j.logger
55
import io.ktor.http.*
66
import io.ktor.server.response.*
7+
import kotlinx.coroutines.flow.fold
78
import kotlinx.coroutines.flow.toList
89
import me.snoty.backend.utils.NULL_UUID
910
import me.snoty.backend.utils.bson.encode
@@ -71,8 +72,12 @@ abstract class DiffNodeHandler(
7172
}
7273
.toMap()
7374

74-
val rawOldStates = entityStateService.getLastStates(node._id)
75-
.toList()
75+
val rawOldStates: Map<String, EntityState> = entityStateService.getLastStates(node._id)
76+
.fold(mutableMapOf()) { acc, state ->
77+
acc[state.id] = state
78+
acc
79+
}
80+
7681
val (oldStates, changes) = processStates(rawOldStates, Data(newData), excludedFields)
7782

7883
entityStateService.updateStates(node._id, changes.values)
@@ -103,17 +108,21 @@ private fun Document.removeAll(fields: Collection<String>) {
103108
}
104109

105110
internal fun processStates(
106-
oldStates: List<EntityState>,
111+
oldStates: Map<String, EntityState>,
107112
newData: DiffNodeHandler.Data,
108113
excludedFields: Collection<String>
109114
): Pair<DiffNodeHandler.States, DiffNodeHandler.Changes> {
115+
val fullOldStates = oldStates
110116
val oldStates = oldStates
111117
// remove excluded fields to not consider them in the diff
112-
.map {
113-
it.state.removeAll(excludedFields)
114-
it.copy(checksum = it.state.checksum())
118+
.mapValues { (_, it) ->
119+
val newState = Document(it.state)
120+
newState.removeAll(excludedFields)
121+
it.copy(
122+
state = newState,
123+
checksum = newState.checksum()
124+
)
115125
}
116-
.associateBy { it.id }
117126

118127
val createAndUpdate = newData
119128
.mapValues { (id, newState) ->
@@ -125,16 +134,15 @@ internal fun processStates(
125134

126135
EntityStateService.EntityStateUpdate(EntityState(id, newState), diff)
127136
}
128-
val delete = oldStates
137+
val delete = fullOldStates
129138
// we only care about deleted entities
130139
.filterKeys { it !in newData }
131-
.mapValues { (id, _) ->
132-
val oldState = oldStates[id] ?: error("Old state not found for entity $id")
140+
.mapValues { (_, oldState) ->
133141
// `null.diff` results in `DiffResult.Deleted`
134142
EntityStateService.EntityStateUpdate(oldState, null.diff(oldState))
135143
}
136144

137145
val allUpdates = createAndUpdate + delete
138146

139-
return DiffNodeHandler.States(oldStates) to DiffNodeHandler.Changes(allUpdates)
147+
return DiffNodeHandler.States(fullOldStates) to DiffNodeHandler.Changes(allUpdates)
140148
}

integrations/builtin/src/main/kotlin/me/snoty/integration/builtin/diff/injector/DiffInjectorNodeHandler.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package me.snoty.integration.builtin.diff.injector
33
import kotlinx.serialization.Serializable
44
import me.snoty.backend.wiring.node.NodesScope
55
import me.snoty.integration.builtin.diff.DiffNodeHandler
6+
import me.snoty.integration.common.annotation.ReceiveEmptyInput
67
import me.snoty.integration.common.annotation.RegisterNode
78
import me.snoty.integration.common.diff.DiffResult
89
import me.snoty.integration.common.diff.EntityStateService
@@ -49,6 +50,7 @@ data class HasDiff(
4950
inputType = EmptySchema::class,
5051
outputType = EmptySchema::class,
5152
)
53+
@ReceiveEmptyInput
5254
@Single
5355
class DiffInjectorNodeHandler(
5456
@ScopeId(NodesScope::class) entityStateService: EntityStateService,
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
<button onclick="
2-
templateAPI.getNodeAPI('{{ node._id }}').apiFetch('clear', { method: 'POST' })
3-
.then(res => {
4-
if (res.ok) {
5-
alert('Successfully cleared states')
6-
} else {
7-
alert('Failed to clear states')
8-
}
9-
})
10-
"
11-
class="btn preset-filled"
1+
<a class="anchor" href="{{ node.apiUrl }}state">View states</a>
2+
3+
<button style="margin-top: 2em" onclick="
4+
templateAPI.getNodeAPI('{{ node._id }}').apiFetch('clear', { method: 'POST' })
5+
.then(res => {
6+
if (res.ok) {
7+
alert('Successfully cleared states')
8+
} else {
9+
alert('Failed to clear states')
10+
}
11+
})
12+
"
13+
class="btn preset-filled block"
1214
>
1315
Clear States
1416
</button>
15-
<small>Warning: this will delete all historic states. All entities will be reset to the status "Created"!</small>
17+
<small class="block">Warning: this will delete all historic states. All entities will be reset to the status "Created"!</small>

integrations/builtin/src/test/kotlin/me/snoty/integration/builtin/diff/DiffNodeHandlerTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class DiffNodeHandlerTest {
2525
val (old, new) = getDocs()
2626

2727
val (_, newStates) = processStates(
28-
oldStates = listOf(EntityState(id, old)),
28+
oldStates = mapOf(id to EntityState(id, old)),
2929
newData = DiffNodeHandler.Data(mapOf(id to new)),
3030
excludedFields = listOf(excluded),
3131
)
@@ -43,7 +43,7 @@ class DiffNodeHandlerTest {
4343
new[key] = value
4444

4545
val (_, newStates) = processStates(
46-
oldStates = listOf(EntityState(id, old)),
46+
oldStates = mapOf(id to EntityState(id, old)),
4747
newData = DiffNodeHandler.Data(mapOf(id to new)),
4848
excludedFields = listOf(excluded),
4949
)

0 commit comments

Comments
 (0)