Configuration Keys
Every key of the wow.* configuration a Spring Boot host reads, 284 in all, generated from the host's configuration metadata (spring-configuration-metadata.json). Spring Boot binds them relaxed: max-concurrent, maxConcurrent and MAX_CONCURRENT are one key. A wow.* key that no property of the host or of a module on the class path names refuses the node's start, pointing at the migration guide's page of the keys of earlier versions. So does an environment variable under a Wow group (WOW_KAFKA_…: the first word of a key), read as Spring maps it; give a variable of your own a name outside these groups. A key below a map takes the map's key in brackets when it holds a dot: wow.aggregates.[shop.cart].tenant; each map's own keys are listed below it, its entry written <name> or [<context>.<aggregate>]. Module Configuration Keys lists the keys of the platform services, of wow-cosid and of wow-cocache. The keys are the contract, not the host's property classes, which are Wow's own: an application reads a key through Spring's Environment, @Value or a Binder.
wow
| Key | Type | Default | Description |
|---|---|---|---|
wow.aggregates | Map<String,Aggregate> | Per aggregate type, by <context>.<aggregate> (bracketed in a property name: wow.aggregates.[shop.cart]). | |
wow.backend | String | auto | The backend of a node that names no wow.stores: auto (the default) takes PostgreSQL or MongoDB by the application's DataSource or MongoClient, and refuses to start without either, so that data is not lost by mistake, unless a profile of wow.dev-profiles is active or the internal port binds the loopback interface alone; memory keeps the data in memory on purpose, for one node whose data does not outlive it. postgres, mongo or the type of a community backend's store provider (me.ahoo.wow.spi.store.StoreProvider) name one. |
wow.callers | Map<String,CallerPermits> | What each service that calls this one may call and read on the internal port, by the name it states (Wow-Service, its spring.application.name): optional lists that catch a misconfiguration. The internal port is reachable by the platform's own pods alone; a service that names itself is taken on that network's word. | |
wow.ddl | Ddl | auto | How the stores manage the framework's tables, collections and indexes: auto creates what is missing (the default), validate creates nothing and refuses a store whose schema is missing or in another format, none creates and checks nothing; wow.stores.<name>.ddl overrides it for one store. |
wow.dev-profiles | Set<String> | dev, local, test, demo | The profiles in which the node runs for development, as it does when its internal port binds a loopback address alone: wow.backend=auto falls back to memory when no durable backend is available, the public port serves without a CallerResolver bean, a single Kafka broker gives no durability warning, and a platform service may take its callers from request headers. None of them is allowed in a deployment. |
wow.peers | Map<String,PeerTarget> | The peer contexts called over HTTP, by context (wow.peers.<context>.*): a saga's synchronous calls to that context and the typed clients of it go to its service, at its url when one is set, else where wow.peer.discovery finds the service its contract names (DNS by default). A node whose saga calls a context it cannot reach does not start. | |
wow.routing | CommandRouting | auto | Where commands run (CommandRouting): auto, on the owner of the aggregate's partition, or here on the memory backend, which cannot route across nodes; partitioned; local; or topic, through each context's command topic. An aggregate type's wow.aggregates.[<context>.<aggregate>].routing comes before it. |
wow.schedules | Map<String,Schedule> | Per @OnSchedule job, by its name: wow.schedules.<job>.* holds all of the job's settings, its rule and the retries of the subscriptions that run it. A job no handler of the node runs fails its start, and so does a job's subscription configured under wow.subscriptions. | |
wow.service | String | The service's name; spring.application.name when not set. | |
wow.stores | Map<String,Store> | The named store instances, by name: wow.stores.<name>.type and its settings. The aggregates whose logs are on one store form a log group, with its own partition sequences, checkpoints, parked entries and timers. | |
wow.subscriptions | Map<String,SubscriptionSettings> | Per subscription, by its context and name, <context>.<name>, bracketed in a property name (wow.subscriptions.[shop.CartSaga.onOrderCreated], wow.subscriptions.[shop.wow.snapshot]): a name is unique within its context alone. | |
wow.transport | String | auto | The node's topic transport: auto (the default) takes the transport a provider finds configured (Kafka with wow.kafka.bootstrap-servers); without one, the topics are in the node's JVM when it runs for development (a profile of wow.dev-profiles, or a loopback internal port), and otherwise it has none: the node then publishes no stream, and refuses to start when it needs topics (topic routing, command intake, ledger publishing set to true). memory keeps the topics in the JVM on purpose, for development alone; none gives the node no topics in any profile, whatever is configured, with the same refusal; kafka, or a community provider's type, names the transport. A blank wow.kafka.bootstrap-servers is no way to turn the topics off: in development it falls back to the topics in the JVM. |
wow.access
How each context's built-in subscription wow.access stamps an aggregate's access attributes over its history when a commit changes them: wow.access.*.
| Key | Type | Default | Description |
|---|---|---|---|
wow.access.capacity | Integer | 100000 | The aggregates whose last stamped attributes the subscription remembers, sparing it a read of the stream before. |
wow.access.stamp-batch | Integer | 1000 | The most streams one stamp writes: a long history is stamped in statements of at most this many. |
wow.access.walk-batch | Integer | 100 | The most aggregates a page of an access walk stamps; the walk records how far it is after each page, about every five seconds at its pace. |
wow.access.walk-rate | Integer | 500 | The most aggregates an access walk stamps a second, each one's whole history and its snapshot, however large its share. |
wow.access.walk-share | Double | 0.25 | The most of the time an access walk takes, as a share of one connection of the log store's, above 0 and at most 1: after each aggregate it waits so its stamping took at most this share. While the store's writes press it gives way, down to an eighth of it. Raise it in a maintenance window to walk faster. |
wow.aggregates.[<context>.<aggregate>]
Per aggregate type, by <context>.<aggregate> (bracketed in a property name: wow.aggregates.[shop.cart]).
| Key | Type | Default | Description |
|---|---|---|---|
wow.aggregates.[<context>.<aggregate>].clickhouse.history.enabled | Switch | auto | Whether every commit of the type is kept: auto, the Sink's default, keeps it; true or false decide. |
wow.aggregates.[<context>.<aggregate>].clickhouse.history.ttl | Duration | How long the type's history is kept; forever when not set. | |
wow.aggregates.[<context>.<aggregate>].id-generator | String | The id generator that gives the type's new ids, by name. | |
wow.aggregates.[<context>.<aggregate>].log.store | String | The store of wow.stores the type's log is on, over wow.log.store. | |
wow.aggregates.[<context>.<aggregate>].query.events.store | String | The store of wow.stores the type's events queries read; its log store when not set. | |
wow.aggregates.[<context>.<aggregate>].query.events.unpinned | UnpinnedEvents | Whether an events query of the type that names no aggregate runs, over its store's. | |
wow.aggregates.[<context>.<aggregate>].query.snapshot.store | String | The snapshot store the type's snapshot queries read, one of its snapshot.stores; its primary when not set. | |
wow.aggregates.[<context>.<aggregate>].routing | CommandRouting | auto | How the commands of the type are routed, over wow.routing (CommandRouting): topic writes them to its context's command topic, accepted once the broker acknowledged them, which needs a topic transport; partitioned and local are the node's, so they name the routing wow.routing gives it. |
wow.aggregates.[<context>.<aggregate>].snapshot.primary | String | The one of them the type's write side and state reads read; the first when not set. | |
wow.aggregates.[<context>.<aggregate>].snapshot.stores | List<String> | The stores of wow.stores the type's snapshots are written to, over wow.snapshot.stores. | |
wow.aggregates.[<context>.<aggregate>].tenant | String | The tenant every aggregate of the type is in, whoever the caller is. |
wow.callers.<service>
What each service that calls this one may call and read on the internal port, by the name it states (Wow-Service, its spring.application.name): optional lists that catch a misconfiguration. The internal port is reachable by the platform's own pods alone; a service that names itself is taken on that network's word.
| Key | Type | Default | Description |
|---|---|---|---|
wow.callers.<service>.commands | List<String> | The commands the service may call, names or patterns; the domain commands alone when empty. | |
wow.callers.<service>.reads | List<String> | The models the service may read on the internal port's read routes, patterns too; every one when empty. |
wow.clickhouse
The settings of ClickHouse: the connection the Sink and the dataset backend share, the Sink's and the datasets'.
| Key | Type | Default | Description |
|---|---|---|---|
wow.clickhouse.database | String | default | The database of the Sink's tables and of a dataset whose table names none. |
wow.clickhouse.ddl | Ddl | How the Sink manages its tables: auto creates what is missing, _state's computed columns included, then validates; validate creates nothing and refuses a table that is missing, is not of the Sink's format (its comment's wow-sink-format:1), has other columns or lacks a computed column; none creates and checks nothing. wow.ddl when not set. | |
wow.clickhouse.endpoint | String | The ClickHouse server's HTTP endpoint, such as http://localhost:8123: the Sink and the datasets open a client of it and its credentials, unless the application has a ClickHouse Client bean, which they use. | |
wow.clickhouse.password | String | "" | The password to sign in with. |
wow.clickhouse.query.enabled | Boolean | true | Whether the datasets are served over ClickHouse when the endpoint is set or the application has a ClickHouse client. |
wow.clickhouse.query.metadata-ttl | Duration | PT1M | How long a dataset table's columns and engine are reused before system.columns is read again. |
wow.clickhouse.query.settings | Map<String,String> | Server settings every dataset query runs under, such as max_memory_usage; the execution time comes from each query's budget (wow.query.budgets.http.timeout), not from here. | |
wow.clickhouse.sink.batch-size | Integer | 1000 | The most records one insert carries. |
wow.clickhouse.sink.deduplication-window | Integer | 1000 | How many recent inserts each table remembers to drop a retried one: the non_replicated_deduplication_window of the tables auto creates. |
wow.clickhouse.sink.enabled | Boolean | false | Whether the Manifest's published streams are written to ClickHouse; off unless set, so a ClickHouse client or endpoint alone writes nothing. |
wow.clickhouse.username | String | default | The user name to sign in with. |
wow.cluster
How the nodes of a service share the partitions of each context's log, and forward commands to their owners.
| Key | Type | Default | Description |
|---|---|---|---|
wow.cluster.drain-timeout | Duration | PT10S | How long a hand-off of a partition waits for its commands in flight before it moves on. |
wow.cluster.forward-timeout | Duration | How long a forward waits for the owner's reply, capped by the command's own deadline: wow.wait.default-timeout when not set, so a node whose waits are longer forwards as long. A forward the owner received and did not answer by then is reported unknown (wow.command.unknown), not run here, so the command never runs twice and a retry with the same request id is safe. | |
wow.cluster.heartbeat-interval | Duration | PT3S | How often a node sends its heartbeat; less than half of member-ttl, so one late heartbeat is harmless. |
wow.cluster.lease-parallelism | Integer | 16 | The most lease acquisitions a node runs at a time. |
wow.cluster.lease-ttl | Duration | PT10S | How long a partition stays with a node that stopped renewing its lease. |
wow.cluster.max-in-flight-per-node | Integer | 1024 | The forwards one node may have outstanding with another; one more runs here instead. |
wow.cluster.member-ttl | Duration | PT10S | How long a node stays a member of the cluster after its last heartbeat. |
wow.cluster.reconcile-interval | Duration | PT1S | How often a node compares the partitions it holds with those it should hold; a change of the members it notices reconciles at once. |
wow.cluster.reconcile-timeout | Duration | PT1M | How long one reconcile may run before the node takes itself as stuck and leaves the members until it ends, so the other nodes take the partitions it cannot run; longer than drain-timeout. One still running after wow.health.liveness.stall-timeout fails the node's liveness. |
wow.cluster.renew-interval | Duration | PT3S | How often a node renews its leases; less than half of lease-ttl, or every lease is lost between rounds. |
wow.cluster.route-refresh-interval | Duration | PT1S | How often the route table is read from the leases and members; a failed forward refreshes it at once. |
wow.contexts
The bounded contexts the node serves.
| Key | Type | Default | Description |
|---|---|---|---|
wow.contexts.exclude | Set<String> | The contexts the node does not serve, taken out of those include gives. | |
wow.contexts.include | Set<String> | The contexts the node serves; every context on the class path when empty. |
wow.cosec
The keys wow-cosec reads (wow.cosec.*), bound here so they are checked and documented as the others are. Experimental in 10.0 with wow-cosec, which follows CoSec 8's pre-release: they may change within 10.x.
| Key | Type | Default | Description |
|---|---|---|---|
wow.cosec.mode | CoSecMode | How CoSec runs in this service, as defaults its own cosec.* keys override (CoSecModeEnvironmentPostProcessor): gateway, behind a CoSec gateway (cosec.pipeline.mode=gateway: the caller read from the CoSec-Identity the gateway verified, with its app and space, and no token verified here); disabled, CoSec off (cosec.enabled=false). Unset, CoSec's own defaults: CoSec decides the requests itself, the Manifest's routes its route map. |
wow.cosec.authorizer
CoSec's authorization of the commands.
| Key | Type | Default | Description |
|---|---|---|---|
wow.cosec.authorizer.enabled | Boolean | false | Whether CoSec authorizes every command and service route call of a request as its caller (CoSecCommandAuthorizer, <context>:<command> on <aggregate>/<id>), not only the public routes, where CoSec decides itself. A request-less command gets no objection. Off, and without a CommandAuthorizer of the application's, the command gateway allows every command that passed its route: behind a CoSec gateway, authorization is the gateway's. |
wow.cosec.cross-scope
The callers that may act across scopes: by CoSec role or policy.
| Key | Type | Default | Description |
|---|---|---|---|
wow.cosec.cross-scope.policies | Set<String> | The CoSec policies of these callers. | |
wow.cosec.cross-scope.roles | Set<String> | The CoSec roles of these callers. |
wow.cosec.tenant-level
The tenant-level callers, who read and write every aggregate of their tenant.
| Key | Type | Default | Description |
|---|---|---|---|
wow.cosec.tenant-level.policies | Set<String> | The CoSec policies of these callers. | |
wow.cosec.tenant-level.roles | Set<String> | The CoSec roles of these callers. |
wow.elasticsearch
The settings of every elasticsearch store; a store's own options override them.
| Key | Type | Default | Description |
|---|---|---|---|
wow.elasticsearch.index-prefix | String | A prefix of every index name of the store (<prefix>wow_snapshot_<context>__<aggregate>), for a cluster several services or environments share; none when not set. | |
wow.elasticsearch.refresh | ElasticsearchRefresh | wait-for | When a write becomes visible to searches: wait-for (the default: a snapshot is queryable once its write returns), immediate (an immediate refresh, for tests) or none (within the index's refresh interval). |
wow.elasticsearch.reindex-requests-per-second | Integer | 1000 | How many documents a second the store indexes again when its queries map a field an index lacks, so that the documents written before it are found by it too; a search of the field misses them until the rewrite ends. 1000 by default (a million documents in about 17 minutes); -1 for no limit. |
wow.executor
How the node executes commands.
| Key | Type | Default | Description |
|---|---|---|---|
wow.executor.lane-capacity | Integer | 1024 | The commands one aggregate may have waiting in the executor. |
wow.executor.max-batch | Integer | 32 | The most of one aggregate's queued commands the executor decides in turn and commits with one append; 1 runs each alone. It never waits to fill a batch. |
wow.executor.max-in-flight | Integer | 4096 | The commands the node may have in flight, all contexts together: beyond it a command is refused as wow.command.busy (429, with Retry-After) instead of queued. |
wow.health
The node's health and its probes, when the application has Spring Boot Actuator: wow.health.*.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.enabled | Boolean | true | Whether the host contributes the node's health to Actuator and its probe groups. |
wow.health.executor
The node's command executors.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.executor.saturation | Double | 0.9 | The share of wow.executor.max-in-flight in flight at which the executor is degraded. |
wow.health.liveness
Whether the node is stuck, so a restart helps; a storage outage never fails it.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.liveness.stall-timeout | Duration | PT3M | How long the node's dispatcher or its backends' driver threads may not tick, one reconcile not end, or commands in flight not finish while every log answers, before the node is not live; longer than wow.cluster.reconcile-timeout, so a stuck node leaves the members before it restarts. |
wow.health.ownership
The node's share of each lease group's partitions.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.ownership.handover-grace | Duration | PT1M | How long the owned partitions may differ from the node's share (a hand-over) before the group is degraded, and down (the node not ready) when it owns none of a share that is not empty. |
wow.health.stores
The node's event logs, as its own calls and a probe of their heads see them.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.stores.down-after | Duration | PT15S | How long a log must keep failing, with no success since, before it is down and the node not ready: a failed call or probe, or a probe that timed out (after this long, at least a second); a probe still under way is no failure. 0s is down at the first failure. |
wow.health.stores.window | Duration | PT1M | A log with a failure this recent is degraded. |
wow.health.subscriptions
The node's subscriptions, never a reason to take it out of service.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.subscriptions.lag-degraded-at | Long | 10000 | The entries a subscription may be behind the log's head before it is degraded. |
wow.health.subscriptions.parked-degraded-at | Integer | 100 | The parked entries of a subscription, counted up to this, at which it is degraded (as when they grow). |
wow.health.topics
The topics of other contexts the node reads.
| Key | Type | Default | Description |
|---|---|---|---|
wow.health.topics.required | Boolean | true | Whether a topic the node is still joining makes it not ready; degraded only when false. |
wow.http
The HTTP edge: its routes and its error answers.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.errors | Map<String,Error> | The HTTP status of an error code, by code (bracketed in a property name: wow.http.errors.[a.b].status). | |
wow.http.request-facts | Set<String> | The request headers copied into a command's headers, beside the standard request facts the edge records: app_id, the application the caller resolver authenticated, and on the public port user_agent and remote_ip; none of the three can be listed, and each fact is cut to 512 characters. remote_ip is the server's remote address, which the host takes from the gateway's X-Forwarded-For (server.forward-headers-strategy is framework unless the application sets it, none included). |
wow.http.client-facts
The client address and User-Agent of each command, recorded as request facts.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.client-facts.enabled | Boolean | true | Whether the public port records each command's client address and User-Agent as the request facts remote_ip and user_agent, for audit. They are personal data, and written into the event stream, which is never deleted: once recorded, they cannot be erased. On by default; off records neither. |
wow.http.errors.[<code>]
The HTTP status of an error code, by code (bracketed in a property name: wow.http.errors.[a.b].status).
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.errors.[<code>].status | Integer | The HTTP status the code is answered with, 400 to 599: required, an entry without it refuses the start. |
wow.http.global-errors
The problem+json answers of what fails on the application's own routes.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.global-errors.enabled | Boolean | true | Whether what fails on the application's own routes is answered as the framework routes' problem+json, so every route answers errors alike: on by default; off leaves those errors to Spring's error handling. |
wow.http.manifest
The service's Manifest route.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.manifest.enabled | Boolean | true | Serves GET /wow/manifest. |
wow.http.openapi
The OpenAPI document of the routes.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.openapi.enabled | Boolean | true | Serves GET /wow/openapi, the OpenAPI 3.1 document of the routes. |
wow.http.openapi.springdoc
The springdoc bridge, when the application has springdoc.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.openapi.springdoc.enabled | Boolean | true | Merges the Wow routes into springdoc's documents. |
wow.http.openapi.springdoc.group | String | wow | The springdoc group of the Wow routes alone: /v3/api-docs/<group>. |
wow.http.ops
The operator's routes of the node: its parked entries and its subscriptions.
| Key | Type | Default | Description |
|---|---|---|---|
wow.http.ops.enabled | Boolean | false | Serves the operator's routes on the public port: the parked entries under /wow/ops/parked, and the read of the node's subscriptions, GET /wow/ops/subscriptions. |
wow.internal
The internal port: the cluster channel, the wait signals and the calls of other services.
| Key | Type | Default | Description |
|---|---|---|---|
wow.internal.connect-timeout | Duration | PT1S | How long a peer has to accept a connection of the cluster channel or the signal sender. |
wow.internal.host | String | The address the internal server binds, 0.0.0.0 for every interface; when not set, the host of the member address the node advertises (wow.node.address, else this host's address). | |
wow.internal.port | Integer | 9090 | The port of the internal server, which carries the cluster channel and the wait signals; 0 for one the system chooses, which the node advertises once the server is bound. |
wow.internal.signal-queue-capacity | Integer | 1024 | The wait signals queued per origin node before they are dropped, so a slow or unreachable node cannot hold the sender's memory. |
wow.kafka
The settings of the kafka topic transport.
| Key | Type | Default | Description |
|---|---|---|---|
wow.kafka.bootstrap-servers | String | The Kafka brokers, host:port separated by commas; the transport, the transport sink and the topic-sourced subscriptions are wired only when it is set. Unset, spring.kafka.bootstrap-servers when the application sets that. | |
wow.kafka.command-intake.enabled | Boolean | false | Whether each context the node hosts executes the commands other contexts send to its command topic, wow.<context>.commands. A context with an aggregate type routed through topics takes them whatever this says. |
wow.kafka.ddl | Ddl | How the node manages the topics its contexts own at its start: auto creates the missing ones, then validates them; validate creates none and refuses the start when one is missing, or when the command topic of a context that takes commands from it has another number of partitions than that context's log (a peer's command topic is only checked to exist); none creates and checks nothing. wow.ddl when not set. | |
wow.kafka.offset-gap | OffsetGapPolicy | fail | What a read of another context's topic does when its partition no longer holds the offset to read from (the retention deleted it, or the topic was created again): fail fails the read, so the subscription stays where it is; earliest reads on from the earliest offset retained, and the skipped range is lost to that subscription. Either way the gap is logged as an error and counted (wow.subscription.offset.gaps). |
wow.kafka.poll-timeout | Duration | PT0.200S | The longest a consumer's poll waits; a read that is cancelled, and a partition that joins or leaves a topic's shared consumer, take effect within it. |
wow.kafka.properties | Map<String,String> | Passed to every producer and consumer as they are (security.protocol, client.id, linger.ms,...), except the settings the transport's guarantees rest on. | |
wow.kafka.topics.configs | Map<String,String> | Other topic configs auto creates a topic with, such as retention.ms. | |
wow.kafka.topics.min-insync-replicas | Integer | The min.insync.replicas auto creates a topic with; the broker's default when not set. | |
wow.kafka.topics.partition-refresh | Duration | PT30S | How often the node looks for partitions added to the topics it reads; new partitions are read within about twice this. |
wow.kafka.topics.prefix | String | "" | Put before every topic name, such as staging. for staging.wow.shop.order.state; none by default, so the topics are the Manifest's. The sinks write and the subscriptions read under it. |
wow.kafka.topics.replication-factor | Integer | The replication factor auto creates a topic with; the broker's default when not set. A command accepted on a command topic is durable only when it and the minimum in-sync replicas are both at least 2. |
wow.log
The aggregates' logs: their partitions, their store, and how their appends and tails run.
| Key | Type | Default | Description |
|---|---|---|---|
wow.log.max-poll-interval | Duration | PT1S | The longest a tail waits between polls that find nothing: an idle tail backs off up to it. |
wow.log.partitions | Integer | 64 | The partitions of each context's log: fixed once the log holds entries, a power of two that divides 4096, refused at start otherwise. |
wow.log.poll-interval | Duration | PT0.05S | How often the tail of a PostgreSQL or MongoDB log polls while it finds entries. |
wow.log.store | String | The store of every aggregate's log that wow.aggregates.[<context>.<aggregate>].log.store does not name: one of wow.stores, the only one when not set. |
wow.memory
The in-memory provider's settings: the topics it keeps in the JVM.
| Key | Type | Default | Description |
|---|---|---|---|
wow.memory.topic-retention | Integer | 1000 | The messages each partition of the topics in the JVM keeps (wow.transport memory, or auto in development without a transport), at least one: past it, a partition drops its oldest, as a broker's retention does, and a subscription behind them reads on from the oldest kept, an offset gap. The topics stay bounded however long the node runs. |
wow.mongo
The settings of every mongo store; a store's own options override them.
| Key | Type | Default | Description |
|---|---|---|---|
wow.mongo.append-timeout | Duration | PT5S | How long an append's insert may take: below the default wait timeout, so a command appending during an outage is answered before its wait ends. |
wow.mongo.database | String | wow | The database of the log and the stores on MongoDB: unset, the one spring.mongodb.uri names, else wow. |
wow.mongo.operation-timeout | Duration | PT30S | How long each call of a MongoDB store may take besides appends (append-timeout) and the schema's commands (5 minutes): a reply lost on the way fails the call instead of blocking it forever. |
wow.mongo.query-read-preference | String | The read preference of the snapshot and events queries of a MongoDB store (secondaryPreferred, say), so a free filter scans a secondary rather than the primary the log appends to; the primary when not set. A snapshot read from a secondary may be behind the one a command's wait waited for. | |
wow.mongo.sharding | MongoSharding | auto | Whether a store on a sharded cluster shards its log, snapshot, timer and reservation collections when it creates them: auto when connected to a mongos with ddl auto, none for a cluster its operators shard. |
wow.node
This node's identity among the nodes of the service, and where they reach it.
| Key | Type | Default | Description |
|---|---|---|---|
wow.node.address | String | The host:port of this node's internal port that the other nodes reach, an IPv6 host in brackets ([::1]:9191; a bare one fails the start), as the node writes it when not set; the port binds at wow.internal.host. | |
wow.node.id | String | This node's id among the nodes of the service; a new one each start when not set. | |
wow.node.max-parked | Integer | 10000 | How many parked entries of one subscription a sample counts at most: a count past it reads as the cap, so a flood of parked entries costs one bounded read per sample. The health's parked-degraded-at is at most it. |
wow.node.sample-interval | Duration | PT10S | How often the node samples what is read rather than heard: for its health, the logs' heads, the subscriptions' lag and parked entries, and a probe of the stores it has not called since; for its gauges (wow-observability), the parked entries, the subscriptions' positions and a rebuild's progress. |
wow.node.standby | Boolean | false | Whether the node starts on standby: through the dual-run window of a migration's cut-over it serves reads of what migrate-data imports, refuses every command (the error wow.node.standby, 503), and handles no subscription, retries no parked entry and runs no job, until its operator activates it on the internal port (POST /wow/node/activate from a node of its service, naming who activates it). A subscription that starts at the end of its stream starts where the stream ends at the activation. |
wow.observability
Observability's configuration, wow.observability.*, read when wow-observability is on the classpath (ObservabilityAutoConfiguration).
| Key | Type | Default | Description |
|---|---|---|---|
wow.observability.enabled | Boolean | true | Whether the node is traced and measured. |
wow.ops.publish
Publishing the failure ledger to the ops context.
| Key | Type | Default | Description |
|---|---|---|---|
wow.ops.publish.context | String | ops | The ops context the ledger is published to. |
wow.ops.publish.enabled | Switch | auto | Whether the node publishes its failure ledger to the ops context: auto (the default) while the ops context's command topic exists on the node's transport, which the ops service creates once it is deployed, checked at start and every wow.kafka.topics.partition-refresh, and not at all without a transport; true always, which needs a transport; false never. |
wow.ops.publish.interval | Duration | PT30S | How often the node scans its ledger and publishes it; an entry is also published at once when it parks. |
wow.ops.webhook
The webhook told when an entry parks or spends its retries.
| Key | Type | Default | Description |
|---|---|---|---|
wow.ops.webhook.events | Set<Kind> | parked, exhausted | The events posted: parked, an entry parked, and exhausted, an entry spent its retries; both by default. |
wow.ops.webhook.format | Format | generic | The body's format: generic, Wow's JSON, or wecom, a WeCom robot's Markdown message. |
wow.ops.webhook.headers | Map<String,String> | The headers added to each post, such as a token the receiver checks. | |
wow.ops.webhook.timeout | Duration | PT5S | How long one post may take. |
wow.ops.webhook.url | java.net.URI | The URL the webhook posts to; none is posted when not set. |
wow.peer
How the node calls its peers, the services of the other contexts it calls over HTTP: wow.peer.*.
| Key | Type | Default | Description |
|---|---|---|---|
wow.peer.connect-timeout | Duration | PT2S | How long a request may take to connect. |
wow.peer.discovery | String | dns | How the node finds the internal ports of a peer's nodes: dns (the default) looks up the DNS SRV records wow.peer.dns.name-template names after the peer's service, as its contract on the class path or its Manifest names it; static takes wow.peers.<context>.url alone; spring-cloud, with wow-spring-cloud on the class path, reads the instances a Spring Cloud service registry has of the service; another value names a community provider's discovery. Each is configured under wow.peer.<type> by the options it declares. A peer's url wins over any discovery. |
wow.peer.forwarded-headers | List<String> | Authorization | The headers of the public request it serves that a user-mode request forwards. |
wow.peer.mode | PeerMode | service | The mode of a peer that names none: service, through its internal port as this service, or user, through its public routes with the end user's credential. |
wow.peer.timeout | Duration | PT30S | How long a request may take to be answered, a command's longer wait aside; wow.peers.<context>.timeout overrides it for one peer. |
wow.peer.dns
The settings of the dns peer discovery.
| Key | Type | Default | Description |
|---|---|---|---|
wow.peer.dns.name-template | String | _internal._tcp.{service}-cluster.{namespace}.svc | The SRV name of a peer service's internal port, {service} its name (spring.application.name) and {namespace} its namespace: by default the headless Service <service>-cluster in that namespace and its port named internal, the records Kubernetes publishes for them. A name without a trailing dot is tried as a resolver tries it: under each search domain of the node's /etc/resolv.conf and as given, as given first when it has at least the resolver's ndots dots; the records' targets are the nodes and their ports. |
wow.peer.dns.namespace | String | The node's own namespace, the {namespace} of each peer that namespaces does not place elsewhere: on Kubernetes, the pod's metadata.namespace (the downward API), as the Wow chart sets it. Unset, the namespace of the pod's service account, from /var/run/secrets/kubernetes.io/serviceaccount/namespace; a call that needs a namespace when neither gives one fails, naming this key. | |
wow.peer.dns.namespaces | Map<String,String> | The namespaces of the peer services outside the node's own, by service name (wow.peer.dns.namespaces.<service>): the {namespace} of their SRV names. Set them in a YAML file or SPRING_APPLICATION_JSON: an environment variable loses the dashes of a service's name. |
wow.peer.retry
How a typed client's request that a peer answered with a problem a retry may get past is sent again; a saga's call is not retried here, its subscription's retry budget is the one that counts.
| Key | Type | Default | Description |
|---|---|---|---|
wow.peer.retry.initial-backoff | Duration | PT0.2S | The wait before the first retry when the peer gives no Retry-After; it doubles at each next one. |
wow.peer.retry.max-attempts | Integer | 5 | The most attempts of a request in all; 1 never retries. |
wow.peer.retry.max-retry-after | Duration | PT5S | The longest Retry-After of a peer that is waited out; a peer that asks for longer is not retried. |
wow.peers.<context>
The peer contexts called over HTTP, by context (wow.peers.<context>.*): a saga's synchronous calls to that context and the typed clients of it go to its service, at its url when one is set, else where wow.peer.discovery finds the service its contract names (DNS by default). A node whose saga calls a context it cannot reach does not start.
| Key | Type | Default | Description |
|---|---|---|---|
wow.peers.<context>.contract | Contract | jar | Where the peer's contract comes from: jar, its api jar, or manifest, its Manifest alone. |
wow.peers.<context>.mode | PeerMode | The mode the peer is called in: service or user, over wow.peer.mode. | |
wow.peers.<context>.public-url | java.net.URI | The base URL of the peer's public routes (user mode). | |
wow.peers.<context>.timeout | Duration | How long a call to the peer may take, over wow.peer.timeout. | |
wow.peers.<context>.url | java.net.URI | The base URL of the peer's internal port (service mode), never its public port; found when not set. |
wow.postgres
The settings of every postgres store; a store's own options override them.
| Key | Type | Default | Description |
|---|---|---|---|
wow.postgres.operation-timeout | Duration | PT30S | How long each call of a PostgreSQL store may wait for a reply besides the schema's statements (5 minutes) and the queries (their own statement_timeout): a reply lost on the way fails the call, and its connection, instead of blocking it forever. |
wow.query
The query plane's configuration, wow.query.*, read by QueryAutoConfiguration: the query routes and gateways, the budgets they run under, who may query what, and how many queries each store runs at once.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.allow-cross-tenant | Boolean | false | Whether a caller that may act across scopes may query across tenants on the query routes (Wow-Scope: tenant=* or tenant=("t1" "t2")); 403 wow.auth.forbidden while not. A type whose tenant is fixed is still read in that tenant alone, and each such query is logged at INFO (me.ahoo.wow.query.CrossTenantAudit). The commands and the state reads never cross tenants. |
wow.query.enabled | Boolean | true | Whether the query routes and gateways are wired at all. |
wow.query.max-concurrent | Integer | How many snapshot and events queries each store runs at once, whichever entry asks; beyond it a query waits, then is wow.query.busy (429, with Retry-After). Not set, each store derives one from the pool it reports: a quarter of a pool its queries share with the appends, at least 2 (MongoDB's, and PostgreSQL's or Elasticsearch's own pool), or the whole of a pool of their own (PostgreSQL's query-data-source, Elasticsearch's query-client); 16 for a store that reports none. That bound then adapts to the store's write pressure (adaptive). 0 for no bound; wow.stores.<name>.query.max-concurrent overrides it for one store. | |
wow.query.max-queued | Integer | How many queries may wait for a permit before the next one is refused at once; 4 per permit when not set. wow.stores.<name>.query.max-queued overrides it for one store. | |
wow.query.max-wait | Duration | PT0.2S | How long a query beyond max-concurrent waits in a FIFO queue for a permit before it is refused; wow.stores.<name>.query.max-wait overrides it for one store. |
wow.query.require-authenticated-scope | Boolean | false | Whether an HTTP query of a built-in model is refused unless the caller's authenticated scope pins its tenant; off, a declared scope, such as a tenant header, is trusted. |
wow.query.require-explicit-entry | Boolean | false | Whether a query must say whether it comes over HTTP or in process; off, a query that does not say is taken as in-process. |
wow.query.unbounded-timeout | Duration | PT30S | The timeout of a trusted in-process query that dropped its budget (NodeQueryApi.trusted().unbounded()); 0 for none. |
wow.query.adaptive
How the bound of a store adapts to its write pressure, when neither wow.query.max-concurrent nor wow.stores.<name>.query.max-concurrent fixes it.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.adaptive.ceiling | Integer | The highest bound the adaptation raises up to; not set, the provider's: PostgreSQL half a pool the appends share, or all of a query-data-source's. | |
wow.query.adaptive.floor | Integer | 1 | The lowest bound the adaptation halves down to. |
wow.query.budgets.http
The budget every query route runs under; a limit of 0 is off.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.budgets.http.allow-exact-count | Boolean | false | Whether a paged query may ask for an exact total, beyond count-limit. |
wow.query.budgets.http.allow-expensive-operators | Boolean | true | Whether a query may use the expensive operators, those an index serves poorly, such as a negation or a suffix match; off also refuses a counting query without a filter. |
wow.query.budgets.http.count-limit | Integer | 10000 | The default and the largest limit of a count, and the bound of a paged query's total. |
wow.query.budgets.http.default-list-size | Integer | 100 | The limit of a list that names none, at most max-list-size. |
wow.query.budgets.http.max-filter-nodes | Integer | 128 | The most nodes a query's filter may have, the caller's scope included. |
wow.query.budgets.http.max-filter-values | Integer | 1000 | The most values one node of a query's filter may list, such as those of an in. |
wow.query.budgets.http.max-list-size | Integer | 1000 | The most results a list or an aggregation may ask for. |
wow.query.budgets.http.max-page-size | Integer | 100 | The largest page of a paged or cursor query. |
wow.query.budgets.http.max-page-window | Long | 10000 | How deep a paged query may go: the most of its page index times its page size. |
wow.query.budgets.http.max-residual-groups | Integer | 10000 | The most groups an aggregation may read when the storage cannot run its HAVING or metric sort itself and the groups are computed in the node. |
wow.query.budgets.http.timeout | Duration | PT30S | The execution timeout of every query of the entry; 0 runs without one. |
wow.query.budgets.http.unindexed-sort-expensive | Boolean | false | Whether a sort the storage runs without an index counts as an expensive operator, so that allow-expensive-operators: false refuses it too. |
wow.query.budgets.in-process
The budget of the in-process queries, the typed me.ahoo.wow.api.read.QueryApi's, trusted code's too.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.budgets.in-process.allow-exact-count | Boolean | false | Whether a paged query may ask for an exact total, beyond count-limit. |
wow.query.budgets.in-process.allow-expensive-operators | Boolean | true | Whether a query may use the expensive operators, those an index serves poorly, such as a negation or a suffix match; off also refuses a counting query without a filter. |
wow.query.budgets.in-process.count-limit | Integer | 10000 | The default and the largest limit of a count, and the bound of a paged query's total. |
wow.query.budgets.in-process.default-list-size | Integer | 100 | The limit of a list that names none, at most max-list-size. |
wow.query.budgets.in-process.max-filter-nodes | Integer | 128 | The most nodes a query's filter may have, the caller's scope included. |
wow.query.budgets.in-process.max-filter-values | Integer | 1000 | The most values one node of a query's filter may list, such as those of an in. |
wow.query.budgets.in-process.max-list-size | Integer | 1000 | The most results a list or an aggregation may ask for. |
wow.query.budgets.in-process.max-page-size | Integer | 100 | The largest page of a paged or cursor query. |
wow.query.budgets.in-process.max-page-window | Long | 10000 | How deep a paged query may go: the most of its page index times its page size. |
wow.query.budgets.in-process.max-residual-groups | Integer | 10000 | The most groups an aggregation may read when the storage cannot run its HAVING or metric sort itself and the groups are computed in the node. |
wow.query.budgets.in-process.timeout | Duration | PT30S | The execution timeout of every query of the entry; 0 runs without one. |
wow.query.budgets.in-process.unindexed-sort-expensive | Boolean | false | Whether a sort the storage runs without an index counts as an expensive operator, so that allow-expensive-operators: false refuses it too. |
wow.query.count-cache
The cache of the snapshot counts.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.count-cache.enabled | Boolean | true | Whether the snapshot counts are cached. |
wow.query.count-cache.max-entries | Integer | 10000 | The most counts the cache holds. |
wow.query.count-cache.paged-totals | Boolean | false | Whether the totals of paged queries come from the cache too; off, each total is counted with its page, so that it agrees with its rows. |
wow.query.count-cache.ttl | Duration | PT30S | How long a count is cached at most; another node's write can make a cached count lag the rows by up to it. |
wow.query.count-cache.events
The cache of the events counts.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.count-cache.events.enabled | Boolean | false | Whether the events' counts are cached too; the log runs ahead of the snapshot checkpoint, so a cached events count may lag the streams for up to ttl. |
wow.query.dataset
The datasets, and the bound of their queries.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.dataset.config-directory | String | config | The working directory whose wow/dataset/ holds dataset files, {context}.{dataset}.json; each takes precedence over the class path's META-INF/wow/dataset/ file of the same dataset. |
wow.query.dataset.max-concurrent | Integer | 8 | How many dataset queries the node runs at once, so analytics queries do not overload a warehouse the Sink writes to; 0 for no bound. The bound is fixed: the warehouse's writes give the node no pressure to adapt to. |
wow.query.dataset.max-queued | Integer | How many dataset queries may wait for a permit before the next one is refused; wow.query.max-queued when not set. | |
wow.query.dataset.max-wait | Duration | How long a dataset query beyond max-concurrent waits for a permit; wow.query.max-wait when not set. |
wow.query.events
The events model, served from each aggregate's log store, or the store its wow.aggregates.[<context>.<aggregate>].query.events.store names.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.events.unpinned | UnpinnedEvents | allow | Whether an events query that names no aggregateId runs: allow or refuse; refused, it is wow.query.invalid. wow.stores.<name>.query.events.unpinned and wow.aggregates.[<context>.<aggregate>].query.events.unpinned override it. |
wow.query.memory
Queries of the snapshots and logs kept in memory.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.memory.enabled | Boolean | true | Whether the snapshots on a store in memory are queried, from the in-memory query backend, and the events of a log in memory scanned: for local runs, demos and tests, not for production. On by default wherever a store is in memory (wow.backend: memory, or auto choosing it); false turns them off there. |
wow.query.sensitivity
What the queries may do with sensitive fields.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.sensitivity.display-comparable | Boolean | true | Whether filters and sorts may compare a field whose sensitivity is DISPLAY. |
wow.query.state
The reads of an aggregate's state at a version or a point in time.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.state.max-replay | Integer | 10000 | The most commits a state read at a version or an instant, or a trace, replays from the aggregate's snapshot, or from version 1: the snapshot holds only the latest state, so an older one is replayed from the first version. A state further away is 400 wow.query.invalid (replay-too-long). It keeps one read from holding the node; raise it where states that far back are read. An aggregate's events are not bounded by it: the events query reads them page by page. |
wow.query.state.min-version-wait | Duration | PT2S | How long a read of ?minVersion= waits for the aggregate to reach that version; past it the read is 409 wow.query.min-version-not-reached with the current version. |
wow.query.stream
How a list streamed as server-sent events reads its chunks and how long it runs.
| Key | Type | Default | Description |
|---|---|---|---|
wow.query.stream.chunk-size | Integer | 500 | The records of one keyset chunk; each chunk takes a query permit. |
wow.query.stream.max-hold | Duration | PT30S | How long a stream runs before it ends with {"reason":"hold-expired","resumable":true}, for the client to resume it with Last-Event-ID; 0 for no bound. |
wow.schedules.<name>
Per @OnSchedule job, by its name: wow.schedules.<job>.* holds all of the job's settings, its rule and the retries of the subscriptions that run it. A job no handler of the node runs fails its start, and so does a job's subscription configured under wow.subscriptions.
| Key | Type | Default | Description |
|---|---|---|---|
wow.schedules.<name>.cron | String | The job's cron, six fields, over its annotation's. | |
wow.schedules.<name>.enabled | Boolean | true | Whether a SYSTEM or a SHARDED job's instances run; false disables them at startup. |
wow.schedules.<name>.misfire | Misfire | What a firing missed while no node ran it does, over its annotation's. | |
wow.schedules.<name>.parked.claim-ttl | Duration | How long a retry's claim on the entry holds, over wow.subscription.parked's. | |
wow.schedules.<name>.parked.initial-backoff | Duration | The wait before the first automatic retry, over wow.subscription.parked's. | |
wow.schedules.<name>.parked.max-retries | Integer | How many automatic retries a parked entry of the subscription gets, over wow.subscription.parked's. | |
wow.schedules.<name>.retry.initial-backoff | Duration | The wait after the first failure. | |
wow.schedules.<name>.retry.max-attempts | Integer | The most attempts of the handler in all, before its aggregate parks. | |
wow.schedules.<name>.retry.max-backoff | Duration | The longest wait between two attempts. | |
wow.schedules.<name>.retry.multiplier | Double | How many times longer each wait is than the one before; at least 1. | |
wow.schedules.<name>.retry.timeout | Duration | How long one attempt may run before it is cancelled and counts as failed. | |
wow.schedules.<name>.zone | String | The time zone its cron is read in, over its annotation's. |
wow.shared-states
The bounds of each context's shared states: wow.shared-states.*.
| Key | Type | Default | Description |
|---|---|---|---|
wow.shared-states.capacity | Integer | 4096 | The most shared states a context keeps. |
wow.shared-states.max-age | Duration | PT1M | How long a shared state is kept at most. |
wow.shared-states.max-bytes | org.springframework.util.unit.DataSize | The most serialized state a context's views hold, counting two bytes a character (64MB). |
wow.snapshot
Where the snapshots are by default, and how the snapshot maintenance runs: wow.snapshot.*.
| Key | Type | Default | Description |
|---|---|---|---|
wow.snapshot.maintenance-interval | Duration | PT5S | How often the snapshot maintenance runs: state revision claims, in-place rebuilds and backfill checks. |
wow.snapshot.primary | String | The one of the stores the write side and the state reads read, and the snapshot queries unless an aggregate's wow.aggregates.[<context>.<aggregate>].query.snapshot.store names another; the first when not set. | |
wow.snapshot.stores | List<String> | The stores of wow.stores every aggregate's snapshots are written to, unless its wow.aggregates.[<context>.<aggregate>].snapshot.stores names others; wow.log.store alone when empty. The first one's built-in subscription is wow.snapshot, each other one's wow.snapshot:<store>. | |
wow.snapshot.write-batch | Integer | 256 | How many snapshots of a partition the snapshot subscriptions write together at most. |
wow.snapshot.rebuild
How an in-place rebuild rewrites the snapshots.
| Key | Type | Default | Description |
|---|---|---|---|
wow.snapshot.rebuild.max-pages | Integer | 10 | The most pages a rebuild rewrites in one maintenance run. |
wow.snapshot.rebuild.page-size | Integer | 100 | How many snapshots a rebuild rewrites per page. |
wow.state-cache
The cache of aggregate states each context keeps between commands.
| Key | Type | Default | Description |
|---|---|---|---|
wow.state-cache.capacity | Integer | The aggregate states kept per context between commands; 0 keeps none. Not set (the default), each context's cache is bounded by bytes instead: a tenth of the maximum heap (-Xmx), split between the node's contexts, each state weighed at an estimated 1 KB plus 12 bytes per recent request it holds (its rings grow with the requests the aggregate commits, up to recent-requests), and at least 4096 states with full rings. Most aggregates commit few requests, so the default holds several times as many of them as a count sized for full rings. A miss costs a snapshot and a tail read before the command is decided, so the cache should hold the aggregates written often: set a capacity when states are much larger than 1 KB (a capacity times the average state size should stay well within the heap). The counters wow.state_cache.lookups (hit, miss) and wow.state_cache.evictions show the fit. | |
wow.state-cache.recent-requests | Integer | 32 | The requests each cached aggregate keeps of those it committed last, derived from the log, so that most commands skip looking their request id up; 0 looks every request id up. |
wow.stores.<name>
The named store instances, by name: wow.stores.<name>.type and its settings. The aggregates whose logs are on one store form a log group, with its own partition sequences, checkpoints, parked entries and timers.
| Key | Type | Default | Description |
|---|---|---|---|
wow.stores.<name>.append-timeout | Duration | PT5S | On mongo: how long an append's insert may take: below the default wait timeout, so a command appending during an outage is answered before its wait ends. |
wow.stores.<name>.client | String | On elasticsearch: the name of the Rest5Client bean the store opens over; the only one when not set. On mongo: the name of the MongoClient bean the store opens over; the only one when not set. | |
wow.stores.<name>.data-source | String | On postgres: the name of the DataSource bean the store opens over; the only one when not set. | |
wow.stores.<name>.database | String | wow | On mongo: the database of the log and the stores on MongoDB: unset, the one spring.mongodb.uri names, else wow. |
wow.stores.<name>.ddl | Ddl | How this store manages the framework's schema, over wow.ddl. | |
wow.stores.<name>.index-prefix | String | On elasticsearch: a prefix of every index name of the store (<prefix>wow_snapshot_<context>__<aggregate>), for a cluster several services or environments share; none when not set. | |
wow.stores.<name>.operation-timeout | Duration | PT30S | On mongo: how long each call of a MongoDB store may take besides appends (append-timeout) and the schema's commands (5 minutes): a reply lost on the way fails the call instead of blocking it forever. On postgres: how long each call of a PostgreSQL store may wait for a reply besides the schema's statements (5 minutes) and the queries (their own statement_timeout): a reply lost on the way fails the call, and its connection, instead of blocking it forever. |
wow.stores.<name>.pool-gauge | String | On mongo: the name of the MongoPoolGauge bean the store's client was built with, when the application has several. | |
wow.stores.<name>.query-client | String | On elasticsearch: the name of the Rest5Client bean the store's queries use, so they draw on a connection pool of their own instead of the one the snapshot writes use; the store's client when not set. | |
wow.stores.<name>.query-data-source | String | On postgres: the name of the DataSource bean the store's snapshot and events queries read through, so they do not take the appends' connections; the store's data-source when not set. | |
wow.stores.<name>.query-read-preference | String | On mongo: the read preference of the snapshot and events queries of a MongoDB store (secondaryPreferred, say), so a free filter scans a secondary rather than the primary the log appends to; the primary when not set. A snapshot read from a secondary may be behind the one a command's wait waited for. | |
wow.stores.<name>.query.adaptive.ceiling | Integer | The most the store's adaptive query bound goes up to, over wow.query.adaptive.ceiling. | |
wow.stores.<name>.query.adaptive.floor | Integer | The least the store's adaptive query bound goes down to, over wow.query.adaptive.floor. | |
wow.stores.<name>.query.events.unpinned | UnpinnedEvents | Whether an events query that names no aggregate runs, over wow.query.events.unpinned. | |
wow.stores.<name>.query.max-concurrent | Integer | How many of the store's queries run at once, over wow.query.max-concurrent; 0 for no bound. | |
wow.stores.<name>.query.max-queued | Integer | How many queries beyond the bound wait for a permit, over wow.query.max-queued. | |
wow.stores.<name>.query.max-wait | Duration | How long a query beyond the bound waits for a permit, over wow.query.max-wait. | |
wow.stores.<name>.refresh | ElasticsearchRefresh | wait-for | On elasticsearch: when a write becomes visible to searches: wait-for (the default: a snapshot is queryable once its write returns), immediate (an immediate refresh, for tests) or none (within the index's refresh interval). |
wow.stores.<name>.reindex-requests-per-second | Integer | 1000 | On elasticsearch: how many documents a second the store indexes again when its queries map a field an index lacks, so that the documents written before it are found by it too; a search of the field misses them until the rewrite ends. 1000 by default (a million documents in about 17 minutes); -1 for no limit. |
wow.stores.<name>.sharding | MongoSharding | auto | On mongo: whether a store on a sharded cluster shards its log, snapshot, timer and reservation collections when it creates them: auto when connected to a mongos with ddl auto, none for a cluster its operators shard. |
wow.stores.<name>.type | String | The store's type: memory, postgres, mongo, elasticsearch or a community backend's. |
wow.subscription
How the node's subscriptions run, retry their failures and park what keeps failing.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.checkpoint-interval | Duration | PT1S | How often each subscription saves its checkpoint; a stop saves it too. |
wow.subscription.max-catch-ups | Integer | 2 | The partitions the node reads behind their head at once, all its subscriptions together; 0 for no bound. A partition whose subscriptions start behind the head (a history migrate-data imported, a long stop) waits for one, and the others stand at their checkpoints, so the node keeps its store for its commands while it catches up. More do not catch up sooner on one store, and raise the latency of the commands meanwhile. |
wow.subscription.max-in-flight | Integer | 1024 | The entries one subscription may hold in one partition between its checkpoint and the last entry it took: it bounds both memory and what a crash replays. |
wow.subscription.stop-timeout | Duration | PT10S | How long a stop waits for the handlers in flight before abandoning them; an abandoned entry is handled again after the restart. |
wow.subscription.backpressure
How a handler whose downstream pushes back is retried, and its partition throttled.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.backpressure.initial-backoff | Duration | PT0.1S | The wait before the first retry; it doubles at each next one. |
wow.subscription.backpressure.jitter | Double | 0.5 | The share of each wait, 0 to 1, by which it is shortened at random, so that retries do not come in step. |
wow.subscription.backpressure.max-attempts | Integer | 20 | The most attempts of an entry that meets backpressure before its aggregate parks. |
wow.subscription.backpressure.max-backoff | Duration | PT10S | The longest wait between two retries; a downstream's longer Retry-After still counts. |
wow.subscription.backpressure.min-concurrency | Integer | 1 | The fewest handlings a throttled partition runs at once. |
wow.subscription.parked
How the parked entries are retried automatically, over minutes and hours.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.parked.claim-ttl | Duration | PT2M | How long a retry's claim on the entry holds before another retry may start, such as on the partition's next owner: it cancels nothing. |
wow.subscription.parked.initial-backoff | Duration | PT3M | The wait before the first retry after the failure; each next one waits twice as long after the previous one started. |
wow.subscription.parked.max-retries | Integer | 10 | The most automatic retries of a parked entry; 0 turns them off. |
wow.subscription.parked.scan-interval | Duration | PT10S | How often each node scans its subscriptions' parked entries for retries that are due. |
wow.subscription.read-retry
How a failing read of the log, or write of a store, is retried: until the node stops, the backoff growing for error-after (5) attempts, after which each failure is logged as an error and retried at max-backoff, so a long outage does not stop the subscription.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.read-retry.error-after | Integer | 5 | The attempts after which each failure is logged as an error, and retried at max-backoff. |
wow.subscription.read-retry.initial-backoff | Duration | PT0.1S | The wait after the first failure. |
wow.subscription.read-retry.max-backoff | Duration | PT5S | The longest wait between two attempts. |
wow.subscription.read-retry.multiplier | Double | 2 | How many times longer each wait is than the one before; at least 1. |
wow.subscription.retry
How a failing handler is retried in process before its aggregate is parked; a subscription's wow.subscriptions.[<context>.<name>].retry.* and its handler's @Retry come before it.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.retry.initial-backoff | Duration | PT0.1S | The wait after the first failure. |
wow.subscription.retry.max-attempts | Integer | 5 | The most attempts of a call in all, the first included. |
wow.subscription.retry.max-backoff | Duration | PT5S | The longest wait between two attempts. |
wow.subscription.retry.multiplier | Double | 2 | How many times longer each wait is than the one before; at least 1. |
wow.subscription.retry.timeout | Duration | How long one attempt of a handler may run before it is cancelled and counts as failed; not set, an attempt runs as long as it takes. |
wow.subscription.systemic
When a partition pauses on a systemic failure, such as a database that is down, instead of parking every aggregate that fails.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscription.systemic.failing-aggregates | Integer | 3 | How many different aggregates failing within window pause the partition; 0 turns that off. |
wow.subscription.systemic.initial-backoff | Duration | PT1S | The wait before the first probe of a paused partition; it doubles at each next one. |
wow.subscription.systemic.max-backoff | Duration | PT30S | The longest wait between two probes of a paused partition. |
wow.subscription.systemic.window | Duration | PT10S | The window in which failing-aggregates failures pause the partition. |
wow.subscriptions.[<context>.<name>]
Per subscription, by its context and name, <context>.<name>, bracketed in a property name (wow.subscriptions.[shop.CartSaga.onOrderCreated], wow.subscriptions.[shop.wow.snapshot]): a name is unique within its context alone.
| Key | Type | Default | Description |
|---|---|---|---|
wow.subscriptions.[<context>.<name>].parked.claim-ttl | Duration | How long a retry's claim on the entry holds, over wow.subscription.parked's. | |
wow.subscriptions.[<context>.<name>].parked.initial-backoff | Duration | The wait before the first automatic retry, over wow.subscription.parked's. | |
wow.subscriptions.[<context>.<name>].parked.max-retries | Integer | How many automatic retries a parked entry of the subscription gets, over wow.subscription.parked's. | |
wow.subscriptions.[<context>.<name>].retry.initial-backoff | Duration | The wait after the first failure. | |
wow.subscriptions.[<context>.<name>].retry.max-attempts | Integer | The most attempts of the handler in all, before its aggregate parks. | |
wow.subscriptions.[<context>.<name>].retry.max-backoff | Duration | The longest wait between two attempts. | |
wow.subscriptions.[<context>.<name>].retry.multiplier | Double | How many times longer each wait is than the one before; at least 1. | |
wow.subscriptions.[<context>.<name>].retry.timeout | Duration | How long one attempt may run before it is cancelled and counts as failed. | |
wow.subscriptions.[<context>.<name>].start | String | Where the subscription starts in a partition it has no checkpoint in: beginning, end or an instant. |
wow.tenant
The tenants of the callers.
| Key | Type | Default | Description |
|---|---|---|---|
wow.tenant.default | String | (0) | The tenant of a caller that has none, such as the anonymous one. |
wow.timers
The node's firing loop of the timers, which sends the scheduled commands when they are due.
| Key | Type | Default | Description |
|---|---|---|---|
wow.timers.claim-timeout | Duration | PT30S | How long the claim on a timer being sent holds: when its node dies, the next owner of the partition sends the timer again after it. Longer than a send takes. |
wow.timers.expires-after | Duration | How late a timer may be sent, after an outage, before it is cancelled with the outcome EXPIRED instead; not set, every timer is sent however late. | |
wow.timers.lookahead | Duration | PT30S | How far ahead each read loads the timers that fall due; a longer lookahead reads more timers at once. |
wow.timers.max-attempts | Integer | 10 | The attempts a technical failure to send a timer gets before the timer is parked, under the subscription wow.timers.sends. |
wow.timers.max-early-wait | Duration | PT5S | How long a scheduled command waits in its target for its due time on the target node's clock; one that arrives earlier than that fails and is sent again later. |
wow.timers.max-fire-rate | Double | The most commands of timers a partition sends a second, so a backlog of overdue timers drains at that rate; not set, as fast as parallelism allows. | |
wow.timers.parallelism | Integer | 64 | The most commands of timers a partition sends at once. |
wow.timers.poll-interval | Duration | PT1S | How often the loop reads the timers due within lookahead, with one query per timer store over every partition the node owns; a timer is sent up to this late. |
wow.wait
How long and how far the commands' waits go.
| Key | Type | Default | Description |
|---|---|---|---|
wow.wait.default-timeout | Duration | PT10S | How long a command whose request names no timeout waits (Wow-Wait-Timeout), whichever edge it came through. At most wow.wait.max-timeout: a node whose default is above it does not start. |
wow.wait.max-hops | Integer | 16 | The most hops of a wait plan, at most WaitOptions.MAX_HOPS_CAP; each saga a chain follows adds two. |
wow.wait.max-registered | Integer | 16384 | The most waits the node holds at once, which bounds their memory: beyond it a command whose plan waits past ACCEPTED is not run and is answered wow.command.busy (429, with Retry-After), FAILED at ACCEPTED. |
wow.wait.max-timeout | Duration | PT1M | The longest wait; a longer timeout a caller asks for is capped to it, and a node stops within it. |
wow.wait.unknown-contexts | UnknownContexts | allow | Whether a wait plan may name a context the node knows no Manifest of: allow, checked where the chain arrives, or reject. |