Die vollständige reference.conf
Das ist die eingebaute Konfiguration des Frameworks, exakt so, wie sie in
src/config/reference.ts ausgeliefert wird. Es ist die vollständige
Menge der First-Party-Settings: was hier nicht steht, hat keine HOCON-Form,
und was hier steht, wird von irgendetwas gelesen (sonst schlägt ein Test
fehl — siehe Keine toten Keys unten).
Jeder gezeigte Wert ist der bereits geltende Default, du musst also nie das
Ganze kopieren. Schreib nur das in deine application.conf, was du ändern
willst:
# application.conf — alles andere behält die Defaults untenactor-ts { system.name = "billing" sharding.passivation-idle = 2 minutes}Was die einzelnen Keys tun, steht in Konfiguration — diese Seite ist die vollständige Liste, jene die Erklärung.
Die Datei
Abschnitt betitelt „Die Datei“actor-ts { system { name = "default" }
logger { level = "info" # debug | info | warn | error | off }
dispatcher { default = "immediate" # immediate | microtask | throughput throughput = 16 }
cluster { gossip-interval = 1s seed-retry-interval = 3s weakly-up-after = 0s # 0 disables auto weakly-up promotion
# Caps on the local member map. max-frame-bytes bounds ONE gossip frame; # these bound what a sequence of well-formed frames can accumulate, since # gossip is what introduces addresses in the first place. 0 disables # either. max-tombstones is the load-bearing one: a tombstone carries no # liveness, so nothing but the TTL below ever reclaims it. max-members = 1000 max-tombstones = 10000
tombstone { time-to-live = 24h prune-interval = 5m min-retention = 0s # 0 = derive from failure-detector down-after }
failure-detector { heartbeat-interval = 500ms unreachable-after = 2s down-after = 5s # measured from the last heartbeat, so > unreachable-after }
# Stable-observation bootstrap: poll discovery until the contact-point set # has been unchanged for stable-margin, then let the lowest-addressed node # -- and only it -- form a cluster if no peer promoted it within # self-election-grace. Opt-in: bootstrapCluster reads this block only when # its stableObservation option is set. required-contact-points is the one # knob worth changing: 1 keeps single-node development working, but only a # value matching the expected replica count catches discovery that is # stably wrong rather than merely slow. bootstrap { stable-margin = 5s poll-interval = 1s max-wait = 60s required-contact-points = 1 self-election-grace = 10s }
# Cluster-wide publish/subscribe (DistributedPubSub). The caps bound what # one mediator can be made to hold -- by local subscribers and by a peer's # gossiped topic claims alike. A Subscribe over a cap is answered with # SubscribeRejected, never silently dropped. pub-sub { gossip-interval = 1s max-subscribers-per-topic = 10000 max-topics = 10000 max-remote-nodes-per-topic = 1000 # A publish that reached no subscriber goes to system.deadLetters, so a # mistyped topic is observable instead of silent. off = discard it. send-to-dead-letters-when-no-subscribers = on }
# Cluster-wide service registry (Receptionist). Subscribers are watched, # so a stopped one is dropped; the caps bound the ones that are still alive. receptionist { gossip-interval = 1s max-subscribers-per-key = 1000 max-subscribers-total = 10000 } }
# Cluster-wide replicated CRDT store (DistributedData). Top-level rather # than under cluster.* because the module is -- the cluster is a positional # argument to start(), not a tunable. Both caps bound quorum requests # (updateAsync + getAsync); 0 disables either. What they buy is a bound on # the unsettled set itself: every entry holds a promise, a timer and a # target set until its deadline passes, so refusing past the cap turns what # would be a timeout storm into immediate, attributable rejections. distributed-data { gossip-interval = 1s max-pending-quorum-requests = 1000 max-quorum-timeout = 30s }
remote { # Bind address of this node. Cluster.join reads these when its options # leave host/port unset, so a deployment can move the address into config. tcp { host = "0.0.0.0" port = 2552 } tls { enabled = false # DEAD KEY — not read by anything yet, see issue #591 } max-frame-bytes = 16M # per-frame wire cap; lower it on semi-trusted networks }
http { backend = "fastify" # fastify | express | hono # In-flight drain window for unbind() before connections are forced. # 0 keeps the historical behaviour (force immediately); raise it if you # want in-flight requests to finish on shutdown. shutdown-grace-period = 0ms
# Server-side defaults for websocket() routes (per-connection policy). # Leaf names match the WebsocketRouteOptions fields (camelCase); a route # may override any of them, and the resolved values are validated # (OptionsError on a bad value). websocket { maxFrameBytes = 1M # inbound frame size cap onOversizeFrame = "close" # close | drop onInvalidMessage = "close" # close | drop | hook maxBufferedBytes = 4M # outbound buffer cap before backpressure onBackpressure = "drop" # drop | close # maxConnections is unlimited by default; set a positive integer to cap. } }
cache { # Defaults for the built-in in-memory cache (the "default" cache, and any # cache whose plugin resolves to actor-ts.cache.in-memory). Leaf names # match the InMemoryCacheOptions fields (camelCase) and are validated on # read — a bad value throws OptionsError. in-memory { maxEntries = 10000 # LRU cap on entries (Infinity/unbounded only settable in code) cleanupMs = 60000 # background expired-entry sweep interval, ms (0 disables the sweep) } }
persistence { journal { plugin = "actor-ts.persistence.journal.in-memory" } snapshot-store { plugin = "actor-ts.persistence.snapshot-store.in-memory" } }
sharding { number-of-shards = 64 rebalance-interval = 2s hand-off-timeout = 10s remember-entities = false passivation-idle = 5m # idle window before an entity passivates; 0 disables the sweep # shard-passivation-idle -- how long a shard may stand empty before it # stops as well. Deliberately left unset rather than given a value: # unset, it follows passivation-idle, which is what "the shard goes # when its entities do" needs. Set it (0ms disables) to decouple them. max-entities = 0 # 0 = no per-node cap }
worker-cluster { workers = "auto" # "auto" uses navigator.hardwareConcurrency restart-policy = "on-failure" # always | on-failure | never }
coordinated-shutdown { default-phase-timeout = 5s terminate-actor-system = true exit-process = false # call process.exit(0) once the pipeline completes }}Was hier bewusst fehlt
Abschnitt betitelt „Was hier bewusst fehlt“Zwei Familien von Settings haben oben keinen Eintrag, beide mit Absicht.
Plugin-Subtrees. Journals, Snapshot Stores, Caches und Broker lesen
ihre Verbindungs-Settings aus ihrem eigenen Subtree —
actor-ts.persistence.journal.postgres, actor-ts.io.broker.kafka,
actor-ts.cache.redis und so weiter. Sie sind optionale Peers; Defaults
für sie auszuliefern hieße, eine Konfiguration für ein Paket
auszuliefern, das du vielleicht gar nicht installiert hast. Jedes ist auf
seiner eigenen Seite dokumentiert.
Alles, was kein Wert ist. Der Entity-Actor, Message-Extraktoren,
Allocation Strategies, Leases, Transports, Downing Provider, eigene
Backends — eine Config-Datei kann keine Klasse und keine Closure
ausdrücken, also bleiben die im Code und laufen über den jeweiligen
XOptions-Builder.
Präzedenz
Abschnitt betitelt „Präzedenz“Drei Schichten, höchste zuerst:
- Explizite Optionen im Code —
ClusterOptions.create().withPort(2552),ActorSystem.create('billing'). - Deine
application.conf(oder ein inlineconfig-Objekt). - Diese Datei.
Pro Feld, nicht pro Block: setzt du eine Failure-Detector-Schwelle im
Code, kommen die anderen beiden weiterhin aus deiner Config-Datei. Ein
undefined im Code bedeutet „nicht gesetzt” und fällt durch — es löscht
die darunterliegende Schicht nicht.
Keine toten Keys
Abschnitt betitelt „Keine toten Keys“Eine ganze Weile lang dokumentierte diese Datei rund fünfundzwanzig
Settings, die im Framework nie jemand gelesen hat. Du konntest
actor-ts.sharding.passivation-idle = 2 minutes setzen, bekamst keine
Passivierung und keine Warnung — der Wert wurde nicht abgelehnt, er wurde
nie angeschaut (Issue #653).
Das ist jetzt ein Build-Fehler. Ein Test läuft über jedes Blatt oben und
prüft, dass es sowohl von ConfigKeys aus erreichbar ist — der typisierten
Liste der Pfade, die das Framework kennt — als auch im Quellcode
referenziert wird. Ein Key ist bewusst ausgenommen und sagt das an Ort und
Stelle: remote.tls.enabled ist inert, bis
#591 landet, und die
Ausnahme ist mit dieser Issue-Nummer registriert statt implizit zu bleiben.
