Skip to content

[server] Support altering table.log.ttl table option#3233

Open
Kaixuan-Duan wants to merge 1 commit intoapache:mainfrom
Kaixuan-Duan:issue-3231-support-alter-ttl
Open

[server] Support altering table.log.ttl table option#3233
Kaixuan-Duan wants to merge 1 commit intoapache:mainfrom
Kaixuan-Duan:issue-3231-support-alter-ttl

Conversation

@Kaixuan-Duan
Copy link
Copy Markdown

@Kaixuan-Duan Kaixuan-Duan commented Apr 29, 2026

Purpose

Linked issue: close #3231

Brief change log

  • Add ConfigOptions.TABLE_LOG_TTL.key() to FlussConfigUtils.ALTERABLE_TABLE_OPTIONS so the validator no longer rejects ALTER on this option.
  • Change RemoteLogTablet#ttlMs from final to volatile and add getTtlMs() / updateTtlMs(long) so the remote-log expiration check can observe the new value without recreating the tablet.
  • Add Replica#updateLogTtlMs(long) which looks up the corresponding RemoteLogTablet via RemoteLogManager and applies the new TTL, guarded by an IllegalStateException fallback for the case where the tablet has not been registered yet.
  • Extend ReplicaManager#updateReplicaTableConfig to collect a tableIdToLogTtlMs map from the metadata diff and dispatch updateLogTtlMs to each affected replica, mirroring how table.log.tiered.local-segments is already handled.

Tests

./mvnw -pl fluss-server test -Dtest='RemoteLogTabletTest,RemoteLogManagerTest,RemoteLogTTLTest'

./mvnw -pl fluss-client test -Dtest='FlussAdminITCase'

API and Format

Documentation

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables ALTER TABLE ... SET ('table.log.ttl' = ...) by allowing the option through config validation and propagating updated TTL values into the server-side remote-log expiration logic without requiring tablet recreation.

Changes:

  • Allow table.log.ttl to be altered by adding it to FlussConfigUtils.ALTERABLE_TABLE_OPTIONS.
  • Make RemoteLogTablet TTL mutable/visible across threads and add update/access methods; wire TTL updates through Replica and ReplicaManager.
  • Add/extend tests to validate TTL alteration persistence and runtime effect on remote-log expiration.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
fluss-common/src/main/java/org/apache/fluss/config/FlussConfigUtils.java Allows table.log.ttl to pass ALTER-table option validation.
fluss-server/src/main/java/org/apache/fluss/server/log/remote/RemoteLogTablet.java Makes TTL mutable (volatile) and adds TTL getter/updater for runtime expiration decisions.
fluss-server/src/main/java/org/apache/fluss/server/replica/Replica.java Adds updateLogTtlMs to apply TTL changes to the associated RemoteLogTablet.
fluss-server/src/main/java/org/apache/fluss/server/replica/ReplicaManager.java Propagates TTL values from metadata updates to online replicas.
fluss-server/src/test/java/org/apache/fluss/server/log/remote/RemoteLogTabletTest.java Adds unit coverage for TTL update behavior affecting expiration results.
fluss-server/src/test/java/org/apache/fluss/server/log/remote/RemoteLogManagerTest.java Adds integration-style test ensuring replica-driven TTL updates reach RemoteLogTablet.
fluss-client/src/test/java/org/apache/fluss/client/admin/FlussAdminITCase.java Adds IT coverage verifying ALTER persists TTL into TableInfo and reset reverts to default.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

/** Returns the current ttl in milliseconds for remote log segments. */
@VisibleForTesting
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getTtlMs() is annotated @VisibleForTesting but is now used by production code (Replica.updateLogTtlMs). This annotation is misleading and may encourage future refactors to remove/break the method; consider either removing @VisibleForTesting (and documenting it as part of the runtime API) or exposing a non-test accessor via RemoteLogManager/package-private API that Replica can use.

Suggested change
@VisibleForTesting

Copilot uses AI. Check for mistakes.
Comment on lines +650 to +662
final RemoteLogTablet remoteLogTablet;
try {
remoteLogTablet = remoteLogManager.remoteLogTablet(tableBucket);
} catch (IllegalStateException e) {
// RemoteLogTablet may not be registered yet during the early stage of replica
// creation. In that case, the alter is a no-op here because the Replica will read the
// up-to-date ttl from the persisted TableInfo when constructing the RemoteLogTablet.
LOG.warn(
"RemoteLogTablet for {} is not registered yet, skip applying new logTtlMs={}.",
tableBucket,
newTtlMs);
return;
}
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This calls remoteLogManager.remoteLogTablet(tableBucket), which is currently a @VisibleForTesting method and throws IllegalStateException when absent. For production code paths, it would be cleaner to add a non-test API on RemoteLogManager (e.g., returning @Nullable/Optional) or a dedicated updateLogTtlMs(tableBucket, ttl) method, instead of relying on an exception-driven control flow.

Suggested change
final RemoteLogTablet remoteLogTablet;
try {
remoteLogTablet = remoteLogManager.remoteLogTablet(tableBucket);
} catch (IllegalStateException e) {
// RemoteLogTablet may not be registered yet during the early stage of replica
// creation. In that case, the alter is a no-op here because the Replica will read the
// up-to-date ttl from the persisted TableInfo when constructing the RemoteLogTablet.
LOG.warn(
"RemoteLogTablet for {} is not registered yet, skip applying new logTtlMs={}.",
tableBucket,
newTtlMs);
return;
}
final RemoteLogTablet remoteLogTablet = remoteLogManager.remoteLogTablet(tableBucket);

Copilot uses AI. Check for mistakes.
Comment on lines +654 to +658
// RemoteLogTablet may not be registered yet during the early stage of replica
// creation. In that case, the alter is a no-op here because the Replica will read the
// up-to-date ttl from the persisted TableInfo when constructing the RemoteLogTablet.
LOG.warn(
"RemoteLogTablet for {} is not registered yet, skip applying new logTtlMs={}.",
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logging this as WARN on every TTL update can be noisy in normal scenarios (e.g., remote-log tiering disabled globally or replica still initializing), and the message implies “not registered yet” even when remote logging is disabled. Consider downgrading to DEBUG (or gating on remote-log enabled) and/or refining the message so operators can distinguish disabled vs. not-yet-registered cases.

Suggested change
// RemoteLogTablet may not be registered yet during the early stage of replica
// creation. In that case, the alter is a no-op here because the Replica will read the
// up-to-date ttl from the persisted TableInfo when constructing the RemoteLogTablet.
LOG.warn(
"RemoteLogTablet for {} is not registered yet, skip applying new logTtlMs={}.",
// RemoteLogTablet may be unavailable when remote logging is disabled or during the
// early stage of replica creation. In those cases, the alter is a no-op here because
// the Replica will read the up-to-date ttl from the persisted TableInfo when
// constructing the RemoteLogTablet.
LOG.debug(
"RemoteLogTablet for {} is unavailable; skip applying new logTtlMs={} "
+ "(remote logging may be disabled or the replica is still initializing).",

Copilot uses AI. Check for mistakes.
Comment on lines +684 to +685
// Verify initial ttl is 7 days
long defaultTtlMs = java.time.Duration.ofDays(7).toMillis();
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test hard-codes the default TTL as 7 days. Since the default is already defined in ConfigOptions.TABLE_LOG_TTL, it would be more robust to derive the expected value from the config option (as done in RemoteLogTabletTest) to avoid failures if the default ever changes.

Suggested change
// Verify initial ttl is 7 days
long defaultTtlMs = java.time.Duration.ofDays(7).toMillis();
// Verify initial ttl matches the configured default table.log.ttl
long defaultTtlMs = ConfigOptions.TABLE_LOG_TTL.defaultValue().toMillis();

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support alter table.log.ttl

2 participants