Skip to content
Bluetape4k docs1.11

Async channel and lifecycle

Latest stable Based on Bluetape4k release 1.11.0

KLoggingChannel publishes events to a MutableSharedFlow; a background collector emits them to SLF4J. This separates caller latency from emission lifecycle at the cost of buffering and shutdown contracts.

KLoggingChannel send, collect, close, and post-close flow

  • replay is 0;
  • extra buffer capacity is 64;
  • overflow policy is SUSPEND;
  • default instances share Dispatchers.IO + SupervisorJob + CoroutineName("logchannel");
  • one JVM shutdown hook cancels the shared job.

SUSPEND does not mean unbounded asynchronous delivery. When a slow collector fills the buffer, send suspends in emit.

class ImportWorker : AutoCloseable {
private val logger = object : KLoggingChannel() {}
suspend fun run(id: String) {
logger.info { "Import started id=$id" }
}
override fun close() = logger.close()
}

close() is idempotent and cancels only this instance’s collector. An injected CoroutineScope remains caller-owned. Tests and suspend lifecycle callbacks can use closeAndJoin() to wait for collector termination.

Close currently cancels; it does not drain. Events buffered immediately before close are not guaranteed to reach the backend. send after close drops the event without blocking. This is not a transport for audit or must-persist events.

The collector catches an exception from an individual emission and attempts an error log. It rethrows CancellationException to preserve cancellation semantics.

ConditionChoice
Ordinary request/service logsKLogging
Measured appender bottleneck and suspend backpressure acceptableconsider KLoggingChannel
Every pending event must survive shutdowndurable queue or explicit drain design
Audit/security eventdurable event pipeline, not a logging channel

Finish with configuration and diagnostics in Operations & recipes.