Skip to content

Conversation

BBQing
Copy link
Contributor

@BBQing BBQing commented Jul 18, 2025

Relates: #20342

Please read https://github.com/etcd-io/etcd/blob/main/CONTRIBUTING.md#contribution-flow.

This is a proposal on how to fix the issue. the problem is, that for the parameter --watch-progress-notify-interval, there is a difference in the behavior. While it is accepted as duration string from CLI, when provided in config_file, it has to be a number, that then gets converted into nanoseconds so for example for 1s you have to use 1000000000. Although it works well for machines it's bad for humans.

I have wrapped the time.duration, so that I can implement the UnmarshalJSON interface and also I have implemented flag.Value interface. And applied it where necessary.
I have also fixed some tests.

The fix supports both numbers and duration string from config file and in the future there can be issued warning, in case it will be decided to abandon the possibility to use numbers in the configuration.

It might be necessary to do this for every duration parameter in the future.
I guess this concerns etcdserver.

@k8s-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BBQing
Once this PR has been reviewed and has the lgtm label, please assign fuweid for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot
Copy link

Hi @BBQing. Thanks for your PR.

I'm waiting for a etcd-io member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@BBQing
Copy link
Contributor Author

BBQing commented Jul 20, 2025

@ivanvc could you check it?

@ivanvc
Copy link
Member

ivanvc commented Jul 25, 2025

Please refer to my comment in #20342 (comment).

@ivanvc
Copy link
Member

ivanvc commented Jul 25, 2025

/ok-to-test

@@ -156,6 +156,46 @@ func init() {
defaultHostname, defaultHostStatus = netutil.GetDefaultHost()
}

type Duration struct {
Duration time.Duration
Copy link
Member

Choose a reason for hiding this comment

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

I left a comment here before, but I don't know what happened as it seems like GitHub dropped it 🤔.

I suggested changing this to an anonymous field. I believe it would be transparent in cases like:

		WatchProgressNotifyInterval:       cfg.WatchProgressNotifyInterval.Duration,

We could revert this change.

Suggested change
Duration time.Duration
time.Duration

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I initially had it anonymous, but then I have decided to be more explicit - I have reverted the change

Updated tests to work with wrapped duration

Signed-off-by: sprochazka <[email protected]>
@BBQing BBQing force-pushed the unmarshall_duration branch from b0edd91 to 519616b Compare July 25, 2025 22:42
Copy link
Member

@ivanvc ivanvc left a comment

Choose a reason for hiding this comment

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

Thanks for the changes, @BBQing. I must have been more explicit before with my suggestion. Apologies, again, I'm not sure why GitHub sent my comment to the void 😅

@@ -224,7 +224,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) {
UnsafeNoFsync: cfg.UnsafeNoFsync,
CompactionBatchLimit: cfg.CompactionBatchLimit,
CompactionSleepInterval: cfg.CompactionSleepInterval,
WatchProgressNotifyInterval: cfg.WatchProgressNotifyInterval,
WatchProgressNotifyInterval: cfg.WatchProgressNotifyInterval.Duration,
Copy link
Member

Choose a reason for hiding this comment

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

With the anonymous time.Duration field, I believe this change is no longer necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have tried to use embed.Duration(current location) instead of time.Duration in the ServerConfig and it failed on the circular imports - I am thinking if the Duration should be placed in the pkg directory in its own package (or in some already existing package).
I'll continue with changes tomorrow. But thank you for the feedback - I am learning a lot.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, @BBQing. I'll keep an eye on this pull request.

Comment on lines 185 to 187
func (d Duration) String() string {
return d.Duration.String()
}
Copy link
Member

Choose a reason for hiding this comment

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

And this is not required, either. As it would call String() from d.Duration.

Copy link

codecov bot commented Jul 25, 2025

Codecov Report

❌ Patch coverage is 88.23529% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.20%. Comparing base (0888376) to head (567d35a).
⚠️ Report is 234 commits behind head on main.

Files with missing lines Patch % Lines
server/embed/config.go 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
server/embed/config_duration.go 100.00% <100.00%> (ø)
server/embed/config.go 79.16% <0.00%> (+50.06%) ⬆️

... and 163 files with indirect coverage changes

@@            Coverage Diff             @@
##             main   #20360      +/-   ##
==========================================
+ Coverage   62.94%   69.20%   +6.26%     
==========================================
  Files         386      417      +31     
  Lines       32989    34724    +1735     
==========================================
+ Hits        20765    24031    +3266     
+ Misses      10667     9300    -1367     
+ Partials     1557     1393     -164     

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0888376...567d35a. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@BBQing BBQing force-pushed the unmarshall_duration branch from 2bcd25a to d7ec16e Compare July 30, 2025 07:48
@BBQing BBQing force-pushed the unmarshall_duration branch from c83387a to a635dc9 Compare July 30, 2025 08:08
@BBQing BBQing force-pushed the unmarshall_duration branch from 1c07ac7 to 2e78494 Compare July 30, 2025 12:59
Copy link
Member

@ivanvc ivanvc left a comment

Choose a reason for hiding this comment

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

Thanks for the updates, @BBQing. Please take a look at my comments :)

Comment on lines 909 to 911
if cfg.WatchProgressNotifyIntervalJSON.Duration != 0 {
cfg.WatchProgressNotifyInterval = cfg.WatchProgressNotifyIntervalJSON.Duration
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion to drop the .Duration

Suggested change
if cfg.WatchProgressNotifyIntervalJSON.Duration != 0 {
cfg.WatchProgressNotifyInterval = cfg.WatchProgressNotifyIntervalJSON.Duration
}
if cfg.WatchProgressNotifyIntervalJSON != 0 {
cfg.WatchProgressNotifyInterval = cfg.WatchProgressNotifyIntervalJSON
}

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, I missed the casting. Thanks for adding that.

Comment on lines 362 to 364
return func(c *EtcdProcessClusterConfig) { c.ServerConfig.WatchProgressNotifyInterval = interval }
return func(c *EtcdProcessClusterConfig) {
c.ServerConfig.WatchProgressNotifyInterval = interval
}
Copy link
Member

Choose a reason for hiding this comment

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

Could you please revert this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

Copy link
Member

Choose a reason for hiding this comment

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

Thanks :)

"time"
)

type Duration struct {
Copy link
Member

Choose a reason for hiding this comment

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

This should be named ConfigDuration if the filename is config_duration.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll change that

Copy link
Member

Choose a reason for hiding this comment

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

Thanks!

Comment on lines 369 to 370
WatchProgressNotifyInterval time.Duration
WatchProgressNotifyIntervalJSON Duration `json:"watch-progress-notify-interval"`
Copy link
Member

Choose a reason for hiding this comment

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

What was the issue of keeping a single field?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The problem for me was, that in the downstream the value is compared to some time.Duration constant (minimal watch progress interval - I could have retyped the constant into the new Duration type, but I think since the functionality of the wrapper type is related to configuration, it should remain there and not leak outside. So I have decided to follow approach used for different configuration fields, that also require some special treatment. beyond the standard unmarshalling

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense, thanks for the clarification. Let's see what other contributors think :)

…d Duration to ConfigDuration

Signed-off-by: sprochazka <[email protected]>
@ivanvc
Copy link
Member

ivanvc commented Aug 1, 2025

This looks good to me. It fixes the issue for watch-progress-notify-interval. Ideally, after this pull request, we should have a follow-up to address the remaining duration fields.

However, I'm not an expert on etcdserver. @ahrtr, @fuweid, would you be able to please take a look at this? Thanks.

@BBQing BBQing mentioned this pull request Aug 2, 2025
4 tasks
@BBQing
Copy link
Contributor Author

BBQing commented Aug 5, 2025

@ahrtr @fuweid Could you please check this PR? Thank you

@ahrtr ahrtr self-requested a review August 8, 2025 10:52
@ahrtr
Copy link
Member

ahrtr commented Aug 10, 2025

Thanks for the contribution, but please see my comment #20342 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants