{
  "$schema" : "https://json-schema.org/draft/2020-12/schema",
  "$id" : "https://voltdb.com/voltsp/schemas/source/kafka",
  "title" : "Kafka Source Configuration",
  "description" : "The `kafka` source consumes data from an Apache Kafka topic. It allows configuration of consumer properties,\nsuch as topic names, bootstrap servers, poll timeout, starting offsets, and more.\nThis source is suitable for integrating real-time data from Kafka into your streaming pipeline.\n\nThe record's key and headers are written to the stage-scoped {@link org.voltdb.stream.api.StashContext}\nand are available during event processing within current stage - starting from this source to the terminator (sink or emitter).\nEach time the new record is read from the kafka source, the key and headers are replaced within the context.\n\nAvailable stash entries:\n\n| Entry   | Java (typed key)         | YAML / JS / Python (name) | Runtime type          |\n|---------|--------------------------|---------------------------|-----------------------|\n| Key     | `KafkaStashKeys.KEY`     | `source.kafka.key`        | `Object`              |\n| Headers | `KafkaStashKeys.HEADERS` | `source.kafka.headers`    | `Map<String, String>` |\n\nHeaders are off by default; set the `includeHeaders` option to enable them.\n",
  "type" : "object",
  "properties" : {
    "kafka" : {
      "type" : "object",
      "properties" : {
        "bootstrapServers" : {
          "description" : "A list of host/port pairs used to establish the initial connection to the Kafka cluster. Clients use this list to bootstrap and discover the full set of Kafka brokers.",
          "anyOf" : [ {
            "type" : "string"
          }, {
            "type" : "array",
            "items" : {
              "type" : "string"
            }
          } ]
        },
        "topicNames" : {
          "anyOf" : [ {
            "type" : "string"
          }, {
            "type" : "array",
            "uniqueItems" : true,
            "items" : {
              "type" : "string"
            }
          } ]
        },
        "groupId" : {
          "type" : "string",
          "description" : "A unique string that identifies the consumer group this consumer belongs to."
        },
        "startingOffset" : {
          "type" : "string",
          "description" : "What to do when there is no initial offset in Kafka or if the current offset does not exist any more:\n- earliest: automatically reset the offset to the earliest offset.\n- latest: automatically reset the offset to the latest offset.\n- none: throw exception to the consumer if no previous offset is found for the consumer's group.\n\nEquivalent to Kafka `auto.offset.reset` setting.\n",
          "default" : "earliest",
          "enum" : [ "earliest", "latest", "none", "EARLIEST", "LATEST", "NONE" ]
        },
        "pollTimeout" : {
          "type" : "string",
          "pattern" : "^(\\d+[smhd]|P(T|\\d+[YMD]).*)",
          "description" : "The maximum time to block the receiving thread.",
          "default" : "1s"
        },
        "maxCommitTimeout" : {
          "type" : "string",
          "pattern" : "^(\\d+[smhd]|P(T|\\d+[YMD]).*)",
          "description" : "Sets the maximum timeout for commit retries.",
          "default" : "10s"
        },
        "maxCommitRetries" : {
          "type" : "integer",
          "description" : "Configures the maximum number of retries for committing offsets.",
          "default" : "3",
          "minimum" : -2147483648,
          "maximum" : 2147483647
        },
        "maxPollRecords" : {
          "type" : "integer",
          "description" : "Specifies the maximum number of records to retrieve in a single poll.",
          "default" : "10000",
          "minimum" : -2147483648,
          "maximum" : 2147483647
        },
        "properties" : {
          "type" : "object",
          "description" : "Adds or overrides a specific Kafka client property, allowing customization for advanced configurations.",
          "additionalProperties" : {
            "type" : "string"
          }
        },
        "keyDeserializer" : {
          "type" : "string",
          "description" : "Kafka key deserializer",
          "default" : "org.apache.kafka.common.serialization.ByteBufferDeserializer"
        },
        "valueDeserializer" : {
          "type" : "string",
          "description" : "Kafka value deserializer",
          "default" : "org.apache.kafka.common.serialization.ByteBufferDeserializer"
        },
        "exceptionHandler" : {
          "type" : "string",
          "description" : "Custom exception handler enabling interception of all errors related to this source."
        },
        "ssl" : {
          "type" : "object",
          "description" : "SSL configuration.",
          "properties" : {
            "trustStoreFile" : {
              "type" : "string",
              "description" : "Truststore file or trusted CA certificate; supported formats include JKS, PKCS#12, or PEM."
            },
            "trustStorePassword" : {
              "type" : "string",
              "description" : "Truststore password."
            },
            "keyStoreFile" : {
              "type" : "string",
              "description" : "Keystore file; supported formats include JKS, PKCS#12, or PEM"
            },
            "keyStorePassword" : {
              "type" : "string",
              "description" : "Keystore password."
            },
            "keyPassword" : {
              "type" : "string",
              "description" : "Private key password. Optional — if not set, the key store password will be used."
            },
            "insecure" : {
              "type" : "boolean",
              "description" : "If set to true, disables SSL certificate and hostname validation.\nIntended for debugging purposes only. Doesn't work with mTLS.\n"
            },
            "hostnameVerifier" : {
              "type" : "string",
              "description" : "Custom hostname verifier for SSL connections.\nIf not specified and 'insecure' is true, hostname verification will be disabled.\n"
            }
          },
          "additionalProperties" : false
        },
        "schemaRegistryUrl" : {
          "type" : "string",
          "description" : "Schema registry URL"
        },
        "includeHeaders" : {
          "type" : "boolean",
          "description" : "Whether to deserialise Kafka record headers into the stash context.",
          "default" : "false"
        }
      },
      "required" : [ "bootstrapServers", "topicNames", "groupId", "startingOffset", "keyDeserializer", "valueDeserializer" ],
      "additionalProperties" : false
    }
  },
  "required" : [ "kafka" ],
  "additionalProperties" : false
}
