package com.sptmobile.voice import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow /** * In-memory [VoiceSpool] for JVM tests. Synchronized: the webhook server * calls [enqueue] from its socket thread while tests inspect from theirs. */ class FakeVoiceSpool : VoiceSpool { private val rows = mutableListOf() private var nextSeq = 1L private val count = MutableStateFlow(0) /** Simulate a durable-write failure (REQ-HAZARD-DICTATION-LOSS 500 path). */ @Volatile var failEnqueue = false @Synchronized override fun enqueue(transcription: String, recordedAtMs: Long): VoiceRow { if (failEnqueue) throw RuntimeException("simulated spool write failure") val row = VoiceRow( seq = nextSeq, msgId = "msg-$nextSeq", transcription = transcription, recordedAtMs = recordedAtMs, spooledAtMs = 111L, ) nextSeq += 1 rows += row count.value = rows.size return row } @Synchronized override fun oldest(): VoiceRow? = rows.firstOrNull() @Synchronized override fun remove(seq: Long) { rows.removeAll { it.seq == seq } count.value = rows.size } override val pending: Flow = count @Synchronized fun all(): List = rows.toList() }