Implementation:Vespa engine Vespa ConfigSubscriber NextGeneration
| Field | Value |
|---|---|
| Sources | Vespa |
| Domains | Configuration, Distributed_Systems |
| Type | API Doc |
| Last Updated | 2026-02-09 12:00 GMT |
Overview
ConfigSubscriber::nextGeneration is a blocking method that waits for any new configuration generation, returning true regardless of whether the subscribed config content has actually changed.
Description
The nextGeneration method is the generation-aware counterpart to nextConfig. While nextConfig requires at least one subscription to have changed content, nextGeneration returns true on any new generation number -- even if all subscribed configs are identical to the previous generation.
Internally, nextGeneration delegates to ConfigSubscriptionSet::acquireSnapshot(timeout, true), where the true parameter is the ignoreChange flag. This flag modifies the synchronization condition in the polling loop:
- With
ignoreChange = false(nextConfig): requiresnumChanged > 0 - With
ignoreChange = true(nextGeneration): ignores thenumChangedcount
The synchronization condition becomes:
inSync = generationsInSync
&& (_subscriptionList.size() == numGenerationChanged)
&& (ignoreChange || numChanged > 0);
This makes nextGeneration the appropriate choice when the process needs to:
- Track the current configuration generation for coordination with other cluster components
- Acknowledge generation changes to the config system even when its own config has not changed
- Use
ConfigHandle::isChanged()to selectively determine which configs need reconfiguration
A convenience variant nextGenerationNow() calls nextGeneration with a zero timeout for non-blocking polling.
Code Reference
Source Location
- Repository
vespa-engine/vespa- File (declaration)
config/src/vespa/config/subscription/configsubscriber.h- Line
- 69
- File (definition)
config/src/vespa/config/subscription/configsubscriber.cpp- Lines
- 26--30
Signature
bool ConfigSubscriber::nextGeneration(vespalib::duration timeout = DEFAULT_NEXTCONFIG_TIMEOUT);
Convenience Variant
bool ConfigSubscriber::nextGenerationNow() { return nextGeneration(vespalib::duration::zero()); }
Internal Delegation
bool
ConfigSubscriber::nextGeneration(vespalib::duration timeout)
{
return _set.acquireSnapshot(timeout, true);
}
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
timeout |
vespalib::duration |
No | Maximum time to block waiting for a new generation. Defaults to DEFAULT_NEXTCONFIG_TIMEOUT.
|
Outputs
| Name | Type | Description |
|---|---|---|
| return | bool |
true if a new configuration generation was obtained (regardless of content changes). false if the timeout was reached or the subscriber has been closed.
|
Side Effects
- On the first call, transitions the subscription set from
OPENtoFROZEN(same asnextConfig). - On success, updates the internal generation counter and flips all subscriptions.
- Sets the subscription set state to
CONFIGURED.
Comparison: nextConfig vs nextGeneration
| Aspect | nextConfig |
nextGeneration
|
|---|---|---|
| Returns true when | New generation and at least one config content changed | New generation (any) |
| ignoreChange parameter | false |
true
|
| Use case | React only to actual config changes | Track generation for coordination; use isChanged() for selective handling
|
| Typical caller | Simple config consumers | Cluster-aware processes, orchestration |
Usage Examples
Generation-Aware Polling Loop
#include <vespa/config/subscription/configsubscriber.h>
#include "config-myapp.h"
#include "config-ranking.h"
using namespace config;
ConfigSubscriber subscriber;
auto appHandle = subscriber.subscribe<MyappConfig>("myapp/instance1");
auto rankHandle = subscriber.subscribe<RankingConfig>("myapp/instance1");
subscriber.nextGeneration(); // Initial fetch
while (!subscriber.isClosed()) {
if (subscriber.nextGeneration(60s)) {
int64_t gen = subscriber.getGeneration();
LOG(info, "New generation: %ld", gen);
if (appHandle->isChanged()) {
auto appCfg = appHandle->getConfig();
reconfigureApp(*appCfg);
}
if (rankHandle->isChanged()) {
auto rankCfg = rankHandle->getConfig();
reconfigureRanking(*rankCfg);
}
acknowledgeGeneration(gen); // Report to cluster controller
}
}
Non-Blocking Generation Check
// Check if a new generation is available without blocking
if (subscriber.nextGenerationNow()) {
int64_t gen = subscriber.getGeneration();
// Process new generation
}