Skip to content

Conversation

@erikjohnston
Copy link
Member

@erikjohnston erikjohnston commented Nov 26, 2025

This changes the arguments in clock functions to be Duration and converts call sites and constants into Duration. There are still some more functions around that should be converted (e.g. timeout_deferred), but we leave that to another PR.

We also changes .as_secs() to return a float, as the rounding broke things subtly. The only reason to keep it (its the same as timedelta.total_seconds()) is for symmetry with as_millis().

Follows on from #19223

Reviewable commit-by-commit.

@erikjohnston erikjohnston marked this pull request as ready for review November 28, 2025 10:31
@erikjohnston erikjohnston requested a review from a team as a code owner November 28, 2025 10:31
Copy link
Member

@anoadragon453 anoadragon453 left a comment

Choose a reason for hiding this comment

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

Really nice readability improvements across the board!

I went through each of the conversions and they looked to be correct. Just a few things below.


def as_millis(self) -> int:
"""Returns the duration in milliseconds."""
return int(self / _ONE_MILLISECOND)
Copy link
Member

Choose a reason for hiding this comment

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

I assume sub-millisecond accuracy doesn't really matter in our case and thus we don't need to do the same for as_millis? (Edit: well, we found one case where it might).

We should note that milliseconds is the smallest time unit this class can work with in the Duration docstring.


# How often we expect remote servers to resend us presence.
FEDERATION_TIMEOUT = 60 * 1000
FEDERATION_TIMEOUT = Duration(seconds=60)
Copy link
Member

Choose a reason for hiding this comment

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

We should be consistent regarding Duration(minutes=1) vs. Duration(seconds=60). Personally I prefer the former.

if hs.config.worker.run_background_tasks:
self.clock.looping_call(
self.cull_expired_threepid_validation_tokens, THIRTY_MINUTES_IN_MS
self.cull_expired_threepid_validation_tokens, THIRTY_MINUTES
Copy link
Member

Choose a reason for hiding this comment

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

We can potentially just inline Duration(minutes=30) here now? I suspect the only reason for the global variable was because 30 * 60 * 1000 was more awful to inline.

# Precision of the scheduler, evaluation of tasks to run will only happen
# every `SCHEDULE_INTERVAL_MS` ms
SCHEDULE_INTERVAL_MS = 1 * 60 * 1000 # 1mn
# every `SCHEDULE_INTERVAL` ms
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# every `SCHEDULE_INTERVAL` ms
# every `SCHEDULE_INTERVAL`

def _scheduler(x: Callable[[], object]) -> IDelayedCall:
return clock.call_later(
_EPSILON,
Duration(seconds=_EPSILON),
Copy link
Member

Choose a reason for hiding this comment

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

We're losing some accuracy here (though I'm not sure how much it matters in this case).

The smallest unit datetime.timedelta deals with is microseconds. _EPSILON is 0.01 microseconds (10 nanoseconds), so Duration(seconds=_EPSILON).as_millis() will result in 1.

I think it'd also be cleaner to write either:

_EPSILON = Duration(milliseconds=1)

or inline it:

        return clock.call_later(
            Duration(milliseconds=1),
            x,
        )

Comment on lines +135 to +138
let duration_module = py.import("synapse.util.duration")?;

let kwargs = [("milliseconds", eviction_interval)].into_py_dict(py)?;
let eviction_duration = duration_module.call_method("Duration", (), Some(&kwargs))?;
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, this is a little horrible. Is it possible to make a Rust struct that wraps synapse.util.duration that we can easily work with?

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.

3 participants