[JAVA-5112] Represent timeouts internally as deadlines Created: 16/Aug/23  Updated: 27/Sep/23  Resolved: 27/Sep/23

Status: Closed
Project: Java Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Unknown
Reporter: Valentin Kavalenka Assignee: Maxim Katcharov
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Epic Link: Client Side Operations Timeout
Quarter: FY24Q2, FY24Q3
Documentation Changes Summary:

1. What would you like to communicate to the user about this feature?
2. Would you like the user to see examples of the syntax and/or executable code and its output?
3. Which versions of the driver/connector does this apply to?


 Description   

https://github.com/mongodb/mongo-java-driver/pull/1164 added TimePoint1, which implements Comparable<TimePoint>, as a tool to measure elapsed time:

TimePoint start = TimePoint.now();
...
Duration elapsed1 = start.elapsed();
Duration elapsed2 = TimePoint.now().durationSince(start);

maxim.katcharov@mongodb.com suggested in that PR that the driver can use deadlines internally instead of timeouts. If we do this, we won't need to have two APIs, Timeout and TimePoint, we will only need TimePoint. I like this idea.

The following table shows how usage may change as a result (the examples assume that the operation we are doing is acquiring a Lock):

timeouts deadlines

// results in calling `tryLock(...)`
Timeout timeout1 = Timeout.startNow(1, SECONDS);
Timeout timeout2 = Timeout.started(1, SECONDS, t);
// results in calling `tryLock(0, ...)`/`tryLock()`
Timeout expiredTimeout = Timeout.expired();
// results in calling `lock()`
Timeout noTimeout = Timeout.infinite();

// results in calling `tryLock(...)`
TimePoint deadline1 = TimePoint.now().add(Duration.ofSeconds(1));
TimePoint deadline2 = t.add(Duration.ofSeconds(1));
// results in calling `tryLock(0, ...)`/`tryLock()`
TimePoint missedDeadline = TimePoint.now();
// results in calling `lock()`
TimePoint noDeadline = TimePoint.infinity();

tryLock(
        timeout.remaining(NANOSECONDS),
        NANOSECONDS);

tryLock(
        deadline.saturatingDurationSince(TimePoint.now()).toNanos(),
        NANOSECONDS);

timeout.expired();

deadline.isNotAfter(TimePoint.now());
deadline.compareTo(TimePoint.now()) <= 0;

timeout.isInfinite();

deadline.isInfinity();
deadline.equals(TimePoint.infinite());
deadline.compareTo(TimePoint.infinity()) == 0;
TimePoint.infinity().isNotAfter(deadline);


1 TimePoint is, of course, implemented via System.nanoTime, but it is better to have a tool that

  • exposes types less generic than long
  • and values that are meaningful on their own (a value returned by System.nanoTime is meaningless on its own).


 Comments   
Comment by Valentin Kavalenka [ 23/Aug/23 ]

Risks

When deadline is used, replacing Timeout.toUserString becomes inconvenient, as it requires having more information than a single TimePoint to figure out what the timeout duration is. Passing this information alongside a deadline is what Timeout already does.

It may turn out that Timeout is a good abstraction for our purposes, after all.

Generated at Thu Feb 08 09:03:46 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.