r.0.9.1.source-code.FanoutChannel.kt Maven / Gradle / Ivy
The newest version!
package se.wollan.tolr
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
internal interface FanoutReceiveChannel {
fun startReceiving(filter: RecordTypePattern): ReceiveChannel
fun stopReceiving(channel: ReceiveChannel)
}
internal interface FanoutSendChannel {
suspend fun send(record: LogRecord)
suspend fun send(records: Collection)
}
internal class FanoutChannel(private val capacity: Int = 100) : FanoutReceiveChannel, FanoutSendChannel {
private val receivers = mutableSetOf, RecordTypePattern>>()
override fun startReceiving(filter: RecordTypePattern): ReceiveChannel {
val channel = Channel(capacity = capacity, onBufferOverflow = BufferOverflow.SUSPEND)
synchronized(receivers) {
receivers.add(channel to filter)
}
return channel
}
override fun stopReceiving(channel: ReceiveChannel) {
synchronized(receivers) {
receivers.removeAll { it.first === channel }
}
channel.cancel()
}
override suspend fun send(record: LogRecord) {
val receivers = synchronized(receivers) {
receivers.toSet()
}
if (receivers.isEmpty())
return
fanout(receivers, record)
}
override suspend fun send(records: Collection) {
if (records.isEmpty())
return
val receivers = synchronized(receivers) {
receivers.toSet()
}
if (receivers.isEmpty())
return
for (record in records) {
fanout(receivers, record)
}
}
private suspend fun fanout(
receivers: Set, RecordTypePattern>>,
record: LogRecord
) {
for ((channel, filter) in receivers) {
if (filter.matches(record.type))
channel.send(record)
}
}
}