Class FanOutAuditSink

java.lang.Object
com.mcpdbwizard.pub.FanOutAuditSink
All Implemented Interfaces:
McpAuditSink

public final class FanOutAuditSink extends Object implements McpAuditSink
Sends every record to several sinks, so a deployment can keep a local trail and stream.

MCP_AUDIT_SINK names one class, which was enough while the only question was where records went. It stopped being enough when the local trail became something every tier has: a licensed installation keeps records here for its window and sends them to Kafka or Splunk as well, and those are two sinks, not a choice between them.

Every member is told, whatever the others do

record(com.mcpdbwizard.pub.McpAuditEvent) catches per sink. One sink throwing must not stop the next from being told — and it must certainly not reach the caller, which is on the tool-call path with a real result to return.

flush() asks every member before answering, and never short-circuits. A && chain would skip flushing the second sink as soon as the first said no, which is the subtle version of not flushing at all: a spool in front of this would then be told "not delivered" by a sink that was never asked, and would keep replaying records the other member had already taken. Copyright 2003-2026 ATB Consultancy Services Ltd (formerly Orinda Software Ltd, Dublin, Ireland)

  • Constructor Details

    • FanOutAuditSink

      public FanOutAuditSink(McpAuditSink... theSinkValues)
  • Method Details

    • sinks

      public List<McpAuditSink> sinks()
      The members, in the order they are told.
    • record

      public void record(McpAuditEvent theEvent)
      Description copied from interface: McpAuditSink
      Record one call. Must not throw.
      Specified by:
      record in interface McpAuditSink
      Parameters:
      theEvent - the call to record; never null
    • flush

      public boolean flush()
      Description copied from interface: McpAuditSink
      Confirm that everything handed to McpAuditSink.record(com.mcpdbwizard.pub.McpAuditEvent) since the last flush is durably accepted.

      This is what makes a spool possible. A spool writes each record to disk first and may only delete it once the sink has genuinely taken it — and for an asynchronous sink like Kafka, record returning tells you nothing, because the send has not completed yet.

      The default returns true, which is correct for a sink that delivers synchronously inside record. An asynchronous sink must override it, and must return false if anything since the last flush was lost — returning true on a failed batch would let a spool delete records that never arrived, which is the one way a spool can be worse than no spool.

      Specified by:
      flush in interface McpAuditSink
      Returns:
      true if everything since the last flush is safely delivered
    • getDroppedCount

      public long getDroppedCount()
      The total known to be lost, or -1 when no member counts.

      Zero and -1 must stay distinguishable: -1 means nobody is counting, while 0 is a positive claim that nothing was lost. Summing a -1 into a total would turn the second into the first.

      Specified by:
      getDroppedCount in interface McpAuditSink
    • getDeliveredCount

      public long getDeliveredCount()
      Description copied from interface: McpAuditSink
      How many records were confirmed delivered, or -1 when the sink does not report.
      Specified by:
      getDeliveredCount in interface McpAuditSink
    • getPendingCount

      public long getPendingCount()
      Description copied from interface: McpAuditSink
      How many records are written down but not yet delivered, or -1 when not reported.
      Specified by:
      getPendingCount in interface McpAuditSink
    • describe

      public String describe()
      Description copied from interface: McpAuditSink
      A short human description of what this sink is, for an operator reading a status page.

      Defaults to the class name. A wrapper overrides it to name what it wraps — otherwise a spooled Kafka sink reports only "SpoolingAuditSink", and where the records finally go is the part being asked about.

      Specified by:
      describe in interface McpAuditSink
    • close

      public void close()
      Close every member, even if one of them fails.
      Specified by:
      close in interface McpAuditSink