Skip to content

Conversation

@jcjones
Copy link
Contributor

@jcjones jcjones commented Dec 16, 2025

Resolves #4019

The rest of the owl:

    /\_/\
   ( o o )
   (  V  )
  /--m-m--\

This small change consists of a few commits which refactor janus_messages::Time and ::Duration to be in janus_messages::TimePrecision units. After the change to the janus_messages module, the first series of commits were done with regexes to get everything to compile. Then I progressively fixed tests, until they all passed. Then I've been performing cleanup, resolving issues from self-review and otherwise.

I have filed follow-on issues for things that seemed bigger but not intrinsic to this change:

I did include two other notable fixes/refactors in this PR which arguably could have gone into separate ones, and still could:

…regation_artifacts test to use fold/merged_with
…k test

- Fix the time_bucket_start_opt for add_report, which I had broken.
- Then also ensure that we ask for buckets, not timestamps
…TIME_PRECISION) to from_time_precision_units(0)
FromSql: PostgreSQL empty range is decoded as Interval::EMPTY, which is good. However,
ToSql: Interval::EMPTY encodes to [1970-01-01 00:00:00, 1970-01-01 00:00:00), which
bit me while I was fixing the rest of this.

We shouldn't ever hit this! But we might as well fix it while we're here.

Also, these timestamps in PostgreSQL are microseconds, not millis.
@jcjones jcjones requested a review from a team as a code owner December 16, 2025 15:56
Comment on lines +2838 to +2850
let now_time = clock.now().to_time(&time_precision);

let report_time_2 = now_time.sub_duration(&batch_time_window_size).unwrap();
let report_time_1 = report_time_2.sub_duration(&batch_time_window_size).unwrap();

// Compute the bucketed time bucket starts for querying outstanding batches
let batch_window_units = batch_time_window_size.as_time_precision_units();
let bucket_time_1 = Time::from_time_precision_units(
(report_time_1.as_time_precision_units() / batch_window_units) * batch_window_units,
);
let bucket_time_2 = Time::from_time_precision_units(
(report_time_2.as_time_precision_units() / batch_window_units) * batch_window_units,
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is just not ergonomic. I did it this way because to_batch_interval_start() is just odd to reason through hanging off of DateTimeExt -- for this purpose anyway. It's also a bit weird to hang off Time because then we need basically two time_precision arguments.

I'm going to open a follow-on to tackle this better. For now, this may be dumb but it works.

Copy link
Contributor

@tgeoghegan tgeoghegan left a comment

Choose a reason for hiding this comment

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

I still need to look at the stuff in janus_aggregator_core::datastore but I'm going a little cross eyed and it's getting dark outside, so here's a first set of comments.

Copy link
Contributor

Choose a reason for hiding this comment

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

The other day I observed to Chris Patton that I'm no longer sure exactly which draft of taskprov we implement. Since you've been looking at this closely and are up to speed on related changes to taskprov itself, do you think you could document the implemented taskprov draft version in the "Draft versions and release branches" table in the top-level README.md? I think it's OK if many of the rows of the taskprov draft columns are "?" so long as we start tracking what version we implement in main / release/0.9 onward.

Comment on lines +120 to +121
(report.client_timestamp().as_time_precision_units() / batch_window_units)
* batch_window_units,
Copy link
Contributor

@tgeoghegan tgeoghegan Dec 17, 2025

Choose a reason for hiding this comment

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

It really looks like / batch_window_units * batch_window_units should cancel out, and then Time::from_time_precision_units(report.client_timestamp().as_time_precision_units()) is just report.client_timestamp(). But I think what's happening is that report.client_timestamp() is in terms of the task's time precision but batch_time_window_size is in terms of a different time precision used by the batch creator? Would a method on Time akin to Interval::to_time_precision help make it clear that we're doing a conversion here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's the issue exactly, the possibility for them being a factor of each other. I'm going to rework that in #4225.

Copy link
Contributor

@tgeoghegan tgeoghegan left a comment

Choose a reason for hiding this comment

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

More comments on the datastore stuff. Please re-request review when you're done addressing things and I will do another pass.

pub fn remaining_lease_duration(&self, current_time: &Time, skew_seconds: u64) -> StdDuration {
pub fn remaining_lease_duration(
&self,
current_time: &DateTime<Utc>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Lease::lease_expiry_time is NaiveDateTime. Is there a reason current_time can't be the same type? Would that simplify the arithmetic here?

}

/// Convert an interval from task time precision to SQL time precision.
pub fn from_task_interval(
Copy link
Contributor

Choose a reason for hiding this comment

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

task_interval doesn't sound right. from_dap_time_interval?

Comment on lines +2310 to +2312
let start_sql_usec = time_to_sql_timestamp(*self.0.start(), &SQL_UNIT_TIME_PRECISION)
.map_err(|_| "microsecond timestamp of Interval start overflowed")?;
let end_sql_usec = time_to_sql_timestamp(self.0.end(), &SQL_UNIT_TIME_PRECISION)
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm. I dislike that we have start() -> &Time end() -> Time, especially since Time is Copy and it's just a u64, so we shouldn't bother with references anyway. Ah well, that's not a new issue.

@jcjones
Copy link
Contributor Author

jcjones commented Dec 18, 2025

More comments on the datastore stuff. Please re-request review when you're done addressing things and I will do another pass.

Will do, but at this point, I'm out! I've resolved everything that I've ... resolved with commits. The unresolved comments will be there for me when we return! See you in 2026!

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.

DAP-16: Represent Times and Durations as Multiples of Precision

4 participants