Class CommandsConsumer
java.lang.Object
app.l2nx.gs.adapter.core.commands.CommandsConsumer
Inbound commands consumer + dispatcher. Owns one Kafka
Consumer on
a single daemon thread nx-commands-consumer. Polls
commandsTopic, resolves handlers via
CommandTypeRegistry, deserializes via Gson, invokes
CommandHandler.handle(C, app.l2nx.gs.adapter.api.spi.CommandContext), publishes the CommandResult reply
to commandsRepliesTopic, awaits the per-batch reply-flush, then
commits the batch offset.
Threading model — CommandHandler.handle(C, app.l2nx.gs.adapter.api.spi.CommandContext) runs synchronously on
the consumer thread; game-state mutations require an explicit
HostExecutor.sync(Runnable) hop bounded by
l2nx.commands.host-sync-timeout-ms. Slow handlers slow this consumer.
At-least-once contract on both legs — for every batch:
- Dispatch all records, issuing reply sends asynchronously.
- Await up to
l2nx.commands.reply-flush-timeout-msfor the producer's send-callbacks to fire (i.e. broker has acknowledged or definitively failed). This bounds the at-most-once reply window: a JVM crash before the flush completes leaves the batch uncommitted, so the records redeliver and the handlers re-emit the replies (handlers must be idempotent). commitSyncthe consumer offset.
Error boundaries (per dispatch step):
- Unknown
Nx-Message-Type→ replyErrorCode.UNSUPPORTED_COMMAND, commit. - Gson
JsonSyntaxException→ replyErrorCode.VALIDATION_FAILED, commit. - Handler
HostExecutorTimeoutException→ replyErrorCode.UNAVAILABLEwitherror.cause = "host-executor-timeout", commit (handler hop did not finish in time; web side may retry). - Handler
RuntimeException→ replyErrorCode.INTERNAL_ERRORwith class+message inerrorDetails, commit. - Handler returns
null→ replyErrorCode.INTERNAL_ERRORwitherror.cause = "handler-returned-null", commit. - Handler
Throwable(OOM / Error) → log ERROR, do NOT reply, do NOT commit, rethrow (consumer thread aborts; JVM-level handler decides next).
Reply path bypasses the events publisher's queue and goes directly to
the Kafka producer via the supplied CommandsConsumer.ReplySender bridge — Kafka's
own record-accumulator absorbs back-pressure, and reply records have
different drop semantics from outbound events (a dropped reply means
web-side timeout, no semantic recovery).
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceBridge to the actual Kafka send. -
Method Summary
Modifier and TypeMethodDescriptionapp.l2nx.gs.adapter.api.kafka.ops.ModuleStatusHeartbeat slot snapshot for thecommandsmodule.voidstart()Spawn the consumer daemon and subscribe toinboundTopic.voidstop()Signal the daemon to stop, wake it from any blocking poll, await join up toshutdownTimeoutMs, then close the Kafka consumer.
-
Method Details
-
start
public void start()Spawn the consumer daemon and subscribe toinboundTopic. Idempotent. -
stop
public void stop()Signal the daemon to stop, wake it from any blocking poll, await join up toshutdownTimeoutMs, then close the Kafka consumer. Idempotent. -
currentStatus
public app.l2nx.gs.adapter.api.kafka.ops.ModuleStatus currentStatus()Heartbeat slot snapshot for thecommandsmodule.
-