Skip to content

Commit 45c7fd5

Browse files
committed
fix concurrency
1 parent 2367cff commit 45c7fd5

2 files changed

Lines changed: 20 additions & 14 deletions

File tree

acp/src/commonMain/kotlin/com/agentclientprotocol/client/ElicitationSessionStore.kt

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import com.agentclientprotocol.annotations.UnstableApi
44
import com.agentclientprotocol.model.ElicitationId
55
import com.agentclientprotocol.model.SessionId
66
import kotlinx.atomicfu.atomic
7+
import kotlinx.atomicfu.update
8+
import kotlinx.collections.immutable.persistentMapOf
79

810
/**
911
* A mutable, bounded map from [ElicitationId] to [SessionId] with bulk eviction.
@@ -19,34 +21,38 @@ internal class ElicitationSessionStore(
1921
private data class Entry(val sessionId: SessionId, val ordinal: Long)
2022

2123
private val counter = atomic(0L)
22-
private val entries: MutableMap<ElicitationId, Entry> = mutableMapOf()
24+
private val entries = atomic(persistentMapOf<ElicitationId, Entry>())
2325

24-
operator fun get(elicitationId: ElicitationId): SessionId? = entries[elicitationId]?.sessionId
26+
operator fun get(elicitationId: ElicitationId): SessionId? = entries.value[elicitationId]?.sessionId
2527

2628
fun put(elicitationId: ElicitationId, sessionId: SessionId) {
27-
entries[elicitationId] = Entry(sessionId, counter.getAndIncrement())
28-
if (entries.size > maxCapacity) {
29+
entries.update { it.put(elicitationId, Entry(sessionId, counter.getAndIncrement())) }
30+
if (entries.value.size > maxCapacity) {
2931
evictOldestHalf()
3032
}
3133
}
3234

3335
fun remove(elicitationId: ElicitationId): SessionId? {
34-
return entries.remove(elicitationId)?.sessionId
36+
val sessionId = entries.value[elicitationId]?.sessionId
37+
entries.update { it.remove(elicitationId) }
38+
return sessionId
3539
}
3640

3741
fun removeBySession(sessionId: SessionId) {
38-
entries.entries.removeAll { it.value.sessionId == sessionId }
42+
val toRemove = entries.value.filter { it.value.sessionId == sessionId }.map { it.key }
43+
entries.update {
44+
toRemove.fold(it) { acc, elicitationId -> acc.remove(elicitationId) }
45+
}
3946
}
4047

4148
private fun evictOldestHalf() {
42-
val toRemove = entries.entries
49+
val value = entries.value
50+
val toRemove = value.entries
4351
.sortedBy { it.value.ordinal }
44-
.take(entries.size / 2)
52+
.take(value.size / 2)
4553
.map { it.key }
46-
if (entries.size > maxCapacity) {
47-
for (key in toRemove) {
48-
entries.remove(key)
49-
}
54+
entries.update {
55+
toRemove.fold(it) { acc, elicitationId -> acc.remove(elicitationId) }
5056
}
5157
}
5258

acp/src/commonMain/kotlin/com/agentclientprotocol/protocol/Protocol.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ public class Protocol(
192192
*/
193193
public override suspend fun sendRequestRaw(
194194
method: MethodName,
195-
params: JsonElement? = null,
196-
sessionId: SessionId? = null
195+
params: JsonElement?,
196+
sessionId: SessionId?
197197
): JsonElement {
198198
val requestId = OutgoingRequestId(RequestId.create(requestIdCounter.incrementAndGet()))
199199
val deferred = CompletableDeferred<JsonElement>()

0 commit comments

Comments
 (0)