1
0
mirror of https://github.com/google/nomulus synced 2026-05-13 11:21:46 +00:00

Refactor bsa, dns, batch, and reporting packages to java.time (#3031)

This commit migrates the BSA, DNS, batch, and reporting packages from Joda-Time
to java.time. Key changes include:

- Updated Sleeper, Clock, and BigqueryUtils to use java.time types natively.
- Refactored models like RdeRevision and Tld to eliminate redundant Joda
  conversions, utilizing new DateTimeUtils static utilities for LocalDate.
- Improved test safety by replacing dynamic Instant.now() calls with static
  parsed constants.
- Migrated temporal arithmetic in test suites to use DateTimeUtils convenience
  methods (plusDays, minusDays).
- Updated BigqueryUtils serialization to preserve millisecond precision and
  formatting for large years, ensuring consistency with previous Joda behavior.
- Enhanced code readability by converting long concatenated strings to Java
  text blocks in LordnLogTest.
- Resolved environmental test failures in SyncRegistrarsSheetTest by
  synchronizing the FakeClock with the JPA extension.
- Updated project engineering standards (GEMINI.md) to prefer Truth's
  .hasValue() for Optional assertions.

Verified with a clean full build and all relevant test suites passing.
This commit is contained in:
Ben McIlwain
2026-05-06 17:44:40 -04:00
committed by GitHub
parent 81b3a2fc5b
commit 74f9f5d478
221 changed files with 1786 additions and 1587 deletions

View File

@@ -19,7 +19,7 @@ This document outlines foundational mandates, architectural patterns, and projec
- **CRITICAL MISTAKES TO AVOID:**
- NEVER use `toInstant(clock.nowUtc())` or `toInstant(fakeClock.nowUtc())`. Both `Clock` and `FakeClock` have a `now()` method that natively returns a `java.time.Instant`. You MUST use `clock.now()` or `fakeClock.now()` directly.
- NEVER double-wrap conversions like `toInstant(toDateTime(...))` or `toDateTime(toInstant(...))`.
- NEVER mark `Instant` parameters or local variables as `final` unnecessarily, as it clutters the codebase.
- NEVER mark method parameters or local variables as `final` unnecessarily, as it clutters the codebase. For class fields and constants, use `final` where applicable (i.e. when the field is assigned once and never mutated) to enforce and communicate immutability.
- When using test helpers like `assertThatCommand().atTime(...)` or `ForeignKeyUtils.loadResource(...)`, ALWAYS use the `Instant` overloads. DO NOT wrap `Instant` instances in `toDateTime(...)` just to pass them to deprecated overloads.
- **UTC Timezones:** Do not use `ZoneId.of("UTC")`. Use a statically imported `UTC` from `ZoneOffset` instead (`import static java.time.ZoneOffset.UTC;`).
- **Millisecond Precision:** Always truncate `Instant.now()` to milliseconds (using `.truncatedTo(ChronoUnit.MILLIS)`) to maintain consistency with Joda `DateTime` and the PostgreSQL schema (which enforces millisecond precision via JPA converters).
@@ -77,6 +77,7 @@ Based on historical PR reviews, avoid the following common mistakes:
- **Immutable Types:** Declare variables, fields, and return types explicitly as Guava immutable types (e.g., `ImmutableList<T>`, `ImmutableMap<K, V>`) instead of their generic interfaces (`List<T>`, `Map<K, V>`) to clearly communicate immutability contracts to callers. Use `toImmutableList()` and `toImmutableMap()` collectors in streams rather than manually accumulating into an `ArrayList` or `HashMap`.
- **Constructors:** Do not perform heavy logic, I/O, or external API calls inside constructors. Initialization logic should be deferred or handled in a factory method or a dedicated startup routine.
- **Exception Handling:** Do not catch generic `Exception` or `Throwable` if a more specific exception is expected. Never "log and re-throw" the same exception; either handle it entirely (and log), or throw it up the chain. For batch processes, catch exceptions at the individual item/chunk level so one failure doesn't abort the entire batch.
- **Optional Assertions:** Prefer Truth's `.hasValue(...)` over `.isEqualTo(Optional.of(...))` for cleaner and more descriptive assertions on `Optional` types.
- **Fail Fast:** Validate inputs and fail fast (using `Preconditions.checkArgument` or similar) at the highest level possible rather than passing invalid state (like `null`s) deeper into business logic.
- **Magic Numbers:** Always document magic numbers or hardcoded limits (like `50.0` or `30`) with inline comments explaining the rationale.
- **Null Safety and Optional:** Prefer using `Optional` for any variable that is expected to potentially be null. For any other variable that can be null but cannot use an `Optional` (e.g., function parameters or return types where `Optional` is not idiomatic), it MUST be annotated with `@Nullable`. Always use the `javax.annotation.Nullable` annotation.
@@ -119,6 +120,7 @@ Before finalizing any PR or declaring a task complete, you MUST perform a thorou
5. **Diff Scope:** Are there any formatting-only changes in files that I did not functionally modify? If so, revert them. Does the total line count of the diff align with the approved scope (e.g., ~1,000 lines for migrations)?
6. **Commit Message:** Does the commit message title fit within 50 characters? Does the body encapsulate the entirety of the changes across the diff cleanly and professionally?
7. **Missing Tests & Coverage:** *Perform a structured check for any new methods or modified behavior.* Did I add a new utility method (like `plusMonths(Instant, int)`) or change core logic? If so, I MUST open the corresponding test file and write tests to cover the new functionality (including edge cases, negative values, and leap years) before considering the task complete. A code review is not thorough if it only checks for compilation. I must actively ensure every new branch of logic has a test.
8. **Package Lock:** Did I include `console-webapp/package-lock.json` in my diff? If so, I MUST revert it (`git checkout console-webapp/package-lock.json`) unless I explicitly intended to modify NPM dependencies. This file is often modified by the build process and should not be committed accidentally.
Only after actively confirming these checks against your diff are you permitted to finalize the task.
@@ -156,20 +158,20 @@ This project treats Error Prone warnings as errors.
---
# GitHub and Pull Request Protocol
## GitHub and Pull Request Protocol
This protocol defines the standard for interacting with GitHub repositories and processing Pull Request (PR) feedback.
## 1. Interaction via `gh` CLI
### 1. Interaction via `gh` CLI
- **Primary Tool:** ALWAYS use the `gh` CLI for all GitHub-related operations (listing PRs, viewing PR content, checking status, adding comments).
- **Credential Safety:** Never expose tokens or credentials in shell commands.
## 2. Processing PR Feedback
### 2. Processing PR Feedback
- **Systematic Review:** When asked to address PR comments, first fetch all comments using `gh pr view <number> --json reviews,comments`.
- **Minimal Scope Expansion:** Address comments surgically. If a fix requires changes beyond a few lines or expands the PR's original scope significantly, DO NOT implement it without explicit user approval. Instead, report the issue to the user.
- **Verification:** After addressing feedback, run the full build (`./gradlew build`) and relevant tests to ensure no regressions were introduced.
## 3. PR Lifecycle Management
### 3. PR Lifecycle Management
- **One Commit Per PR:** Ensure all changes are squashed into a single, clean commit. Use `git commit --amend --no-edit` for follow-up fixes.
- **Clean Workspace:** Always run `git status` and verify the repository state before declaring a task complete.
- **Package Lock:** The Gradle build automatically modifies `console-webapp/package-lock.json` via the `npmInstallDeps` task. ALWAYS revert this file (`git checkout console-webapp/package-lock.json`) before staging changes or finalizing a commit unless you explicitly modified NPM dependencies.

View File

@@ -15,6 +15,7 @@
package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -30,14 +31,14 @@ import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.ReadableDuration;
/** Utilities methods and constants related to Joda {@link DateTime} objects. */
public abstract class DateTimeUtils {
/** The start of the epoch, in a convenient constant. */
@Deprecated public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC);
@Deprecated public static final DateTime START_OF_TIME = new DateTime(0, UTC);
/** The start of the UNIX epoch (which is defined in UTC), in a convenient constant. */
public static final Instant START_INSTANT = Instant.ofEpochMilli(0);
@@ -49,8 +50,7 @@ public abstract class DateTimeUtils {
* but Java uses milliseconds, so this is the largest representable date that will survive a
* round-trip through the database.
*/
@Deprecated
public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, DateTimeZone.UTC);
@Deprecated public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, UTC);
/**
* An instant in the far future that we can treat as infinity.
@@ -76,6 +76,10 @@ public abstract class DateTimeUtils {
.toFormatter()
.withZone(ZoneOffset.UTC);
/** A formatter that produces lowercase, filename-safe and job-name-safe timestamps. */
public static final DateTimeFormatter LOWERCASE_TIMESTAMP_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd't'HH-mm-ss'z'").withZone(ZoneOffset.UTC);
/** Formats an {@link Instant} to an ISO-8601 string. */
public static String formatInstant(Instant instant) {
return ISO_8601_FORMATTER.format(instant);
@@ -147,6 +151,18 @@ public abstract class DateTimeUtils {
return !timeToCheck.isAfter(timeToCompareTo);
}
/** Converts a Joda-Time Duration to a java.time.Duration. */
@Nullable
public static java.time.Duration toJavaDuration(@Nullable ReadableDuration duration) {
return duration == null ? null : java.time.Duration.ofMillis(duration.getMillis());
}
/** Converts a java.time.Duration to a Joda-Time Duration. */
@Nullable
public static org.joda.time.Duration toJodaDuration(@Nullable java.time.Duration duration) {
return duration == null ? null : org.joda.time.Duration.millis(duration.toMillis());
}
/** Returns whether the first {@link Instant} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isAfter(timeToCompareTo);
@@ -237,7 +253,17 @@ public abstract class DateTimeUtils {
}
public static LocalDate toLocalDate(Date date) {
return new LocalDate(date.getTime(), DateTimeZone.UTC);
return new LocalDate(date.getTime(), UTC);
}
/** Converts a java.time.LocalDate to a Joda-Time LocalDate. */
public static LocalDate toJodaLocalDate(java.time.LocalDate localDate) {
return new LocalDate(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
}
/** Converts an Instant to a Joda-Time LocalDate in UTC. */
public static LocalDate toJodaLocalDate(Instant instant) {
return new LocalDate(instant.toEpochMilli(), UTC);
}
/** Convert a joda {@link DateTime} to a java.time {@link Instant}, null-safe. */
@@ -249,7 +275,7 @@ public abstract class DateTimeUtils {
/** Convert a java.time {@link Instant} to a joda {@link DateTime}, null-safe. */
@Nullable
public static DateTime toDateTime(@Nullable Instant instant) {
return (instant == null) ? null : new DateTime(instant.toEpochMilli(), DateTimeZone.UTC);
return (instant == null) ? null : new DateTime(instant.toEpochMilli(), UTC);
}
/** Convert a java.time {@link java.time.Instant} to a joda {@link org.joda.time.Instant}. */

View File

@@ -14,6 +14,7 @@
package google.registry.util;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
@@ -32,6 +33,15 @@ public interface Sleeper {
*/
void sleep(ReadableDuration duration) throws InterruptedException;
/**
* Puts the current thread to sleep.
*
* @throws InterruptedException if this thread was interrupted
*/
default void sleep(Duration duration) throws InterruptedException {
sleep(DateTimeUtils.toJodaDuration(duration));
}
/**
* Puts the current thread to sleep, ignoring interrupts.
*
@@ -42,6 +52,18 @@ public interface Sleeper {
*/
void sleepUninterruptibly(ReadableDuration duration);
/**
* Puts the current thread to sleep, ignoring interrupts.
*
* <p>If {@link InterruptedException} was caught, then {@code Thread.currentThread().interrupt()}
* will be called at the end of the {@code duration}.
*
* @see com.google.common.util.concurrent.Uninterruptibles#sleepUninterruptibly
*/
default void sleepUninterruptibly(Duration duration) {
sleepUninterruptibly(DateTimeUtils.toJodaDuration(duration));
}
/**
* Puts the current thread to interruptible sleep.
*
@@ -57,4 +79,20 @@ public interface Sleeper {
throw new RuntimeException("Interrupted.", e);
}
}
/**
* Puts the current thread to interruptible sleep.
*
* <p>This is a convenience method for {@link #sleep} that properly converts an {@link
* InterruptedException} to a {@link RuntimeException}.
*/
default void sleepInterruptibly(Duration duration) {
try {
sleep(duration);
} catch (InterruptedException e) {
// Restore current thread's interrupted state.
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted.", e);
}
}
}

View File

@@ -14,11 +14,11 @@
package google.registry.util;
import static java.time.temporal.ChronoUnit.MILLIS;
import static org.joda.time.DateTimeZone.UTC;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
@@ -43,6 +43,6 @@ public class SystemClock implements Clock {
// (which uses millisecond precision via DateTimeConverter). This prevents subtle comparison
// bugs where a high-precision Instant would be considered "after" a truncated database
// timestamp.
return Instant.now().truncatedTo(ChronoUnit.MILLIS);
return Instant.now().truncatedTo(MILLIS);
}
}

View File

@@ -15,11 +15,11 @@
package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.DateTimeUtils.toJavaDuration;
import com.google.common.util.concurrent.Uninterruptibles;
import jakarta.inject.Inject;
import java.io.Serializable;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
@@ -41,6 +41,6 @@ public final class SystemSleeper implements Sleeper, Serializable {
@Override
public void sleepUninterruptibly(ReadableDuration duration) {
checkArgument(duration.getMillis() >= 0);
Uninterruptibles.sleepUninterruptibly(Duration.ofMillis(duration.getMillis()));
Uninterruptibles.sleepUninterruptibly(toJavaDuration(duration));
}
}

View File

@@ -89,6 +89,11 @@ public final class FakeClock implements Clock {
currentTimeMillis.addAndGet(duration.getMillis());
}
/** Advances clock by some duration. */
public void advanceBy(java.time.Duration duration) {
currentTimeMillis.addAndGet(duration.toMillis());
}
/** Sets the time to the specified instant. */
public void setTo(ReadableInstant time) {
currentTimeMillis.set(time.getMillis());

View File

@@ -628,6 +628,18 @@
}
}
},
"node_modules/@angular/build/node_modules/@types/node": {
"version": "25.6.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.6.0.tgz",
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"undici-types": "~7.19.0"
}
},
"node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz",
@@ -641,6 +653,24 @@
"vite": "^6.0.0 || ^7.0.0"
}
},
"node_modules/@angular/build/node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/build/node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -664,6 +694,22 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@angular/build/node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/build/node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
@@ -697,6 +743,15 @@
"node": ">= 12"
}
},
"node_modules/@angular/build/node_modules/undici-types": {
"version": "7.19.2",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.19.2.tgz",
"integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/@angular/build/node_modules/vite": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
@@ -916,6 +971,24 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/@angular/cli/node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/cli/node_modules/cli-spinners": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz",
@@ -1019,6 +1092,22 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@angular/cli/node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@angular/cli/node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
@@ -4606,6 +4695,24 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/@schematics/angular/node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@schematics/angular/node_modules/cli-spinners": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz",
@@ -4709,6 +4816,22 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@schematics/angular/node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@schematics/angular/node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",

View File

@@ -26,8 +26,8 @@ import google.registry.model.EppResource;
import google.registry.persistence.VKey;
import google.registry.request.Action;
import jakarta.inject.Inject;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.time.Duration;
import java.time.Instant;
/** Helper class to enqueue tasks for handling asynchronous operations in flows. */
public final class AsyncTaskEnqueuer {
@@ -41,7 +41,7 @@ public final class AsyncTaskEnqueuer {
public static final String QUEUE_ASYNC_ACTIONS = "async-actions";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Duration MAX_ASYNC_ETA = Duration.standardDays(30);
private static final Duration MAX_ASYNC_ETA = Duration.ofDays(30);
private final CloudTasksUtils cloudTasksUtils;
@@ -58,12 +58,12 @@ public final class AsyncTaskEnqueuer {
*/
public void enqueueAsyncResave(
VKey<? extends EppResource> entityKey,
DateTime now,
ImmutableSortedSet<DateTime> whenToResave) {
DateTime firstResave = whenToResave.first();
Instant now,
ImmutableSortedSet<Instant> whenToResave) {
Instant firstResave = whenToResave.first();
checkArgument(isBeforeOrAt(now, firstResave), "Can't enqueue a resave to run in the past");
Duration etaDuration = new Duration(now, firstResave);
if (etaDuration.isLongerThan(MAX_ASYNC_ETA)) {
Duration etaDuration = Duration.between(now, firstResave);
if (etaDuration.compareTo(MAX_ASYNC_ETA) > 0) {
logger.atInfo().log(
"Ignoring async re-save of %s; %s is past the ETA threshold of %s.",
entityKey, firstResave, MAX_ASYNC_ETA);

View File

@@ -24,9 +24,9 @@ import static google.registry.request.RequestParameters.extractOptionalBooleanPa
import static google.registry.request.RequestParameters.extractOptionalInstantParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredDatetimeParameter;
import static google.registry.request.RequestParameters.extractRequiredInstantParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
import static google.registry.request.RequestParameters.extractSetOfInstantParameters;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -44,7 +44,6 @@ import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import org.joda.time.DateTime;
/** Dagger module for injecting common settings for batch actions. */
@Module
@@ -98,14 +97,14 @@ public class BatchModule {
@Provides
@Parameter(PARAM_REQUESTED_TIME)
static DateTime provideRequestedTime(HttpServletRequest req) {
return extractRequiredDatetimeParameter(req, PARAM_REQUESTED_TIME);
static Instant provideRequestedTime(HttpServletRequest req) {
return extractRequiredInstantParameter(req, PARAM_REQUESTED_TIME);
}
@Provides
@Parameter(PARAM_RESAVE_TIMES)
static ImmutableSet<DateTime> provideResaveTimes(HttpServletRequest req) {
return extractSetOfDatetimeParameters(req, PARAM_RESAVE_TIMES);
static ImmutableSet<Instant> provideResaveTimes(HttpServletRequest req) {
return extractSetOfInstantParameters(req, PARAM_RESAVE_TIMES);
}
@Provides

View File

@@ -42,10 +42,10 @@ import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import org.joda.time.Duration;
/**
* An action that transfers a set of domains from one registrar to another.
@@ -158,7 +158,7 @@ public class BulkDomainTransferAction implements Runnable {
return null;
};
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
// Send a 200-series status code to prevent this conflicting action from retrying.
response.setStatus(SC_NO_CONTENT);
response.setPayload("Could not acquire lock; already running?");

View File

@@ -52,11 +52,11 @@ import jakarta.inject.Inject;
import java.io.Serial;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
import java.util.function.Supplier;
import org.joda.time.Duration;
/** Utilities for dealing with Cloud Tasks. */
public class CloudTasksUtils implements Serializable {
@@ -251,7 +251,7 @@ public class CloudTasksUtils implements Serializable {
method,
service,
params,
Duration.millis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
Duration.ofMillis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
}
/**
@@ -302,12 +302,12 @@ public class CloudTasksUtils implements Serializable {
Action.Service service,
Multimap<String, String> params,
Duration delay) {
if (delay.isEqual(Duration.ZERO)) {
if (delay.isZero()) {
return createTask(path, method, service, params);
}
checkArgument(delay.isLongerThan(Duration.ZERO), "Negative duration is not supported.");
checkArgument(!delay.isNegative(), "Negative duration is not supported.");
return Task.newBuilder(createTask(path, method, service, params))
.setScheduleTime(Timestamps.fromMillis(clock.nowUtc().plus(delay).getMillis()))
.setScheduleTime(Timestamps.fromMillis(clock.now().plus(delay).toEpochMilli()))
.build();
}

View File

@@ -42,11 +42,11 @@ import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import org.joda.time.Duration;
/**
* An action that deletes all non-renewing domains whose expiration dates have now passed.
@@ -116,7 +116,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
return null;
};
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
// Send a 200-series status code to prevent this conflicting action from retrying.
response.setStatus(SC_NO_CONTENT);
response.setPayload("Could not acquire lock; already running?");

View File

@@ -115,7 +115,7 @@ public class DeleteLoadTestDataAction implements Runnable {
VKey<Host> hostVKey = host.createVKey();
// We can remove hosts from linked domains, so we should do so then delete the hosts
ImmutableSet<VKey<Domain>> linkedDomains =
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.nowUtc(), null);
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.now(), null);
tm().loadByKeys(linkedDomains)
.values()
.forEach(

View File

@@ -218,7 +218,7 @@ public class DeleteProberDataAction implements Runnable {
// successfully soft-delete the domain (thus leaving its DNS entry published). We soft-delete
// it now so that the DNS entry can be handled. The domain will then be hard-deleted the next
// time the job is run.
if (EppResourceUtils.isActive(domain, tm().getTransactionTime())) {
if (EppResourceUtils.isActive(domain, tm().getTxTime())) {
if (isDryRun) {
logger.atInfo().log(
"Would soft-delete the active domain: %s (%s).",

View File

@@ -111,7 +111,7 @@ public class ExpandBillingRecurrencesAction implements Runnable {
() ->
tm().loadByKeyIfPresent(Cursor.createGlobalVKey(RECURRING_BILLING))
.orElse(Cursor.createGlobal(RECURRING_BILLING, START_INSTANT))
.getCursorTimeInstant()));
.getCursorTime()));
checkArgument(
startTime.isBefore(endTime),
"Start time (%s) must be before end time (%s)",

View File

@@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.toJodaDuration;
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
@@ -36,13 +38,12 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.tools.DomainLockUtils;
import google.registry.util.DateTimeUtils;
import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.util.Optional;
import org.joda.time.Duration;
/** Task that re-locks a previously-Registry-Locked domain after a predetermined period of time. */
@Action(
@@ -59,8 +60,8 @@ public class RelockDomainAction implements Runnable {
static final int ATTEMPTS_BEFORE_SLOWDOWN = 36; // every ten minutes for six hours then every hour
static final int FAILURES_BEFORE_EMAIL = 2; // email after three failures, one half hour
private static final Duration TEN_MINUTES = Duration.standardMinutes(10);
private static final Duration ONE_HOUR = Duration.standardHours(1);
private static final Duration TEN_MINUTES = Duration.ofMinutes(10);
private static final Duration ONE_HOUR = Duration.ofHours(1);
private static final String RELOCK_SUCCESS_EMAIL_TEMPLATE =
"""
@@ -188,7 +189,7 @@ public class RelockDomainAction implements Runnable {
"Domain %s has a pending delete.",
domainName);
checkArgument(
!DateTimeUtils.isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
!isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
"Domain %s has been deleted.",
domainName);
checkArgument(
@@ -237,7 +238,8 @@ public class RelockDomainAction implements Runnable {
}
}
Duration timeBeforeRetry = previousAttempts < ATTEMPTS_BEFORE_SLOWDOWN ? TEN_MINUTES : ONE_HOUR;
domainLockUtils.enqueueDomainRelock(timeBeforeRetry, oldUnlockRevisionId, previousAttempts + 1);
domainLockUtils.enqueueDomainRelock(
toJodaDuration(timeBeforeRetry), oldUnlockRevisionId, previousAttempts + 1);
}
private void sendSuccessEmail(RegistryLock oldLock) {

View File

@@ -30,8 +30,8 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
/**
* An action that re-saves a given entity, typically after a certain amount of time has passed.
@@ -50,16 +50,16 @@ public class ResaveEntityAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final String resourceKey;
private final DateTime requestedTime;
private final ImmutableSortedSet<DateTime> resaveTimes;
private final Instant requestedTime;
private final ImmutableSortedSet<Instant> resaveTimes;
private final AsyncTaskEnqueuer asyncTaskEnqueuer;
private final Response response;
@Inject
ResaveEntityAction(
@Parameter(PARAM_RESOURCE_KEY) String resourceKey,
@Parameter(PARAM_REQUESTED_TIME) DateTime requestedTime,
@Parameter(PARAM_RESAVE_TIMES) ImmutableSet<DateTime> resaveTimes,
@Parameter(PARAM_REQUESTED_TIME) Instant requestedTime,
@Parameter(PARAM_RESAVE_TIMES) ImmutableSet<Instant> resaveTimes,
AsyncTaskEnqueuer asyncTaskEnqueuer,
Response response) {
this.resourceKey = resourceKey;

View File

@@ -17,8 +17,8 @@ package google.registry.batch;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.time.ZoneOffset.UTC;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_OK;
@@ -43,11 +43,10 @@ import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/** An action that sends notification emails to registrars whose certificates are expiring soon. */
@Action(
@@ -57,6 +56,7 @@ import org.joda.time.format.DateTimeFormatter;
public class SendExpiringCertificateNotificationEmailAction implements Runnable {
public static final String PATH = "/_dr/task/sendExpiringCertificateNotificationEmail";
/**
* Used as an offset when storing the last notification email sent date.
*
@@ -65,10 +65,11 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
* next day at 2am, the date difference will be less than a day, which will lead to the date
* difference between two successive email sent date being the expected email interval days + 1;
*/
protected static final Duration UPDATE_TIME_OFFSET = Duration.standardMinutes(10);
protected static final Duration UPDATE_TIME_OFFSET = Duration.ofMinutes(10);
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(UTC);
private final CertificateChecker certificateChecker;
private final String expirationWarningEmailBodyText;
@@ -149,19 +150,19 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@VisibleForTesting
boolean sendNotificationEmail(
Registrar registrar,
DateTime lastExpiringCertNotificationSentDate,
Instant lastExpiringCertNotificationSentDate,
CertificateType certificateType,
Optional<String> certificate) {
if (certificate.isEmpty()
|| !certificateChecker.shouldReceiveExpiringNotification(
lastExpiringCertNotificationSentDate, certificate.get())) {
toDateTime(lastExpiringCertNotificationSentDate), certificate.get())) {
return false;
}
try {
ImmutableSet<InternetAddress> recipients = getEmailAddresses(registrar, Type.TECH);
ImmutableSet<InternetAddress> ccs = getEmailAddresses(registrar, Type.ADMIN);
DateTime expirationDate =
new DateTime(certificateChecker.getCertificate(certificate.get()).getNotAfter());
Instant expirationDate =
certificateChecker.getCertificate(certificate.get()).getNotAfter().toInstant();
logger.atInfo().log(
" %s SSL certificate of registrar '%s' will expire on %s.",
certificateType.getDisplayName(), registrar.getRegistrarName(), expirationDate);
@@ -190,9 +191,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
* for applicable certificate.
*/
updateLastNotificationSentDate(
registrar,
clock.nowUtc().minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
certificateType);
registrar, clock.now().minus(UPDATE_TIME_OFFSET), certificateType);
return true;
} catch (Exception e) {
throw new RuntimeException(
@@ -205,29 +204,29 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
/** Updates the last notification sent date in database. */
@VisibleForTesting
void updateLastNotificationSentDate(
Registrar registrar, DateTime now, CertificateType certificateType) {
Registrar registrar, Instant now, CertificateType certificateType) {
try {
tm().transact(
() -> {
Registrar.Builder newRegistrar = tm().loadByEntity(registrar).asBuilder();
switch (certificateType) {
case PRIMARY -> {
newRegistrar.setLastExpiringCertNotificationSentDate(toInstant(now));
newRegistrar.setLastExpiringCertNotificationSentDate(now);
tm().put(newRegistrar.build());
logger.atInfo().log(
"Updated last notification email sent date to %s for %s certificate of "
+ "registrar %s.",
DATE_FORMATTER.print(now),
DATE_FORMATTER.format(now),
certificateType.getDisplayName(),
registrar.getRegistrarName());
}
case FAILOVER -> {
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(toInstant(now));
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(now);
tm().put(newRegistrar.build());
logger.atInfo().log(
"Updated last notification email sent date to %s for %s certificate of "
+ "registrar %s.",
DATE_FORMATTER.print(now),
DATE_FORMATTER.format(now),
certificateType.getDisplayName(),
registrar.getRegistrarName());
}
@@ -257,7 +256,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
if (registrarInfo.isCertExpiring()
&& sendNotificationEmail(
registrar,
toDateTime(registrar.getLastExpiringCertNotificationSentDate()),
registrar.getLastExpiringCertNotificationSentDate(),
CertificateType.PRIMARY,
registrar.getClientCertificate())) {
numEmailsSent++;
@@ -265,7 +264,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
if (registrarInfo.isFailOverCertExpiring()
&& sendNotificationEmail(
registrar,
toDateTime(registrar.getLastExpiringFailoverCertNotificationSentDate()),
registrar.getLastExpiringFailoverCertNotificationSentDate(),
CertificateType.FAILOVER,
registrar.getFailoverClientCertificate())) {
numEmailsSent++;
@@ -300,7 +299,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@VisibleForTesting
@SuppressWarnings("lgtm[java/dereferenced-value-may-be-null]")
String getEmailBody(
String registrarName, CertificateType type, DateTime expirationDate, String registrarId) {
String registrarName, CertificateType type, Instant expirationDate, String registrarId) {
checkArgumentNotNull(expirationDate, "Expiration date cannot be null");
checkArgumentNotNull(type, "Certificate type cannot be null");
checkArgumentNotNull(registrarId, "Registrar Id cannot be null");
@@ -308,7 +307,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
expirationWarningEmailBodyText,
registrarName,
type.getDisplayName(),
DATE_FORMATTER.print(expirationDate),
DATE_FORMATTER.format(expirationDate),
registrarId);
}

View File

@@ -40,12 +40,12 @@ import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.Function;
import org.joda.time.Duration;
@Action(
service = Action.Service.BACKEND,
@@ -99,7 +99,7 @@ public class SyncRemoteCacheAction implements Runnable {
return null;
};
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
// Send a 200-series status code to prevent this conflicting action from retrying.
response.setStatus(SC_NO_CONTENT);
response.setPayload("Could not acquire lock; already running?");
@@ -184,7 +184,7 @@ public class SyncRemoteCacheAction implements Runnable {
private Instant getPreviousCursorTime(Cursor.CursorType cursorType) {
return tm().loadByKeyIfPresent(Cursor.createGlobalVKey(cursorType))
.map(Cursor::getCursorTimeInstant)
.map(Cursor::getCursorTime)
.orElse(START_INSTANT);
}

View File

@@ -15,6 +15,7 @@
package google.registry.beam;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.DateTimeUtils.LOWERCASE_TIMESTAMP_FORMATTER;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -61,7 +62,7 @@ public class BeamUtils {
// with a letter and ending with a letter or number. So we replace the "T" and "Z" in ISO 8601
// with lowercase letters.
String jobName =
String.format("%s-%s", prefix, clock.nowUtc().toString("yyyy-MM-dd't'HH-mm-ss'z'"));
String.format("%s-%s", prefix, LOWERCASE_TIMESTAMP_FORMATTER.format(clock.now()));
checkArgument(
Pattern.compile("^[a-z][-a-z0-9]*[a-z0-9]*").matcher(jobName).matches(),
"The job name %s is illegal, it consists of only characters [-a-z0-9], "

View File

@@ -14,6 +14,7 @@
package google.registry.beam.billing;
import static java.time.ZoneOffset.UTC;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -22,7 +23,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;
@@ -70,7 +70,7 @@ public record BillingEvent(
String flags) {
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'UTC'").withZone(ZoneOffset.UTC);
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'UTC'").withZone(UTC);
private static final Pattern SYNTHETIC_REGEX = Pattern.compile("SYNTHETIC", Pattern.LITERAL);
@@ -164,13 +164,10 @@ public record BillingEvent(
/** Returns the grouping key for this {@code BillingEvent}, to generate the overall invoice. */
InvoiceGroupingKey getInvoiceGroupingKey() {
return new InvoiceGroupingKey(
ZonedDateTime.ofInstant(billingTime(), ZoneOffset.UTC)
.toLocalDate()
.withDayOfMonth(1)
.toString(),
ZonedDateTime.ofInstant(billingTime(), UTC).toLocalDate().withDayOfMonth(1).toString(),
years() == 0
? ""
: ZonedDateTime.ofInstant(billingTime(), ZoneOffset.UTC)
: ZonedDateTime.ofInstant(billingTime(), UTC)
.toLocalDate()
.withDayOfMonth(1)
.plusYears(years())

View File

@@ -445,7 +445,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
Cursor.createGlobalVKey(RECURRING_BILLING))
.orElse(
Cursor.createGlobal(RECURRING_BILLING, START_INSTANT))
.getCursorTimeInstant();
.getCursorTime();
if (!currentCursorTime.equals(startTime)) {
throw new IllegalStateException(
String.format(

View File

@@ -56,6 +56,8 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.security.Security;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.transforms.DoFn;
@@ -66,8 +68,6 @@ import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.PDone;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
import org.joda.time.Duration;
public class RdeIO {
@@ -163,7 +163,7 @@ public class RdeIO {
// Determine some basic things about the deposit.
final RdeMode mode = key.mode();
final String tld = key.tld();
final DateTime watermark = key.watermark();
final Instant watermark = key.watermark();
final int revision =
Optional.ofNullable(key.revision())
.orElseGet(() -> RdeRevision.getNextRevision(tld, watermark, mode));
@@ -259,7 +259,7 @@ public class RdeIO {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final long serialVersionUID = 5822176227753327224L;
private static final Duration ENQUEUE_DELAY = Duration.standardMinutes(1);
private static final Duration ENQUEUE_DELAY = Duration.ofMinutes(1);
private final CloudTasksUtils cloudTasksUtils;
@@ -276,9 +276,9 @@ public class RdeIO {
Tld tld = Tld.get(key.tld());
Optional<Cursor> cursor =
tm().loadByKeyIfPresent(Cursor.createScopedVKey(key.cursor(), tld));
DateTime position = getCursorTimeOrStartOfTime(cursor);
Instant position = getCursorTimeOrStartOfTime(cursor);
checkState(key.interval() != null, "Interval must be present");
DateTime newPosition = key.watermark().plus(key.interval());
Instant newPosition = key.watermark().plus(key.interval());
if (!position.isBefore(newPosition)) {
logger.atWarning().log("Cursor has already been rolled forward.");
return;

View File

@@ -27,7 +27,6 @@ import static google.registry.beam.rde.RdePipeline.TupleTags.REVISION_ID;
import static google.registry.beam.rde.RdePipeline.TupleTags.SUPERORDINATE_DOMAINS;
import static google.registry.model.reporting.HistoryEntryDao.RESOURCE_TYPES_TO_HISTORY_TYPES;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toInstant;
import static google.registry.util.SafeSerializationUtils.safeDeserializeCollection;
import static google.registry.util.SafeSerializationUtils.serializeCollection;
import static google.registry.util.SerializeUtils.decodeBase64;
@@ -72,6 +71,7 @@ import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.coders.KvCoder;
@@ -97,7 +97,6 @@ import org.apache.beam.sdk.values.PCollectionTuple;
import org.apache.beam.sdk.values.TupleTag;
import org.apache.beam.sdk.values.TupleTagList;
import org.apache.beam.sdk.values.TypeDescriptor;
import org.joda.time.DateTime;
/**
* Definition of a Dataflow Flex template, which generates RDE/BRDA deposits.
@@ -171,7 +170,7 @@ public class RdePipeline implements Serializable {
private final transient RdePipelineOptions options;
private final ValidationMode mode;
private final ImmutableSet<PendingDeposit> pendingDeposits;
private final DateTime watermark;
private final Instant watermark;
private final String rdeBucket;
private final byte[] stagingKeyBytes;
private final GcsUtils gcsUtils;
@@ -190,7 +189,7 @@ public class RdePipeline implements Serializable {
this.options = options;
this.mode = ValidationMode.valueOf(options.getValidationMode());
this.pendingDeposits = decodePendingDeposits(options.getPendings());
ImmutableSet<DateTime> potentialWatermarks =
ImmutableSet<Instant> potentialWatermarks =
pendingDeposits.stream()
.map(PendingDeposit::watermark)
.distinct()
@@ -324,7 +323,7 @@ public class RdePipeline implements Serializable {
? "AND resource.tld IN " + "(SELECT id FROM Tld WHERE tldType = 'REAL')"
: ""))
.replace("%entity%", historyClass.getSimpleName()),
ImmutableMap.of("watermark", toInstant(watermark)),
ImmutableMap.of("watermark", watermark),
Object[].class,
row -> KV.of((String) row[0], (long) row[1]))
.withCoder(KvCoder.of(StringUtf8Coder.of(), VarLongCoder.of())));
@@ -365,7 +364,7 @@ public class RdePipeline implements Serializable {
tm().loadByKey(
VKey.create(historyEntryClazz, new HistoryEntryId(repoId, revisionId))))
.getResourceAtPointInTime()
.map(resource -> resource.cloneProjectedAtTime(toInstant(watermark)))
.map(resource -> resource.cloneProjectedAtTime(watermark))
.get();
}

View File

@@ -103,7 +103,7 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
* transfers, grace periods).
*
* <p>The logic of what might have changed is paraphrased from {@link
* DomainBase#cloneProjectedAtTime(DateTime)}.
* DomainBase#cloneProjectedAtTime(Instant)}.
*/
private void fastResaveDomains(Pipeline pipeline) {
Read<String, String> repoIdRead =

View File

@@ -14,6 +14,7 @@
package google.registry.beam.spec11;
import static google.registry.util.DateTimeUtils.toJodaInstant;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.http.HttpStatus.SC_OK;
@@ -22,7 +23,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.CharStreams;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import google.registry.util.Retrier;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -132,9 +132,7 @@ public class SafeBrowsingTransforms {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach(
(kv) ->
context.output(
kv, DateTimeUtils.toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
(kv) -> context.output(kv, toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
}
}

View File

@@ -64,19 +64,19 @@ import google.registry.util.SqlTemplate;
import google.registry.util.SystemSleeper;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Duration;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
import org.joda.time.Duration;
/** Class encapsulating parameters and state for accessing the Bigquery API. */
public class BigqueryConnection implements AutoCloseable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final Duration MIN_POLL_INTERVAL = Duration.millis(500);
private static final Duration MIN_POLL_INTERVAL = Duration.ofMillis(500);
@NonFinalForTesting
private static Sleeper sleeper = new SystemSleeper();
@@ -88,7 +88,7 @@ public class BigqueryConnection implements AutoCloseable {
private static final String TEMP_DATASET_NAME = "__temp__";
/** Default time to live for temporary tables. */
private static final Duration TEMP_TABLE_TTL = Duration.standardHours(24);
private static final Duration TEMP_TABLE_TTL = Duration.ofHours(24);
/** Bigquery client instance wrapped by this class. */
private final Bigquery bigquery;
@@ -109,7 +109,7 @@ public class BigqueryConnection implements AutoCloseable {
private boolean overwrite = false;
/** Duration to wait between polls for job status. */
private Duration pollInterval = Duration.millis(1000);
private Duration pollInterval = Duration.ofSeconds(1);
BigqueryConnection(Bigquery bigquery, Clock clock) {
this.bigquery = bigquery;
@@ -146,9 +146,9 @@ public class BigqueryConnection implements AutoCloseable {
public Builder setPollInterval(Duration pollInterval) {
checkArgument(
!pollInterval.isShorterThan(MIN_POLL_INTERVAL),
pollInterval.compareTo(MIN_POLL_INTERVAL) >= 0,
"poll interval must be at least %s ms",
MIN_POLL_INTERVAL.getMillis());
MIN_POLL_INTERVAL.toMillis());
instance.pollInterval = pollInterval;
return this;
}
@@ -225,7 +225,7 @@ public class BigqueryConnection implements AutoCloseable {
}
public Builder timeToLive(Duration duration) {
this.table.setExpirationTime(clock.nowUtc().plus(duration).getMillis());
this.table.setExpirationTime(clock.now().plus(duration).toEpochMilli());
return this;
}

View File

@@ -14,13 +14,16 @@
package google.registry.bigquery;
import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoUnit.MICROS;
import com.google.api.services.bigquery.model.JobReference;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.joda.time.format.ISODateTimeFormat;
/** Utilities related to Bigquery. */
public class BigqueryUtils {
@@ -67,47 +70,56 @@ public class BigqueryUtils {
*
* <p>The general format definition is "YYYY-MM-DD HH:MM:SS.SSS[ ZZ]", where the fractional
* seconds portion can have 0-6 decimal places (although we restrict it to 0-3 here since Joda
* DateTime only supports up to millisecond precision) and the zone if not specified defaults to
* Instant only supports up to millisecond precision) and the zone if not specified defaults to
* UTC.
*
* <p>Although we expect a zone specification of "UTC" when parsing, we don't emit it when
* printing because in some cases BigQuery does not allow any time zone specification (instead it
* assumes UTC for whatever input you provide) for input timestamp strings (see b/16380363).
*
* @see <a href="https://cloud.google.com/bigquery/data-types#timestamp-type">
* BigQuery Data Types - TIMESTAMP</a>
* @see <a href="https://cloud.google.com/bigquery/data-types#timestamp-type">BigQuery Data Types
* - TIMESTAMP</a>
*/
public static final DateTimeFormatter BIGQUERY_TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
.append(ISODateTimeFormat.date())
.appendLiteral(' ')
.append(
// For printing, always print out the milliseconds.
ISODateTimeFormat.hourMinuteSecondMillis().getPrinter(),
// For parsing, we need a series of parsers to correctly handle the milliseconds.
new DateTimeParser[] {
// Try to parse the time with milliseconds first, which requires at least one
// fractional second digit, and if that fails try to parse without milliseconds.
ISODateTimeFormat.hourMinuteSecondMillis().getParser(),
ISODateTimeFormat.hourMinuteSecond().getParser()})
// Print UTC as the empty string since BigQuery's TIMESTAMP() function does not accept any
// time zone specification, but require "UTC" on parsing. Since we force this formatter to
// always use UTC below, the other arguments do not matter. If b/16380363 ever gets resolved
// this could be simplified to appendLiteral(" UTC").
.appendTimeZoneOffset("", " UTC", false, 1, 1)
.toFormatter()
.withZoneUTC();
private static final DateTimeFormatter BIGQUERY_TIMESTAMP_PARSER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendLiteral(' ')
.appendPattern("HH:mm:ss")
.optionalStart()
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
.optionalEnd()
.appendLiteral(" UTC")
.toFormatter()
.withZone(UTC);
private static final DateTimeFormatter BIGQUERY_TIMESTAMP_PRINTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendLiteral(' ')
.appendPattern("HH:mm:ss")
.appendFraction(ChronoField.MILLI_OF_SECOND, 3, 3, true)
.toFormatter()
.withZone(UTC);
/**
* Returns the human-readable string version of the given DateTime, suitable for conversion
* within BigQuery from a string literal into a BigQuery timestamp type.
* Returns the human-readable string version of the given Instant, suitable for conversion within
* BigQuery from a string literal into a BigQuery timestamp type.
*/
public static String toBigqueryTimestampString(DateTime dateTime) {
return BIGQUERY_TIMESTAMP_FORMAT.print(dateTime);
public static String toBigqueryTimestampString(Instant dateTime) {
return BIGQUERY_TIMESTAMP_PRINTER.format(dateTime);
}
/** Returns the DateTime for a given human-readable string-formatted BigQuery timestamp. */
public static DateTime fromBigqueryTimestampString(String timestampString) {
return BIGQUERY_TIMESTAMP_FORMAT.parseDateTime(timestampString);
/** Returns the Instant for a given human-readable string-formatted BigQuery timestamp. */
public static Instant fromBigqueryTimestampString(String timestampString) {
return BIGQUERY_TIMESTAMP_PARSER.parse(timestampString, Instant::from);
}
/**
@@ -123,15 +135,16 @@ public class BigqueryUtils {
}
/**
* Converts a {@link DateTime} into a numeric string that BigQuery understands as a timestamp:
* the decimal number of seconds since the epoch, precise up to microseconds.
* Converts a time into a numeric string that BigQuery understands as a timestamp: the decimal
* number of seconds since the epoch, precise up to microseconds.
*
* <p>Note that since {@code DateTime} only stores milliseconds, the last 3 digits will be zero.
* <p>Note that while {@code Instant} supports nanosecond precision, BigQuery only supports
* microsecond precision, so the sub-microsecond precision is truncated.
*
* @see <a href="https://developers.google.com/bigquery/timestamp">Data Types</a>
*/
public static String toBigqueryTimestamp(DateTime dateTime) {
return toBigqueryTimestamp(dateTime.getMillis(), TimeUnit.MILLISECONDS);
public static String toBigqueryTimestamp(Instant dateTime) {
return toBigqueryTimestamp(MICROS.between(Instant.EPOCH, dateTime), TimeUnit.MICROSECONDS);
}
/**

View File

@@ -116,7 +116,7 @@ public class BsaDownloadAction implements Runnable {
Void runWithinLock() {
// Cannot enroll new TLDs after download starts. This may change if b/309175410 is fixed.
if (!Tlds.hasActiveBsaEnrollment(clock.nowUtc())) {
if (!Tlds.hasActiveBsaEnrollment(clock.now())) {
logger.atInfo().log("No TLDs enrolled with BSA. Quitting.");
return null;
}
@@ -179,9 +179,7 @@ public class BsaDownloadAction implements Runnable {
gcsClient.writeUnblockableDomains(
schedule.jobName(),
batches
.map(
batch ->
applyLabelDiff(batch, lazyIdnChecker.get(), schedule, clock.nowUtc()))
.map(batch -> applyLabelDiff(batch, lazyIdnChecker.get(), schedule, clock.now()))
.flatMap(ImmutableList::stream));
}
schedule.updateJobStage(DownloadStage.REPORT_START_OF_ORDER_PROCESSING);

View File

@@ -17,8 +17,8 @@ package google.registry.bsa;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.lock.LockHandler;
import jakarta.inject.Inject;
import java.time.Duration;
import java.util.concurrent.Callable;
import org.joda.time.Duration;
/** Helper for guarding all BSA related work with a common lock. */
public class BsaLock {

View File

@@ -67,7 +67,7 @@ public class BsaRefreshAction implements Runnable {
GcsClient gcsClient,
BsaReportSender bsaReportSender,
@Config("bsaTxnBatchSize") int transactionBatchSize,
@Config("domainCreateTxnCommitTimeLag") org.joda.time.Duration domainCreateTxnCommitTimeLag,
@Config("domainCreateTxnCommitTimeLag") Duration domainCreateTxnCommitTimeLag,
BsaEmailSender emailSender,
BsaLock bsaLock,
Clock clock,
@@ -76,7 +76,7 @@ public class BsaRefreshAction implements Runnable {
this.gcsClient = gcsClient;
this.bsaReportSender = bsaReportSender;
this.transactionBatchSize = transactionBatchSize;
this.domainCreateTxnCommitTimeLag = Duration.ofMillis(domainCreateTxnCommitTimeLag.getMillis());
this.domainCreateTxnCommitTimeLag = domainCreateTxnCommitTimeLag;
this.emailSender = emailSender;
this.bsaLock = bsaLock;
this.clock = clock;

View File

@@ -88,14 +88,14 @@ public class BsaValidateAction implements Runnable {
IdnChecker idnChecker,
BsaEmailSender emailSender,
@Config("bsaTxnBatchSize") int transactionBatchSize,
@Config("bsaValidationMaxStaleness") org.joda.time.Duration maxStaleness,
@Config("bsaValidationMaxStaleness") Duration maxStaleness,
Clock clock,
Response response) {
this.gcsClient = gcsClient;
this.idnChecker = idnChecker;
this.emailSender = emailSender;
this.transactionBatchSize = transactionBatchSize;
this.maxStaleness = Duration.ofMillis(maxStaleness.getMillis());
this.maxStaleness = maxStaleness;
this.clock = clock;
this.response = response;
}

View File

@@ -29,7 +29,7 @@ import google.registry.tldconfig.idn.IdnLabelValidator;
import google.registry.tldconfig.idn.IdnTableEnum;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import org.joda.time.DateTime;
import java.time.Instant;
/**
* Checks labels' validity wrt Idns in TLDs enrolled with BSA.
@@ -45,7 +45,7 @@ public class IdnChecker {
@Inject
IdnChecker(Clock clock) {
this.idnToTlds = getIdnToTldMap(clock.nowUtc());
this.idnToTlds = getIdnToTldMap(clock.now());
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
}
@@ -79,7 +79,7 @@ public class IdnChecker {
return Sets.difference(allTlds, getSupportingTlds(idnTables)).immutableCopy();
}
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(DateTime now) {
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(Instant now) {
var idnToTldMap = new ImmutableMultimap.Builder<IdnTableEnum, Tld>();
Tlds.getTldEntitiesOfType(TldType.REAL).stream()
.filter(tld -> isEnrolledWithBsa(tld, now))

View File

@@ -20,7 +20,6 @@ import static google.registry.bsa.BsaStringUtils.DOMAIN_JOINER;
import static google.registry.flows.domain.DomainFlowUtils.isReserved;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.label.ReservedList.loadReservedLists;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
@@ -35,7 +34,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.joda.time.DateTime;
/**
* Utility for looking up reserved domain names.
@@ -47,15 +45,6 @@ public final class ReservedDomainsUtils {
private ReservedDomainsUtils() {}
/**
* @deprecated Use {@link #getAllReservedNames(Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static Stream<String> getAllReservedNames(DateTime now) {
return getAllReservedNames(toInstant(now));
}
public static Stream<String> getAllReservedNames(Instant now) {
return Tlds.getTldEntitiesOfType(TldType.REAL).stream()
.filter(tld -> Tld.isEnrolledWithBsa(tld, now))
@@ -74,15 +63,6 @@ public final class ReservedDomainsUtils {
.collect(toImmutableSet());
}
/**
* @deprecated Use {@link #getAllReservedDomainsInTld(Tld, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
static ImmutableSet<String> getAllReservedDomainsInTld(Tld tld, DateTime now) {
return getAllReservedDomainsInTld(tld, toInstant(now));
}
/**
* Returns true if {@code domain} is a reserved name that can be registered right now (e.g.,
* during sunrise or with allocation token), therefore unblockable.
@@ -95,13 +75,4 @@ public final class ReservedDomainsUtils {
InternetDomainName.from(domain),
Objects.equals(tld.getTldState(now), TldState.START_DATE_SUNRISE));
}
/**
* @deprecated Use {@link #isReservedDomain(String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static boolean isReservedDomain(String domain, DateTime now) {
return isReservedDomain(domain, toInstant(now));
}
}

View File

@@ -31,12 +31,12 @@ import jakarta.inject.Inject;
import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.net.ssl.HttpsURLConnection;
import org.joda.time.Duration;
import org.joda.time.Instant;
/**
* A credential for accessing the BSA API.
@@ -104,7 +104,7 @@ public class BsaCredential {
}
private void ensureAuthTokenValid() throws IOException, GeneralSecurityException {
Instant now = Instant.ofEpochMilli(clock.nowUtc().getMillis());
Instant now = clock.now();
if (authToken != null && lastRefreshTime.plus(authTokenExpiry).isAfter(now)) {
logger.atInfo().log("AuthToken still valid, reusing.");
return;

View File

@@ -20,7 +20,6 @@ import static google.registry.bsa.DownloadStage.DONE;
import static google.registry.bsa.DownloadStage.NOP;
import static google.registry.bsa.persistence.RefreshScheduler.fetchMostRecentRefresh;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static org.joda.time.Duration.standardSeconds;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -28,9 +27,9 @@ import google.registry.bsa.persistence.DownloadSchedule.CompletedJob;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.util.Objects;
import java.util.Optional;
import org.joda.time.Duration;
/**
* Assigns work for each cron invocation of the BSA Download job.
@@ -57,7 +56,7 @@ import org.joda.time.Duration;
public final class DownloadScheduler {
/** Allows a new download to proceed if the cron job fires a little early due to NTP drift. */
private static final Duration CRON_JITTER = standardSeconds(5);
private static final Duration CRON_JITTER = Duration.ofSeconds(5);
private final Duration downloadInterval;
private final Duration maxNopInterval;
@@ -117,8 +116,8 @@ public final class DownloadScheduler {
private boolean isTimeAgain(BsaDownload mostRecent, Duration interval) {
return mostRecent
.getCreationTime()
.plusMillis(interval.getMillis())
.minusMillis(CRON_JITTER.getMillis())
.plusMillis(interval.toMillis())
.minusMillis(CRON_JITTER.toMillis())
.isBefore(clock.now());
}

View File

@@ -37,9 +37,9 @@ import google.registry.bsa.api.UnblockableDomain.Reason;
import google.registry.model.ForeignKeyUtils;
import google.registry.model.domain.Domain;
import google.registry.model.tld.Tld;
import java.time.Instant;
import java.util.Map;
import java.util.stream.Stream;
import org.joda.time.DateTime;
/** Applies the BSA label diffs from the latest BSA download. */
public final class LabelDiffUpdates {
@@ -60,7 +60,7 @@ public final class LabelDiffUpdates {
ImmutableList<BlockLabel> labels,
IdnChecker idnChecker,
DownloadSchedule schedule,
DateTime now) {
Instant now) {
ImmutableList.Builder<UnblockableDomain> nonBlockedDomains = new ImmutableList.Builder<>();
ImmutableMap<LabelType, ImmutableList<BlockLabel>> labelsByType =
ImmutableMap.copyOf(
@@ -134,7 +134,7 @@ public final class LabelDiffUpdates {
}
static ImmutableList<UnblockableDomain> tallyUnblockableDomainsForNewLabels(
ImmutableList<BlockLabel> labels, IdnChecker idnChecker, DateTime now) {
ImmutableList<BlockLabel> labels, IdnChecker idnChecker, Instant now) {
ImmutableList.Builder<UnblockableDomain> nonBlockedDomains = new ImmutableList.Builder<>();
for (BlockLabel label : labels) {

View File

@@ -225,7 +225,7 @@ public final class RegistryConfig {
*/
@Provides
@Config("databaseRetention")
public static Duration provideDatabaseRetention() {
public static java.time.Duration provideDatabaseRetention() {
return getDatabaseRetention();
}
@@ -281,8 +281,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("brdaInterval")
public static Duration provideBrdaInterval() {
return Duration.standardDays(7);
public static java.time.Duration provideBrdaInterval() {
return java.time.Duration.ofDays(7);
}
/**
@@ -315,8 +315,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("publishDnsUpdatesLockDuration")
public static Duration providePublishDnsUpdatesLockDuration() {
return Duration.standardMinutes(3);
public static java.time.Duration providePublishDnsUpdatesLockDuration() {
return java.time.Duration.ofMinutes(3);
}
/**
@@ -343,8 +343,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("readDnsRefreshRequestsActionRuntime")
public static Duration provideReadDnsRefreshRequestsRuntime() {
return Duration.standardSeconds(45);
public static java.time.Duration provideReadDnsRefreshRequestsRuntime() {
return java.time.Duration.ofSeconds(45);
}
/**
@@ -354,8 +354,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultATtl")
public static Duration provideDnsDefaultATtl() {
return Duration.standardHours(1);
public static java.time.Duration provideDnsDefaultATtl() {
return java.time.Duration.ofHours(1);
}
/**
@@ -365,8 +365,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultNsTtl")
public static Duration provideDnsDefaultNsTtl() {
return Duration.standardHours(3);
public static java.time.Duration provideDnsDefaultNsTtl() {
return java.time.Duration.ofHours(3);
}
/**
@@ -376,8 +376,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultDsTtl")
public static Duration provideDnsDefaultDsTtl() {
return Duration.standardHours(1);
public static java.time.Duration provideDnsDefaultDsTtl() {
return java.time.Duration.ofHours(1);
}
@Provides
@@ -757,8 +757,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeInterval")
public static Duration provideRdeInterval() {
return Duration.standardDays(1);
public static java.time.Duration provideRdeInterval() {
return java.time.Duration.ofDays(1);
}
/**
@@ -768,8 +768,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeReportLockTimeout")
public static Duration provideRdeReportLockTimeout() {
return Duration.standardMinutes(1);
public static java.time.Duration provideRdeReportLockTimeout() {
return java.time.Duration.ofMinutes(1);
}
/**
@@ -792,8 +792,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeUploadLockTimeout")
public static Duration provideRdeUploadLockTimeout() {
return Duration.standardMinutes(30);
public static java.time.Duration provideRdeUploadLockTimeout() {
return java.time.Duration.ofMinutes(30);
}
/**
@@ -805,8 +805,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeUploadSftpCooldown")
public static Duration provideRdeUploadSftpCooldown() {
return Duration.standardHours(2);
public static java.time.Duration provideRdeUploadSftpCooldown() {
return java.time.Duration.ofHours(2);
}
/**
@@ -841,8 +841,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("sheetLockTimeout")
public static Duration provideSheetLockTimeout() {
return Duration.standardHours(1);
public static java.time.Duration provideSheetLockTimeout() {
return java.time.Duration.ofHours(1);
}
/**
@@ -865,8 +865,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("emailThrottleDuration")
public static Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
return Duration.standardSeconds(config.misc.emailThrottleSeconds);
public static java.time.Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.misc.emailThrottleSeconds);
}
/**
@@ -946,8 +946,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("sshTimeout")
public static Duration provideSshTimeout() {
return Duration.standardSeconds(30);
public static java.time.Duration provideSshTimeout() {
return java.time.Duration.ofSeconds(30);
}
/**
@@ -957,8 +957,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("transactionCooldown")
public static Duration provideTransactionCooldown() {
return Duration.standardMinutes(5);
public static java.time.Duration provideTransactionCooldown() {
return java.time.Duration.ofMinutes(5);
}
/**
@@ -1327,15 +1327,15 @@ public final class RegistryConfig {
@Provides
@Config("bsaLockLeaseExpiry")
public static Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
return Duration.standardMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
public static java.time.Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
return java.time.Duration.ofMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
}
/** Returns the desired interval between successive BSA downloads. */
@Provides
@Config("bsaDownloadInterval")
public static Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
return Duration.standardMinutes(config.bsa.bsaDownloadIntervalMinutes);
public static java.time.Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
return java.time.Duration.ofMinutes(config.bsa.bsaDownloadIntervalMinutes);
}
/**
@@ -1344,8 +1344,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("bsaMaxNopInterval")
public static Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
return Duration.standardHours(config.bsa.bsaMaxNopIntervalHours);
public static java.time.Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
return java.time.Duration.ofHours(config.bsa.bsaMaxNopIntervalHours);
}
@Provides
@@ -1356,14 +1356,16 @@ public final class RegistryConfig {
@Provides
@Config("domainCreateTxnCommitTimeLag")
public static Duration provideDomainCreateTxnCommitTimeLag(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
public static java.time.Duration provideDomainCreateTxnCommitTimeLag(
RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
}
@Provides
@Config("bsaValidationMaxStaleness")
public static Duration provideBsaValidationMaxStaleness(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
public static java.time.Duration provideBsaValidationMaxStaleness(
RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
}
@Provides
@@ -1374,8 +1376,8 @@ public final class RegistryConfig {
@Provides
@Config("bsaAuthTokenExpiry")
public static Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.authTokenExpirySeconds);
public static java.time.Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.authTokenExpirySeconds);
}
@Provides
@@ -1488,8 +1490,8 @@ public final class RegistryConfig {
*
* @see google.registry.tools.server.GenerateZoneFilesAction
*/
public static Duration getDatabaseRetention() {
return Duration.standardDays(30);
public static java.time.Duration getDatabaseRetention() {
return java.time.Duration.ofDays(30);
}
public static boolean areServersLocal() {

View File

@@ -26,7 +26,7 @@ import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import org.joda.time.Duration;
import java.time.Duration;
/** DNS instrumentation. */
// TODO(b/67947699):Once load testing is done, revisit these to rename them and delete the ones that
@@ -239,15 +239,15 @@ public class DnsMetrics {
int batchSize = numberOfDomains + numberOfHosts;
processingTimePerCommitDist.record(
processingDuration.getMillis(), tld, status.name(), dnsWriter);
processingDuration.toMillis(), tld, status.name(), dnsWriter);
processingTimePerItemDist.record(
processingDuration.getMillis(), batchSize, tld, status.name(), dnsWriter);
processingDuration.toMillis(), batchSize, tld, status.name(), dnsWriter);
if (batchSize > 0) {
normalizedProcessingTimePerCommitDist.record(
processingDuration.getMillis() / (double) batchSize, tld, status.name(), dnsWriter);
processingDuration.toMillis() / (double) batchSize, tld, status.name(), dnsWriter);
normalizedProcessingTimePerItemDist.record(
processingDuration.getMillis() / (double) batchSize,
processingDuration.toMillis() / (double) batchSize,
batchSize,
tld,
status.name(),
@@ -267,7 +267,7 @@ public class DnsMetrics {
Duration timeSinceUpdateRequest,
Duration timeSinceActionEnqueued) {
updateRequestLatency.record(
timeSinceUpdateRequest.getMillis(), numberOfItems, tld, status.name(), dnsWriter);
publishQueueDelay.record(timeSinceActionEnqueued.getMillis(), tld, status.name(), dnsWriter);
timeSinceUpdateRequest.toMillis(), numberOfItems, tld, status.name(), dnsWriter);
publishQueueDelay.record(timeSinceActionEnqueued.toMillis(), tld, status.name(), dnsWriter);
}
}

View File

@@ -32,9 +32,9 @@ import google.registry.dns.writer.DnsWriterZone;
import google.registry.request.Parameter;
import google.registry.request.RequestParameters;
import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import org.joda.time.DateTime;
/** Dagger module for the dns package. */
@Module
@@ -68,15 +68,15 @@ public abstract class DnsModule {
@Provides
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED)
static DateTime provideCreateTime(HttpServletRequest req) {
return DateTime.parse(extractRequiredParameter(req, PARAM_PUBLISH_TASK_ENQUEUED));
static Instant provideCreateTime(HttpServletRequest req) {
return Instant.parse(extractRequiredParameter(req, PARAM_PUBLISH_TASK_ENQUEUED));
}
// TODO: Retire the old header after DNS pull queue migration.
@Provides
@Parameter(PARAM_REFRESH_REQUEST_TIME)
static DateTime provideItemsCreateTime(HttpServletRequest req) {
return DateTime.parse(
static Instant provideItemsCreateTime(HttpServletRequest req) {
return Instant.parse(
extractOptionalParameter(req, "itemsCreated")
.orElse(extractRequiredParameter(req, PARAM_REFRESH_REQUEST_TIME)));
}

View File

@@ -17,6 +17,7 @@ package google.registry.dns;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toJavaDuration;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
@@ -24,10 +25,10 @@ import com.google.common.net.InternetDomainName;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/** Utility class to handle DNS refresh requests. */
public final class DnsUtils {
@@ -42,13 +43,13 @@ public final class DnsUtils {
// Throws an IllegalArgumentException if the name is not under a managed TLD -- we only update
// DNS for names that are under our management.
String tld = Tlds.findTldForNameOrThrow(InternetDomainName.from(name)).toString();
tm().insert(new DnsRefreshRequest(type, name, tld, tm().getTransactionTime().plus(delay)));
tm().insert(new DnsRefreshRequest(type, name, tld, tm().getTxTime().plus(delay)));
}
private static void requestDnsRefresh(
ImmutableCollection<String> names, TargetType type, Duration delay) {
tm().assertInTransaction();
DateTime requestTime = tm().getTransactionTime().plus(delay);
Instant requestTime = tm().getTxTime().plus(delay);
tm().insertAll(
names.stream()
.map(
@@ -103,7 +104,7 @@ public final class DnsUtils {
return tm().transact(
TRANSACTION_REPEATABLE_READ,
() -> {
DateTime transactionTime = tm().getTransactionTime();
Instant transactionTime = tm().getTxTime();
ImmutableList<DnsRefreshRequest> requests =
tm().query(
"FROM DnsRefreshRequest WHERE tld = :tld "
@@ -150,10 +151,10 @@ public final class DnsUtils {
if (tldName.isPresent()) {
Tld tld = Tld.get(tldName.get().toString());
if (tld.getDnsAPlusAaaaTtl().isPresent()) {
dnsAPlusAaaaTtl = tld.getDnsAPlusAaaaTtl().get();
dnsAPlusAaaaTtl = toJavaDuration(tld.getDnsAPlusAaaaTtl().get());
}
}
return dnsAPlusAaaaTtl.getStandardSeconds();
return dnsAPlusAaaaTtl.toSeconds();
}
/** The possible values of the {@code DNS_TARGET_TYPE_PARAM} parameter. */

View File

@@ -63,11 +63,11 @@ import google.registry.util.DomainNameUtils;
import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/** Task that sends domain and host updates to the DNS server. */
@Action(
@@ -100,8 +100,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
*/
private final String dnsWriter;
private final DateTime enqueuedTime;
private final DateTime itemsCreateTime;
private final Instant enqueuedTime;
private final Instant itemsCreateTime;
private final int lockIndex;
private final int numPublishLocks;
private final Set<String> domains;
@@ -121,8 +121,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
@Inject
public PublishDnsUpdatesAction(
@Parameter(PARAM_DNS_WRITER) String dnsWriter,
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED) DateTime enqueuedTime,
@Parameter(PARAM_REFRESH_REQUEST_TIME) DateTime itemsCreateTime,
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED) Instant enqueuedTime,
@Parameter(PARAM_REFRESH_REQUEST_TIME) Instant itemsCreateTime,
@Parameter(PARAM_LOCK_INDEX) int lockIndex,
@Parameter(PARAM_NUM_PUBLISH_LOCKS) int numPublishLocks,
@Parameter(PARAM_DOMAINS) Set<String> domains,
@@ -167,15 +167,15 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
}
private void recordActionResult(ActionStatus status) {
DateTime now = clock.nowUtc();
Instant now = clock.now();
dnsMetrics.recordActionResult(
tld,
dnsWriter,
status,
nullToEmpty(domains).size() + nullToEmpty(hosts).size(),
new Duration(itemsCreateTime, now),
new Duration(enqueuedTime, now));
Duration.between(itemsCreateTime, now),
Duration.between(enqueuedTime, now));
logger.atInfo().log(
"publishDnsWriter latency statistics: TLD: %s, dnsWriter: %s, actionStatus: %s, "
+ "numItems: %d, timeSinceCreation: %s, timeInQueue: %s.",
@@ -183,8 +183,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
dnsWriter,
status,
nullToEmpty(domains).size() + nullToEmpty(hosts).size(),
new Duration(itemsCreateTime, now),
new Duration(enqueuedTime, now));
Duration.between(itemsCreateTime, now),
Duration.between(enqueuedTime, now));
}
/** Runs the task. */
@@ -237,7 +237,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
.ifPresent(
dn -> {
Optional<Domain> domain =
ForeignKeyUtils.loadResource(Domain.class, dn, clock.nowUtc());
ForeignKeyUtils.loadResource(Domain.class, dn, clock.now());
if (domain.isPresent()) {
notifyWithEmailAboutDnsUpdateFailure(
domain.get().getCurrentSponsorRegistrarId(), dn, false);
@@ -250,8 +250,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
.findFirst()
.ifPresent(
hn -> {
Optional<Host> host =
ForeignKeyUtils.loadResource(Host.class, hn, clock.nowUtc());
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hn, clock.now());
if (host.isPresent()) {
notifyWithEmailAboutDnsUpdateFailure(
host.get().getPersistedCurrentSponsorRegistrarId(), hn, true);
@@ -336,7 +335,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
.put(PARAM_DNS_WRITER, dnsWriter)
.put(PARAM_LOCK_INDEX, Integer.toString(lockIndex))
.put(PARAM_NUM_PUBLISH_LOCKS, Integer.toString(numPublishLocks))
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.nowUtc().toString())
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.now().toString())
.put(PARAM_REFRESH_REQUEST_TIME, itemsCreateTime.toString())
.put(PARAM_DOMAINS, Joiner.on(",").join(domains))
.put(PARAM_HOSTS, Joiner.on(",").join(hosts))
@@ -374,7 +373,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
/** Steps through the domain and host refreshes contained in the parameters and processes them. */
private void processBatch() {
DateTime timeAtStart = clock.nowUtc();
Instant timeAtStart = clock.now();
DnsWriter writer = dnsWriterProxy.getByClassNameForTld(dnsWriter, tld);
@@ -426,7 +425,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
actionStatus = ActionStatus.SUCCESS;
} finally {
recordActionResult(actionStatus);
Duration duration = new Duration(timeAtStart, clock.nowUtc());
Duration duration = Duration.between(timeAtStart, clock.now());
dnsMetrics.recordCommit(
tld, dnsWriter, commitStatus, duration, domainsPublished, hostsPublished);
logger.atInfo().log(

View File

@@ -28,7 +28,7 @@ import static google.registry.dns.DnsUtils.deleteRequests;
import static google.registry.dns.DnsUtils.readAndUpdateRequestsWithLatestProcessTime;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_TLD;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DomainNameUtils.getSecondLevelDomain;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -49,10 +49,10 @@ import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Action for fanning out DNS refresh tasks by TLD, using data taken from {@link DnsRefreshRequest}
@@ -104,11 +104,11 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
logger.atInfo().log("The queue updated is paused for TLD: %s.", tld);
return;
}
DateTime requestedEndTime = clock.nowUtc().plus(requestedMaximumDuration);
Instant requestedEndTime = clock.now().plus(requestedMaximumDuration);
// See getLockIndex(), requests are evenly distributed to [1, numDnsPublishLocks], so each
// bucket would be roughly the size of tldUpdateBatchSize.
int processBatchSize = tldUpdateBatchSize * Tld.get(tld).getNumDnsPublishLocks();
while (requestedEndTime.isAfter(clock.nowUtc())) {
while (requestedEndTime.isAfter(clock.now())) {
ImmutableList<DnsRefreshRequest> requests =
readAndUpdateRequestsWithLatestProcessTime(
tld, requestedMaximumDuration, processBatchSize);
@@ -165,7 +165,7 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
void enqueueUpdates(int lockIndex, int numPublishLocks, Collection<DnsRefreshRequest> requests) {
ImmutableList.Builder<String> domainsBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<String> hostsBuilder = new ImmutableList.Builder<>();
DateTime earliestRequestTime = END_OF_TIME;
Instant earliestRequestTime = END_INSTANT;
for (DnsRefreshRequest request : requests) {
if (request.getRequestTime().isBefore(earliestRequestTime)) {
earliestRequestTime = request.getRequestTime();
@@ -189,7 +189,7 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
.put(PARAM_DNS_WRITER, dnsWriter)
.put(PARAM_LOCK_INDEX, Integer.toString(lockIndex))
.put(PARAM_NUM_PUBLISH_LOCKS, Integer.toString(numPublishLocks))
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.nowUtc().toString())
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.now().toString())
.put(PARAM_REFRESH_REQUEST_TIME, earliestRequestTime.toString())
.put(PARAM_DOMAINS, Joiner.on(',').join(domains))
.put(PARAM_HOSTS, Joiner.on(',').join(hosts))

View File

@@ -78,7 +78,7 @@ public final class RefreshDnsAction implements Runnable {
private <T extends EppResource & ForeignKeyedEppResource>
T loadAndVerifyExistence(Class<T> clazz, String foreignKey) {
return ForeignKeyUtils.loadResource(clazz, foreignKey, clock.nowUtc())
return ForeignKeyUtils.loadResource(clazz, foreignKey, clock.now())
.orElseThrow(
() ->
new NotFoundException(

View File

@@ -30,7 +30,7 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import org.joda.time.DateTime;
import java.time.Instant;
@Action(
service = Action.Service.BACKEND,
@@ -56,7 +56,7 @@ public class RefreshDnsOnHostRenameAction implements Runnable {
public void run() {
tm().transact(
() -> {
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
Host host = tm().loadByKeyIfPresent(hostKey).orElse(null);
boolean hostValid = true;
String failureMessage = null;

View File

@@ -44,6 +44,7 @@ import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import google.registry.util.Concurrent;
import google.registry.util.DateTimeUtils;
import google.registry.util.Retrier;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@@ -51,6 +52,7 @@ import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.time.Duration;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,7 +61,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.joda.time.Duration;
/**
* {@link DnsWriter} implementation that talks to Google Cloud DNS.
@@ -123,8 +124,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
String absoluteDomainName = getAbsoluteHostName(domainName);
// Load the target domain. Note that it can be absent if this domain was just deleted.
Optional<Domain> domain =
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.nowUtc());
Optional<Domain> domain = ForeignKeyUtils.loadResource(Domain.class, domainName, clock.now());
// Return early if no DNS records should be published.
// desiredRecordsBuilder is populated with an empty set to indicate that all existing records
@@ -148,7 +148,12 @@ public class CloudDnsWriter extends BaseDnsWriter {
domainRecords.add(
new ResourceRecordSet()
.setName(absoluteDomainName)
.setTtl((int) tld.getDnsDsTtl().orElse(defaultDsTtl).getStandardSeconds())
.setTtl(
(int)
tld.getDnsDsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(defaultDsTtl)
.toSeconds())
.setType("DS")
.setKind("dns#resourceRecordSet")
.setRrdatas(ImmutableList.copyOf(dsRrData)));
@@ -171,7 +176,12 @@ public class CloudDnsWriter extends BaseDnsWriter {
domainRecords.add(
new ResourceRecordSet()
.setName(absoluteDomainName)
.setTtl((int) tld.getDnsNsTtl().orElse(defaultNsTtl).getStandardSeconds())
.setTtl(
(int)
tld.getDnsNsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(defaultNsTtl)
.toSeconds())
.setType("NS")
.setKind("dns#resourceRecordSet")
.setRrdatas(ImmutableList.copyOf(nsRrData)));
@@ -190,7 +200,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
// Load the target host. Note that it can be absent if this host was just deleted.
// desiredRecords is populated with an empty set to indicate that all existing records
// should be deleted.
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.nowUtc());
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.now());
// Return early if the host is deleted.
if (host.isEmpty()) {

View File

@@ -28,8 +28,8 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.time.Duration;
import javax.net.SocketFactory;
import org.joda.time.Duration;
import org.xbill.DNS.Message;
import org.xbill.DNS.Opcode;
@@ -76,7 +76,7 @@ public class DnsMessageTransport {
@Config("dnsUpdateTimeout") Duration updateTimeout) {
this.factory = factory;
this.updateHost = updateHost;
this.updateTimeout = Ints.checkedCast(updateTimeout.getMillis());
this.updateTimeout = Ints.checkedCast(updateTimeout.toMillis());
}
/**

View File

@@ -17,7 +17,7 @@ package google.registry.dns.writer.dnsupdate;
import dagger.Module;
import dagger.Provides;
import google.registry.config.RegistryConfig.Config;
import org.joda.time.Duration;
import java.time.Duration;
/** Dagger module that provides DNS configuration settings. */
@Module
@@ -39,6 +39,6 @@ public class DnsUpdateConfigModule {
@Provides
@Config("dnsUpdateTimeout")
public static Duration provideDnsUpdateTimeout() {
return Duration.standardSeconds(30);
return Duration.ofSeconds(30);
}
}

View File

@@ -34,13 +34,14 @@ import google.registry.model.host.Host;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import jakarta.inject.Inject;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.time.Duration;
import java.util.Optional;
import org.joda.time.Duration;
import org.xbill.DNS.AAAARecord;
import org.xbill.DNS.ARecord;
import org.xbill.DNS.DClass;
@@ -130,7 +131,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
*/
private void publishDomain(String domainName, String requestingHostName) {
Optional<Domain> domainOptional =
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.nowUtc());
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.now());
update.delete(toAbsoluteName(domainName), Type.ANY);
// If the domain is now deleted, then don't update DNS for it.
if (domainOptional.isPresent()) {
@@ -194,7 +195,10 @@ public class DnsUpdateWriter extends BaseDnsWriter {
new DSRecord(
toAbsoluteName(domain.getDomainName()),
DClass.IN,
tld.getDnsDsTtl().orElse(dnsDefaultDsTtl).getStandardSeconds(),
tld.getDnsDsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(dnsDefaultDsTtl)
.toSeconds(),
signerData.getKeyTag(),
signerData.getAlgorithm(),
signerData.getDigestType(),
@@ -219,7 +223,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
private void addInBailiwickNameServerSet(Domain domain, Update update) {
for (String hostName :
intersection(domain.loadNameserverHostNames(), domain.getSubordinateHosts())) {
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.nowUtc());
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.now());
checkState(host.isPresent(), "Host %s cannot be loaded", hostName);
update.add(makeAddressSet(host.get()));
update.add(makeV6AddressSet(host.get()));
@@ -234,7 +238,10 @@ public class DnsUpdateWriter extends BaseDnsWriter {
new NSRecord(
toAbsoluteName(domain.getDomainName()),
DClass.IN,
tld.getDnsNsTtl().orElse(dnsDefaultNsTtl).getStandardSeconds(),
tld.getDnsNsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(dnsDefaultNsTtl)
.toSeconds(),
toAbsoluteName(hostName));
nameServerSet.addRR(record);
}

View File

@@ -47,8 +47,6 @@ import java.time.Instant;
import java.util.List;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.TupleTransformer;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
/**
* An action that exports the list of active domains on all real TLDs to Google Drive and GCS.
@@ -175,8 +173,7 @@ public class ExportDomainListsAction implements Runnable {
@Override
public String transformTuple(Object[] domainResult, String[] strings) {
String domainName = (String) domainResult[0];
Instant deletionInstant = (Instant) domainResult[1];
DateTime deletionTime = new DateTime(deletionInstant.toEpochMilli(), DateTimeZone.UTC);
Instant deletionTime = (Instant) domainResult[1];
String[] domainStatuses = (String[]) domainResult[2];
String gracePeriodType = (String) domainResult[3];
boolean inPendingDelete =

View File

@@ -26,6 +26,7 @@ import static google.registry.model.registrar.RegistrarPoc.Type.TECH;
import static google.registry.model.registrar.RegistrarPoc.Type.WHOIS;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -37,7 +38,6 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Instant;
@@ -63,9 +63,9 @@ class SyncRegistrarsSheet {
boolean wereRegistrarsModified() {
Optional<Cursor> cursor =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createGlobalVKey(SYNC_REGISTRAR_SHEET)));
Instant lastUpdateTime = cursor.isEmpty() ? START_INSTANT : cursor.get().getCursorTimeInstant();
Instant lastUpdateTime = cursor.isEmpty() ? START_INSTANT : cursor.get().getCursorTime();
for (Registrar registrar : Registrar.loadAllCached()) {
if (DateTimeUtils.isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
if (isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
return true;
}
}

View File

@@ -30,10 +30,10 @@ import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import org.joda.time.Duration;
/**
* Action for synchronizing the registrars spreadsheet.

View File

@@ -42,6 +42,7 @@ import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import static java.time.ZoneOffset.UTC;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -101,7 +102,6 @@ import google.registry.model.tld.Tld.TldType;
import google.registry.model.transfer.TransferStatus;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
@@ -194,9 +194,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
} else {
Instant redemptionTime = now.plusMillis(redemptionGracePeriodLength.getMillis());
asyncTaskEnqueuer.enqueueAsyncResave(
existingDomain.createVKey(),
toDateTime(now),
ImmutableSortedSet.of(toDateTime(redemptionTime), toDateTime(deletionTime)));
existingDomain.createVKey(), now, ImmutableSortedSet.of(redemptionTime, deletionTime));
builder
.setDeletionTime(deletionTime)
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
@@ -253,14 +251,11 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
// This can be either add grace periods or renew grace periods.
BillingEvent billingEvent = tm().loadByKey(gracePeriod.getBillingEvent());
newExpirationTime =
newExpirationTime
.atZone(ZoneOffset.UTC)
.minusYears(billingEvent.getPeriodYears())
.toInstant();
newExpirationTime.atZone(UTC).minusYears(billingEvent.getPeriodYears()).toInstant();
} else if (gracePeriod.getBillingRecurrence() != null) {
// Take 1 year off the registration if in the autorenew grace period (no need to load the
// recurrence billing event; all autorenews are for 1 year).
newExpirationTime = newExpirationTime.atZone(ZoneOffset.UTC).minusYears(1).toInstant();
newExpirationTime = newExpirationTime.atZone(UTC).minusYears(1).toInstant();
}
}
}

View File

@@ -44,6 +44,7 @@ import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.minusDays;
import static google.registry.util.DomainNameUtils.ACE_PREFIX;
import static java.time.ZoneOffset.UTC;
import static java.util.stream.Collectors.joining;
import com.google.common.base.CharMatcher;
@@ -124,7 +125,6 @@ import google.registry.tools.DigestType;
import google.registry.util.Idn;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
@@ -848,10 +848,7 @@ public class DomainFlowUtils {
*/
public static void validateRegistrationPeriod(Instant now, Instant newExpirationTime)
throws EppException {
if (now.atZone(ZoneOffset.UTC)
.plusYears(MAX_REGISTRATION_YEARS)
.toInstant()
.isBefore(newExpirationTime)) {
if (now.atZone(UTC).plusYears(MAX_REGISTRATION_YEARS).toInstant().isBefore(newExpirationTime)) {
throw new ExceedsMaxRegistrationYearsException();
}
}

View File

@@ -35,6 +35,7 @@ import static google.registry.flows.domain.token.AllocationTokenFlowUtils.verify
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RENEW;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toDateTime;
import static java.time.ZoneOffset.UTC;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -87,7 +88,6 @@ import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.tld.Tld;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.Duration;
@@ -194,7 +194,7 @@ public final class DomainRenewFlow implements MutatingFlow {
Instant newExpirationTime =
existingDomain
.getRegistrationExpirationTime()
.atZone(ZoneOffset.UTC)
.atZone(UTC)
.plusYears(years)
.toInstant(); // Uncapped
validateRegistrationPeriod(now, newExpirationTime);

View File

@@ -31,6 +31,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActi
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RESTORE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static java.time.ZoneOffset.UTC;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -70,7 +71,6 @@ import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.tld.Tld;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Optional;
import org.joda.money.Money;
@@ -152,7 +152,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
Instant newExpirationTime =
existingDomain
.getRegistrationExpirationTime()
.atZone(ZoneOffset.UTC)
.atZone(UTC)
.plusYears(isExpired ? 1 : 0)
.toInstant();
// Restore the expiration time on the deleted domain, except if that's already passed, then add

View File

@@ -35,7 +35,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toDateTime;
import static java.time.temporal.ChronoUnit.DAYS;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -82,7 +82,6 @@ import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Optional;
/**
@@ -220,8 +219,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
.map(
domainTransferRequestSuperuserExtension ->
now.plus(
domainTransferRequestSuperuserExtension.getAutomaticTransferLength(),
ChronoUnit.DAYS))
domainTransferRequestSuperuserExtension.getAutomaticTransferLength(), DAYS))
.orElseGet(() -> now.plusMillis(tld.getAutomaticTransferLength().getMillis()));
// If the domain will be in the auto-renew grace period at the moment of transfer, the transfer
// will subsume the autorenew, so we don't add the normal extra year from the transfer.
@@ -284,9 +282,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now, period);
asyncTaskEnqueuer.enqueueAsyncResave(
newDomain.createVKey(),
toDateTime(now),
ImmutableSortedSet.of(toDateTime(automaticTransferTime)));
newDomain.createVKey(), now, ImmutableSortedSet.of(automaticTransferTime));
tm().put(newDomain);
tm().putAll(serverApproveEntities);
tm().insertAll(domainHistory, requestPollMessage);

View File

@@ -83,7 +83,7 @@ public final class PollAckFlow implements MutatingFlow {
throw new InvalidMessageIdException(messageId);
}
final Instant now = tm().getTxTime();
Instant now = tm().getTxTime();
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
// it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual

View File

@@ -17,8 +17,6 @@ package google.registry.model.common;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
@@ -35,7 +33,6 @@ import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
/**
* Shared entity for date cursors.
@@ -156,15 +153,6 @@ public class Cursor extends UpdateAutoTimestampEntity {
return getUpdateTimestamp().getTimestamp();
}
/**
* @deprecated Use {@link #getLastUpdateTime()}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public DateTime getLastUpdateDateTime() {
return toDateTime(getUpdateTimestamp().getTimestamp());
}
public String getScope() {
return scope;
}
@@ -189,30 +177,12 @@ public class Cursor extends UpdateAutoTimestampEntity {
return create(cursorType, cursorTime, GLOBAL);
}
/**
* @deprecated Use {@link #createGlobal(CursorType, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static Cursor createGlobal(CursorType cursorType, DateTime cursorTime) {
return createGlobal(cursorType, toInstant(cursorTime));
}
/** Creates a new cursor instance with a given {@link Tld} scope. */
public static Cursor createScoped(CursorType cursorType, Instant cursorTime, Tld scope) {
checkNotNull(scope, "Cursor scope cannot be null");
return create(cursorType, cursorTime, scope.getTldStr());
}
/**
* @deprecated Use {@link #createScoped(CursorType, Instant, Tld)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static Cursor createScoped(CursorType cursorType, DateTime cursorTime, Tld scope) {
return createScoped(cursorType, toInstant(cursorTime), scope);
}
/**
* Creates a new cursor instance with a given TLD scope, or global if the scope is {@link
* #GLOBAL}.
@@ -230,29 +200,11 @@ public class Cursor extends UpdateAutoTimestampEntity {
/**
* Returns the current time for a given cursor, or {@code START_INSTANT} if the cursor is null.
*/
public static Instant getCursorTimeOrStartOfTimeInstant(Optional<Cursor> cursor) {
return cursor.map(Cursor::getCursorTimeInstant).orElse(START_INSTANT);
public static Instant getCursorTimeOrStartOfTime(Optional<Cursor> cursor) {
return cursor.map(Cursor::getCursorTime).orElse(START_INSTANT);
}
/**
* @deprecated Use {@link #getCursorTimeOrStartOfTimeInstant(Optional)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime getCursorTimeOrStartOfTime(Optional<Cursor> cursor) {
return toDateTime(getCursorTimeOrStartOfTimeInstant(cursor));
}
/**
* @deprecated Use {@link #getCursorTimeInstant()}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public DateTime getCursorTime() {
return toDateTime(cursorTime);
}
public Instant getCursorTimeInstant() {
public Instant getCursorTime() {
return cursorTime;
}

View File

@@ -16,7 +16,7 @@ package google.registry.model.common;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import google.registry.dns.DnsUtils.TargetType;
import google.registry.dns.PublishDnsUpdatesAction;
@@ -31,8 +31,8 @@ import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import java.time.Instant;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
@Entity
@Table(indexes = {@Index(columnList = "requestTime"), @Index(columnList = "lastProcessTime")})
@@ -54,10 +54,10 @@ public class DnsRefreshRequest extends ImmutableObject {
private String tld;
@Column(nullable = false)
private DateTime requestTime;
private Instant requestTime;
@Column(nullable = false)
private DateTime lastProcessTime;
private Instant lastProcessTime;
public TargetType getType() {
return type;
@@ -71,7 +71,7 @@ public class DnsRefreshRequest extends ImmutableObject {
return tld;
}
public DateTime getRequestTime() {
public Instant getRequestTime() {
return requestTime;
}
@@ -86,7 +86,7 @@ public class DnsRefreshRequest extends ImmutableObject {
* there are concurrent reads that all attempt to read the rows with oldest {@link #requestTime},
* or another read that comes too early after the previous read.
*/
public DateTime getLastProcessTime() {
public Instant getLastProcessTime() {
return lastProcessTime;
}
@@ -102,8 +102,8 @@ public class DnsRefreshRequest extends ImmutableObject {
TargetType type,
String name,
String tld,
DateTime requestTime,
DateTime lastProcessTime) {
Instant requestTime,
Instant lastProcessTime) {
checkNotNull(type, "Target type cannot be null");
checkNotNull(name, "Domain/host name cannot be null");
checkNotNull(tld, "TLD cannot be null");
@@ -119,11 +119,11 @@ public class DnsRefreshRequest extends ImmutableObject {
this.lastProcessTime = lastProcessTime;
}
public DnsRefreshRequest(TargetType type, String name, String tld, DateTime requestTime) {
this(null, type, name, tld, requestTime, START_OF_TIME);
public DnsRefreshRequest(TargetType type, String name, String tld, Instant requestTime) {
this(null, type, name, tld, requestTime, START_INSTANT);
}
public DnsRefreshRequest updateProcessTime(DateTime processTime) {
public DnsRefreshRequest updateProcessTime(Instant processTime) {
checkArgument(
processTime.isAfter(getRequestTime()),
"Process time %s must be later than request time %s",

View File

@@ -22,6 +22,7 @@ import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.minusYears;
import static google.registry.util.DateTimeUtils.plusYears;
import static java.time.ZoneOffset.UTC;
import com.google.common.base.Splitter;
import com.google.common.collect.ContiguousSet;
@@ -32,7 +33,6 @@ import jakarta.persistence.Embeddable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
@@ -63,7 +63,7 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
* February 28. It is impossible to construct a {@link TimeOfYear} for February 29th.
*/
public static TimeOfYear fromInstant(Instant instant) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, UTC);
int month = zdt.getMonthValue();
int day = zdt.getDayOfMonth();
if (month == 2 && day == 29) {
@@ -88,8 +88,8 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
Range<Instant> normalizedRange = range.intersection(Range.closed(START_INSTANT, END_INSTANT));
Range<Integer> yearRange =
Range.closed(
ZonedDateTime.ofInstant(normalizedRange.lowerEndpoint(), ZoneOffset.UTC).getYear(),
ZonedDateTime.ofInstant(normalizedRange.upperEndpoint(), ZoneOffset.UTC).getYear());
ZonedDateTime.ofInstant(normalizedRange.lowerEndpoint(), UTC).getYear(),
ZonedDateTime.ofInstant(normalizedRange.upperEndpoint(), UTC).getYear());
return ContiguousSet.create(yearRange, integers()).stream()
.map(this::toInstantWithYear)
.filter(normalizedRange)
@@ -107,20 +107,18 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
int millis = Integer.parseInt(monthDayMillis.get(2));
return LocalDate.of(year, month, day)
.atTime(LocalTime.ofNanoOfDay(millis * 1000000L))
.toInstant(ZoneOffset.UTC);
.toInstant(UTC);
}
/** Get the first {@link Instant} with this month/day/millis that is at or after the start. */
public Instant getNextInstanceAtOrAfter(Instant start) {
Instant withSameYear =
toInstantWithYear(ZonedDateTime.ofInstant(start, ZoneOffset.UTC).getYear());
Instant withSameYear = toInstantWithYear(ZonedDateTime.ofInstant(start, UTC).getYear());
return isAtOrAfter(withSameYear, start) ? withSameYear : plusYears(withSameYear, 1);
}
/** Get the first {@link Instant} with this month/day/millis that is at or before the end. */
public Instant getLastInstanceBeforeOrAt(Instant end) {
Instant withSameYear =
toInstantWithYear(ZonedDateTime.ofInstant(end, ZoneOffset.UTC).getYear());
Instant withSameYear = toInstantWithYear(ZonedDateTime.ofInstant(end, UTC).getYear());
return isBeforeOrAt(withSameYear, end) ? withSameYear : minusYears(withSameYear, 1);
}

View File

@@ -14,9 +14,10 @@
package google.registry.model.poll;
import static java.time.ZoneOffset.UTC;
import com.google.common.base.Splitter;
import google.registry.persistence.VKey;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
@@ -45,8 +46,7 @@ public final class PollMessageExternalKeyConverter {
public static String makePollMessageExternalId(PollMessage pollMessage) {
return String.format(
"%d-%d",
pollMessage.getId(),
ZonedDateTime.ofInstant(pollMessage.getEventTime(), ZoneOffset.UTC).getYear());
pollMessage.getId(), ZonedDateTime.ofInstant(pollMessage.getEventTime(), UTC).getYear());
}
/**

View File

@@ -16,38 +16,39 @@ package google.registry.model.rde;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoUnit.DAYS;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
/** Utility class for generating RDE filenames and string IDs. */
public final class RdeNamingUtils {
private static final DateTimeFormatter DATE_FORMATTER = ISODateTimeFormat.date();
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
/**
* Returns extensionless RDE filename in format {@code <gTLD>_<YYYY-MM-DD>_<type>_S<#>_R<rev>}.
*
* <p>This naming scheme is defined in the {@code gTLD_Applicant_Guidebook_full.pdf}.
*/
public static
String makeRydeFilename(String tld, DateTime date, RdeMode mode, int series, int revision) {
public static String makeRydeFilename(
String tld, Instant date, RdeMode mode, int series, int revision) {
checkArgument(series >= 1, "series >= 1");
checkArgument(revision >= 0, "revision >= 0");
return String.format("%s_S%d_R%d", makePartialName(tld, date, mode), series, revision);
}
/** Returns same thing as {@link #makeRydeFilename} except without the series and revision. */
public static String makePartialName(String tld, DateTime date, RdeMode mode) {
public static String makePartialName(String tld, Instant date, RdeMode mode) {
return String.format("%s_%s_%s",
checkNotNull(tld), formatDate(date), mode.getFilenameComponent());
}
/** Returns date as a hyphened string with ISO-8601 ordering, e.g. {@code 1984-12-18}. */
private static String formatDate(DateTime date) {
checkArgument(date.withTimeAtStartOfDay().equals(date), "Not midnight: %s", date);
return DATE_FORMATTER.print(date);
private static String formatDate(Instant date) {
checkArgument(date.truncatedTo(DAYS).equals(date), "Not midnight: %s", date);
return DATE_FORMATTER.withZone(UTC).format(date);
}
private RdeNamingUtils() {}

View File

@@ -17,11 +17,11 @@ package google.registry.model.rde;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.rde.RdeNamingUtils.makePartialName;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toJodaLocalDate;
import com.google.common.base.VerifyException;
import google.registry.model.ImmutableObject;
import google.registry.model.UpdateAutoTimestampEntity;
import google.registry.model.rde.RdeRevision.RdeRevisionId;
import google.registry.persistence.VKey;
import google.registry.persistence.converter.LocalDateConverter;
import jakarta.persistence.Column;
@@ -32,8 +32,8 @@ import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import java.io.Serializable;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
/**
@@ -44,7 +44,7 @@ import org.joda.time.LocalDate;
* flag is included in the generated XML.
*/
@Entity
@IdClass(RdeRevisionId.class)
@IdClass(RdeRevision.RdeRevisionId.class)
public final class RdeRevision extends UpdateAutoTimestampEntity {
@Id String tld;
@@ -82,15 +82,15 @@ public final class RdeRevision extends UpdateAutoTimestampEntity {
*
* @return {@code 0} for first deposit generation and {@code >0} for resends
*/
public static int getNextRevision(String tld, DateTime date, RdeMode mode) {
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
public static int getNextRevision(String tld, Instant date, RdeMode mode) {
RdeRevisionId revisionId = RdeRevisionId.create(tld, toJodaLocalDate(date), mode);
Optional<RdeRevision> revisionOptional =
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey)));
tm().transact(() -> tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, revisionId)));
return revisionOptional.map(rdeRevision -> rdeRevision.revision + 1).orElse(0);
}
/** Returns the latest revision of the report already generated for the given triplet. */
public static Optional<Integer> getCurrentRevision(String tld, DateTime date, RdeMode mode) {
public static Optional<Integer> getCurrentRevision(String tld, Instant date, RdeMode mode) {
int nextRevision = getNextRevision(tld, date, mode);
if (nextRevision == 0) {
return Optional.empty();
@@ -107,12 +107,12 @@ public final class RdeRevision extends UpdateAutoTimestampEntity {
* @throws IllegalStateException if not in a transaction
* @throws VerifyException if the state doesn't meet the above criteria
*/
public static void saveRevision(String tld, DateTime date, RdeMode mode, int revision) {
public static void saveRevision(String tld, Instant date, RdeMode mode, int revision) {
checkArgument(revision >= 0, "Negative revision: %s", revision);
tm().assertInTransaction();
RdeRevisionId sqlKey = RdeRevisionId.create(tld, date.toLocalDate(), mode);
RdeRevisionId revisionId = RdeRevisionId.create(tld, toJodaLocalDate(date), mode);
Optional<RdeRevision> revisionOptional =
tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, sqlKey));
tm().loadByKeyIfPresent(VKey.create(RdeRevision.class, revisionId));
if (revision == 0) {
revisionOptional.ifPresent(
rdeRevision -> {
@@ -133,8 +133,7 @@ public final class RdeRevision extends UpdateAutoTimestampEntity {
revision - 1,
revisionOptional.get());
}
RdeRevision object = create(tld, date.toLocalDate(), mode, revision);
tm().put(object);
tm().put(RdeRevision.create(tld, toJodaLocalDate(date), mode, revision));
}
/** Class to represent the composite primary key of {@link RdeRevision} entity. */

View File

@@ -34,11 +34,11 @@ import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* A lock on some shared resource.
@@ -79,11 +79,11 @@ public class Lock extends ImmutableObject implements Serializable {
/** When the lock can be considered implicitly released. */
@Column(nullable = false)
DateTime expirationTime;
Instant expirationTime;
/** When was the lock acquired. Used for logging. */
@Column(nullable = false)
DateTime acquiredTime;
Instant acquiredTime;
/** The resource name used to create the lock. */
@Column(nullable = false)
@@ -95,7 +95,7 @@ public class Lock extends ImmutableObject implements Serializable {
@Id
String scope;
public DateTime getExpirationTime() {
public Instant getExpirationTime() {
return expirationTime;
}
@@ -109,10 +109,7 @@ public class Lock extends ImmutableObject implements Serializable {
* namespace).
*/
private static Lock create(
String resourceName,
String scope,
DateTime acquiredTime,
Duration leaseLength) {
String resourceName, String scope, Instant acquiredTime, Duration leaseLength) {
checkArgument(!Strings.isNullOrEmpty(resourceName), "resourceName cannot be null or empty");
Lock instance = new Lock();
// Add the scope to the Lock's id so that it is unique for locks acquiring the same resource
@@ -130,7 +127,7 @@ public class Lock extends ImmutableObject implements Serializable {
}
record AcquireResult(
DateTime transactionTime,
Instant transactionTime,
@Nullable Lock existingLock,
@Nullable Lock newLock,
LockState lockState) {}
@@ -138,7 +135,7 @@ public class Lock extends ImmutableObject implements Serializable {
private static void logAcquireResult(AcquireResult acquireResult) {
try {
Lock lock = acquireResult.existingLock();
DateTime now = acquireResult.transactionTime();
Instant now = acquireResult.transactionTime();
switch (acquireResult.lockState()) {
case IN_USE ->
logger.atInfo().log(
@@ -170,7 +167,7 @@ public class Lock extends ImmutableObject implements Serializable {
String scope = tld != null ? tld : GLOBAL;
Callable<AcquireResult> lockAcquirer =
() -> {
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
// Checking if an unexpired lock still exists - if so, the lock can't be acquired.
Lock lock =
@@ -233,7 +230,7 @@ public class Lock extends ImmutableObject implements Serializable {
tm().delete(key);
lockMetrics.recordRelease(
resourceName, scope, new Duration(acquiredTime, tm().getTransactionTime()));
resourceName, scope, Duration.between(acquiredTime, tm().getTxTime()));
} else {
logger.atSevere().log(
"The lock we acquired was transferred to someone else before we"

View File

@@ -22,8 +22,8 @@ import com.google.monitoring.metrics.IncrementableMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import google.registry.model.server.Lock.LockState;
import java.time.Duration;
import javax.annotation.Nullable;
import org.joda.time.Duration;
/** Metrics for lock contention. */
class LockMetrics {
@@ -67,6 +67,6 @@ class LockMetrics {
}
void recordRelease(String resourceName, @Nullable String tld, Duration duration) {
lockLifetimeMetric.record(duration.getMillis(), String.valueOf(tld), resourceName);
lockLifetimeMetric.record(duration.toMillis(), String.valueOf(tld), resourceName);
}
}

View File

@@ -40,12 +40,12 @@ import google.registry.request.lock.LockHandler;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import org.joda.time.Duration;
/** Metrics Exporter for MoSAPI. */
public class MosApiMetrics {
@@ -67,7 +67,7 @@ public class MosApiMetrics {
// Lock Constants
private static final String LOCK_NAME = "MosApiMetricCreation";
private static final Duration LOCK_LEASE_TIME = Duration.standardHours(1);
private static final Duration LOCK_LEASE_TIME = Duration.ofHours(1);
// Metric Names
private static final String METRIC_TLD_STATUS = "tld_status";
private static final String METRIC_SERVICE_STATUS = "service_status";

View File

@@ -13,7 +13,6 @@
// limitations under the License.
package google.registry.persistence.converter;
import static org.joda.time.DateTimeZone.UTC;
import jakarta.persistence.AttributeConverter;

View File

@@ -14,7 +14,9 @@
package google.registry.persistence.converter;
import google.registry.util.DateTimeUtils;
import static google.registry.util.DateTimeUtils.toLocalDate;
import static google.registry.util.DateTimeUtils.toSqlDate;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.sql.Date;
@@ -26,11 +28,11 @@ public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate attribute) {
return attribute == null ? null : DateTimeUtils.toSqlDate(attribute);
return attribute == null ? null : toSqlDate(attribute);
}
@Override
public LocalDate convertToEntityAttribute(Date dbData) {
return dbData == null ? null : DateTimeUtils.toLocalDate(dbData);
return dbData == null ? null : toLocalDate(dbData);
}
}

View File

@@ -14,6 +14,7 @@
package google.registry.rde;
import static google.registry.model.common.Cursor.CursorType.BRDA;
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
import static google.registry.model.rde.RdeMode.THIN;
@@ -40,11 +41,11 @@ import jakarta.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.Optional;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
/**
* Action that re-encrypts a BRDA escrow deposit and puts it into the upload bucket.
@@ -77,7 +78,11 @@ public final class BrdaCopyAction implements Runnable {
@Inject @Config("brdaBucket") String brdaBucket;
@Inject @Config("rdeBucket") String stagingBucket;
@Inject @Parameter(RequestParameters.PARAM_TLD) String tld;
@Inject @Parameter(RdeModule.PARAM_WATERMARK) DateTime watermark;
@Inject
@Parameter(RdeModule.PARAM_WATERMARK)
Instant watermark;
@Inject @Parameter(RdeModule.PARAM_PREFIX) Optional<String> prefix;
@Inject @Key("brdaReceiverKey") PGPPublicKey receiverKey;
@Inject @Key("brdaSigningKey") PGPKeyPair signingKey;
@@ -98,7 +103,7 @@ public final class BrdaCopyAction implements Runnable {
// Not urgent since file writes on GCS are atomic.
Optional<Cursor> cursor =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createScopedVKey(BRDA, Tld.get(tld))));
DateTime brdaCursorTime = getCursorTimeOrStartOfTime(cursor);
Instant brdaCursorTime = getCursorTimeOrStartOfTime(cursor);
if (isBeforeOrAt(brdaCursorTime, watermark)) {
throw new NoContentException(
String.format(

View File

@@ -15,6 +15,7 @@
package google.registry.rde;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static java.time.temporal.ChronoUnit.DAYS;
import com.google.common.flogger.FluentLogger;
import google.registry.model.common.Cursor;
@@ -25,9 +26,9 @@ import google.registry.request.HttpException.ServiceUnavailableException;
import google.registry.request.lock.LockHandler;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Callable;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Runner applying guaranteed reliability to an {@link EscrowTask}.
@@ -61,7 +62,7 @@ class EscrowTaskRunner {
*
* @param watermark the logical time for a point-in-time view of the database.
*/
void runWithLock(DateTime watermark) throws Exception;
void runWithLock(Instant watermark) throws Exception;
}
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -88,8 +89,8 @@ class EscrowTaskRunner {
Callable<Void> lockRunner =
() -> {
logger.atInfo().log("Performing escrow for TLD '%s'.", tld.getTld());
DateTime startOfToday = clock.nowUtc().withTimeAtStartOfDay();
DateTime nextRequiredRun =
Instant startOfToday = clock.now().truncatedTo(DAYS);
Instant nextRequiredRun =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createScopedVKey(cursorType, tld)))
.map(Cursor::getCursorTime)
.orElse(startOfToday);
@@ -98,7 +99,7 @@ class EscrowTaskRunner {
}
logger.atInfo().log("Current cursor is: %s.", nextRequiredRun);
task.runWithLock(nextRequiredRun);
DateTime nextRun = nextRequiredRun.plus(interval);
Instant nextRun = nextRequiredRun.plus(interval);
logger.atInfo().log("Rolling cursor forward to %s.", nextRun);
tm().transact(() -> tm().put(Cursor.createScoped(cursorType, nextRun, tld)));
return null;

View File

@@ -36,10 +36,10 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import javax.annotation.Nullable;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
/**
* Utility class for reading and writing data in the ghostryde container format.
@@ -116,7 +116,8 @@ public final class Ghostryde {
* set them to a constant value.
*/
static final String INNER_FILENAME = "file.xml";
static final DateTime INNER_MODIFICATION_TIME = DateTime.parse("2000-01-01TZ");
static final Instant INNER_MODIFICATION_TIME = Instant.parse("2000-01-01T00:00:00Z");
/** Creates a ghostryde file from an in-memory byte array. */
public static byte[] encode(byte[] data, PGPPublicKey key) throws IOException {

View File

@@ -29,7 +29,7 @@ import google.registry.xjc.rdehost.XjcRdeHost;
import google.registry.xjc.rdehost.XjcRdeHostElement;
import java.net.Inet6Address;
import java.net.InetAddress;
import org.joda.time.DateTime;
import java.time.Instant;
/** Utility class that turns a {@link Host} resource into {@link XjcRdeHostElement}. */
final class HostToXjcConverter {
@@ -52,7 +52,7 @@ final class HostToXjcConverter {
convertHostCommon(
model,
superordinateDomain.getCurrentSponsorRegistrarId(),
toDateTime(model.computeLastTransferTime(superordinateDomain)));
model.computeLastTransferTime(superordinateDomain));
if (superordinateDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
bean.getStatuses().add(convertStatusValue(StatusValue.PENDING_TRANSFER));
}
@@ -62,13 +62,11 @@ final class HostToXjcConverter {
/** Converts {@link Host} to {@link XjcRdeHost}. */
static XjcRdeHost convertExternalHost(Host model) {
return convertHostCommon(
model,
model.getPersistedCurrentSponsorRegistrarId(),
toDateTime(model.getLastTransferTime()));
model, model.getPersistedCurrentSponsorRegistrarId(), model.getLastTransferTime());
}
private static XjcRdeHost convertHostCommon(
Host model, String registrarId, DateTime lastTransferTime) {
Host model, String registrarId, Instant lastTransferTime) {
XjcRdeHost bean = new XjcRdeHost();
bean.setName(model.getHostName());
bean.setRoid(model.getRepoId());
@@ -78,7 +76,7 @@ final class HostToXjcConverter {
bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateRegistrarId(), null));
bean.setCrRr(RdeAdapter.convertRr(model.getCreationRegistrarId(), null));
bean.setClID(registrarId);
bean.setTrDate(lastTransferTime);
bean.setTrDate(toDateTime(lastTransferTime));
for (StatusValue status : model.getStatusValues()) {
// TODO(b/34844887): Remove when PENDING_TRANSFER is not persisted on host resources.
if (status.equals(StatusValue.PENDING_TRANSFER)) {

View File

@@ -25,7 +25,7 @@ import google.registry.config.RegistryConfig.Config;
import jakarta.inject.Inject;
import java.io.Closeable;
import java.net.URI;
import org.joda.time.Duration;
import java.time.Duration;
/**
* SFTP connection {@link Session} delegate that implements {@link Closeable}.
@@ -67,9 +67,9 @@ final class JSchSshSession implements Closeable {
if (url.getPass().isPresent()) {
session.setPassword(url.getPass().get());
}
session.setTimeout((int) sshTimeout.getMillis());
session.connect((int) sshTimeout.getMillis());
return new JSchSshSession(session, url, (int) sshTimeout.getMillis());
session.setTimeout((int) sshTimeout.toMillis());
session.connect((int) sshTimeout.toMillis());
return new JSchSshSession(session, url, (int) sshTimeout.toMillis());
}
}

View File

@@ -20,8 +20,8 @@ import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpProgressMonitor;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import java.time.Duration;
import java.time.Instant;
/** A progress monitor for SFTP operations that writes status to logs periodically. */
public class LoggingSftpProgressMonitor implements SftpProgressMonitor {
@@ -32,7 +32,7 @@ public class LoggingSftpProgressMonitor implements SftpProgressMonitor {
private final Clock clock;
private long bytesOfLastLog = 0;
private int callsSinceLastLog = 0;
private DateTime timeOfLastLog;
private Instant timeOfLastLog;
@Inject
LoggingSftpProgressMonitor(Clock clock) {
@@ -49,7 +49,7 @@ public class LoggingSftpProgressMonitor implements SftpProgressMonitor {
@Override
public void init(int op, String src, String dest, long max) {
timeOfLastLog = clock.nowUtc();
timeOfLastLog = clock.now();
logger.atInfo().log(
"Initiating SFTP transfer from '%s' to '%s' using mode %s, max size %,d bytes.",
src, dest, OPERATION_MODES.getOrDefault(op, "(unknown)"), max);
@@ -60,11 +60,11 @@ public class LoggingSftpProgressMonitor implements SftpProgressMonitor {
callsSinceLastLog++;
long bytesSinceLastLog = count - bytesOfLastLog;
if (bytesSinceLastLog > LOGGING_CHUNK_SIZE_BYTES) {
DateTime now = clock.nowUtc();
Instant now = clock.now();
logger.atInfo().log(
"%,d more bytes transmitted in %,d ms; %,d bytes in total. [%,d calls to count()]",
bytesSinceLastLog,
new Duration(timeOfLastLog, now).getMillis(),
Duration.between(timeOfLastLog, now).toMillis(),
count,
callsSinceLastLog);
bytesOfLastLog = count;

View File

@@ -22,6 +22,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serial;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.beam.sdk.coders.AtomicCoder;
@@ -29,8 +31,6 @@ import org.apache.beam.sdk.coders.BooleanCoder;
import org.apache.beam.sdk.coders.NullableCoder;
import org.apache.beam.sdk.coders.StringUtf8Coder;
import org.apache.beam.sdk.coders.VarIntCoder;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Container representing a single RDE or BRDA XML escrow deposit that needs to be created.
@@ -68,8 +68,8 @@ public record PendingDeposit(
@Nullable Integer revision)
implements Serializable {
public DateTime watermark() {
return DateTime.parse(watermarkStr);
public Instant watermark() {
return Instant.parse(watermarkStr);
}
public Duration interval() {
@@ -79,14 +79,14 @@ public record PendingDeposit(
@Serial private static final long serialVersionUID = 3141095605225904433L;
public static PendingDeposit create(
String tld, DateTime watermark, RdeMode mode, CursorType cursor, Duration interval) {
String tld, Instant watermark, RdeMode mode, CursorType cursor, Duration interval) {
return new PendingDeposit(
false, tld, watermark.toString(), mode, cursor, interval.toString(), null, null);
}
public static PendingDeposit createInManualOperation(
String tld,
DateTime watermark,
Instant watermark,
RdeMode mode,
String directoryWithTrailingSlash,
@Nullable Integer revision) {

View File

@@ -17,6 +17,9 @@ package google.registry.rde;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.plusDays;
import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoUnit.DAYS;
import com.google.common.collect.ImmutableSetMultimap;
import google.registry.config.RegistryConfig.Config;
@@ -28,9 +31,9 @@ import google.registry.model.tld.Tld.TldType;
import google.registry.model.tld.Tlds;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Utility class that determines which RDE or BRDA deposits need to be created.
@@ -64,25 +67,22 @@ public final class PendingDepositChecker {
return new ImmutableSetMultimap.Builder<String, PendingDeposit>()
.putAll(
getTldsAndWatermarksPendingDeposit(
RdeMode.FULL,
CursorType.RDE_STAGING,
rdeInterval,
clock.nowUtc().withTimeAtStartOfDay()))
RdeMode.FULL, CursorType.RDE_STAGING, rdeInterval, clock.now().truncatedTo(DAYS)))
.putAll(
getTldsAndWatermarksPendingDeposit(
RdeMode.THIN,
CursorType.BRDA,
brdaInterval,
advanceToDayOfWeek(clock.nowUtc().withTimeAtStartOfDay(), brdaDayOfWeek)))
advanceToDayOfWeek(clock.now().truncatedTo(DAYS), brdaDayOfWeek)))
.build();
}
private ImmutableSetMultimap<String, PendingDeposit> getTldsAndWatermarksPendingDeposit(
RdeMode mode, CursorType cursorType, Duration interval, DateTime startingPoint) {
checkArgument(interval.isLongerThan(Duration.ZERO));
RdeMode mode, CursorType cursorType, Duration interval, Instant startingPoint) {
checkArgument(interval.compareTo(Duration.ZERO) > 0);
ImmutableSetMultimap.Builder<String, PendingDeposit> builder =
new ImmutableSetMultimap.Builder<>();
DateTime now = clock.nowUtc();
Instant now = clock.now();
for (String tldStr : Tlds.getTldsOfType(TldType.REAL)) {
Tld tld = Tld.get(tldStr);
if (!tld.getEscrowEnabled()) {
@@ -91,9 +91,9 @@ public final class PendingDepositChecker {
// Avoid creating a transaction unless absolutely necessary.
Optional<Cursor> maybeCursor =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createScopedVKey(cursorType, tld)));
DateTime cursorValue = maybeCursor.map(Cursor::getCursorTime).orElse(startingPoint);
Instant cursorValue = maybeCursor.map(Cursor::getCursorTime).orElse(startingPoint);
if (isBeforeOrAt(cursorValue, now)) {
DateTime watermark =
Instant watermark =
maybeCursor
.map(Cursor::getCursorTime)
.orElse(transactionallyInitializeCursor(tld, cursorType, startingPoint));
@@ -105,8 +105,8 @@ public final class PendingDepositChecker {
return builder.build();
}
private DateTime transactionallyInitializeCursor(
final Tld tld, final CursorType cursorType, final DateTime initialValue) {
private Instant transactionallyInitializeCursor(
Tld tld, CursorType cursorType, Instant initialValue) {
return tm().transact(
() -> {
Optional<Cursor> maybeCursor =
@@ -119,9 +119,9 @@ public final class PendingDepositChecker {
});
}
private static DateTime advanceToDayOfWeek(DateTime date, int dayOfWeek) {
while (date.getDayOfWeek() != dayOfWeek) {
date = date.plusDays(1);
private static Instant advanceToDayOfWeek(Instant date, int dayOfWeek) {
while (date.atZone(UTC).getDayOfWeek().getValue() != dayOfWeek) {
date = plusDays(date, 1);
}
return date;
}

View File

@@ -14,6 +14,8 @@
package google.registry.rde;
import static google.registry.util.DateTimeUtils.toDateTime;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import google.registry.model.rde.RdeMode;
@@ -23,11 +25,11 @@ import google.registry.xjc.rdeheader.XjcRdeHeaderCount;
import google.registry.xjc.rdeheader.XjcRdeHeaderElement;
import google.registry.xjc.rdereport.XjcRdeReport;
import jakarta.inject.Inject;
import java.time.Instant;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.concurrent.NotThreadSafe;
import org.joda.time.DateTime;
/** Utility class for generating a single {@link XjcRdeHeader} while marshalling a deposit. */
@NotThreadSafe
@@ -61,13 +63,12 @@ public final class RdeCounter {
}
/** Returns an ICANN notification report as a JAXB object. */
public XjcRdeReport
makeReport(String id, DateTime watermark, XjcRdeHeader header, int revision) {
public XjcRdeReport makeReport(String id, Instant watermark, XjcRdeHeader header, int revision) {
XjcRdeReport report = new XjcRdeReport();
report.setId(id);
report.setKind(XjcRdeDepositTypeType.FULL);
report.setCrDate(watermark);
report.setWatermark(watermark);
report.setCrDate(toDateTime(watermark));
report.setWatermark(toDateTime(watermark));
report.setVersion(ICANN_REPORT_SPEC_VERSION);
report.setRydeSpecEscrow(URI_ESCROW);
report.setRydeSpecMapping(URI_MAPPING);

View File

@@ -15,6 +15,7 @@
package google.registry.rde;
import static com.google.common.base.Verify.verify;
import static google.registry.util.DateTimeUtils.toDateTime;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.flogger.FluentLogger;
@@ -41,9 +42,9 @@ import jakarta.xml.bind.MarshalException;
import java.io.ByteArrayOutputStream;
import java.io.Serial;
import java.io.Serializable;
import java.time.Instant;
import java.util.Collection;
import javax.annotation.concurrent.NotThreadSafe;
import org.joda.time.DateTime;
/** XML document <i>fragment</i> marshaller for RDE. */
@NotThreadSafe
@@ -61,7 +62,7 @@ public final class RdeMarshaller implements Serializable {
/** Returns top-portion of XML document. */
public String makeHeader(
String depositId, DateTime watermark, Collection<String> uris, int revision) {
String depositId, Instant watermark, Collection<String> uris, int revision) {
// We can't make JAXB marshal half an element. So we're going to use a kludge where we provide
// it with the minimum data necessary to marshal a deposit, and then cut it up by manually.
XjcRdeMenuType menu = new XjcRdeMenuType();
@@ -74,7 +75,7 @@ public final class RdeMarshaller implements Serializable {
contents.getContents().add(new XjcRdePolicyElement(policy));
XjcRdeDeposit deposit = new XjcRdeDeposit();
deposit.setId(depositId);
deposit.setWatermark(watermark);
deposit.setWatermark(toDateTime(watermark));
deposit.setType(XjcRdeDepositTypeType.FULL);
if (revision > 0) {
deposit.setResend(revision);

View File

@@ -17,8 +17,8 @@ package google.registry.rde;
import static google.registry.request.RequestParameters.extractBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredDatetimeParameter;
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
import static google.registry.request.RequestParameters.extractRequiredInstantParameter;
import static google.registry.request.RequestParameters.extractSetOfInstantParameters;
import static google.registry.request.RequestParameters.extractSetOfParameters;
import com.google.common.collect.ImmutableSet;
@@ -28,8 +28,8 @@ import dagger.Module;
import dagger.Provides;
import google.registry.request.Parameter;
import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
/** Dagger module for RDE package. */
@Module
@@ -49,14 +49,14 @@ public abstract class RdeModule {
@Provides
@Parameter(PARAM_WATERMARK)
static DateTime provideWatermark(HttpServletRequest req) {
return extractRequiredDatetimeParameter(req, PARAM_WATERMARK);
static Instant provideWatermark(HttpServletRequest req) {
return extractRequiredInstantParameter(req, PARAM_WATERMARK);
}
@Provides
@Parameter(PARAM_WATERMARKS)
static ImmutableSet<DateTime> provideWatermarks(HttpServletRequest req) {
return extractSetOfDatetimeParameters(req, PARAM_WATERMARKS);
static ImmutableSet<Instant> provideWatermarks(HttpServletRequest req) {
return extractSetOfInstantParameters(req, PARAM_WATERMARKS);
}
@Provides

View File

@@ -14,6 +14,7 @@
package google.registry.rde;
import static com.google.common.base.Verify.verify;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static google.registry.model.common.Cursor.getCursorTimeOrStartOfTime;
@@ -44,10 +45,10 @@ import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Action that uploads a small XML RDE report to ICANN after {@link RdeUploadAction} has finished.
@@ -81,13 +82,13 @@ public final class RdeReportAction implements Runnable, EscrowTask {
}
@Override
public void runWithLock(DateTime watermark) throws Exception {
public void runWithLock(Instant watermark) throws Exception {
Optional<Cursor> cursor =
tm().transact(
() ->
tm().loadByKeyIfPresent(
Cursor.createScopedVKey(CursorType.RDE_UPLOAD, Tld.get(tld))));
DateTime cursorTime = getCursorTimeOrStartOfTime(cursor);
Instant cursorTime = getCursorTimeOrStartOfTime(cursor);
if (isBeforeOrAt(cursorTime, watermark)) {
throw new NoContentException(
String.format(

View File

@@ -18,11 +18,13 @@ import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMulti
import static google.registry.beam.BeamUtils.createJobName;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.LOWERCASE_TIMESTAMP_FORMATTER;
import static google.registry.xml.ValidationMode.LENIENT;
import static google.registry.xml.ValidationMode.STRICT;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.util.function.Function.identity;
import com.google.api.services.dataflow.Dataflow;
@@ -59,9 +61,9 @@ import google.registry.util.RegistryEnvironment;
import google.registry.xml.ValidationMode;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Action that kicks off a Dataflow job to stage escrow deposit XML files on GCS for RDE/BRDA for
@@ -237,7 +239,11 @@ public final class RdeStagingAction implements Runnable {
@Inject @Parameter(RdeModule.PARAM_DIRECTORY) Optional<String> directory;
@Inject @Parameter(RdeModule.PARAM_MODE) ImmutableSet<String> modeStrings;
@Inject @Parameter(RequestParameters.PARAM_TLDS) ImmutableSet<String> tlds;
@Inject @Parameter(RdeModule.PARAM_WATERMARKS) ImmutableSet<DateTime> watermarks;
@Inject
@Parameter(RdeModule.PARAM_WATERMARKS)
ImmutableSet<Instant> watermarks;
@Inject @Parameter(RdeModule.PARAM_REVISION) Optional<Integer> revision;
@Inject @Parameter(RdeModule.PARAM_LENIENT) boolean lenient;
@Inject @Key("rdeStagingEncryptionKey") byte[] stagingKeyBytes;
@@ -271,7 +277,7 @@ public final class RdeStagingAction implements Runnable {
.setJobName(
createJobName(
String.format(
"rde-%s", watermark.toString("yyyy-MM-dd't'HH-mm-ss'z'")),
"rde-%s", LOWERCASE_TIMESTAMP_FORMATTER.format(watermark)),
clock))
.setContainerSpecGcsPath(
String.format("%s/%s_metadata.json", stagingBucketUrl, PIPELINE_NAME))
@@ -340,7 +346,7 @@ public final class RdeStagingAction implements Runnable {
Multimaps.filterValues(
pendingDepositChecker.getTldsAndWatermarksPendingDepositForRdeAndBrda(),
pending -> {
if (clock.nowUtc().isBefore(pending.watermark().plus(transactionCooldown))) {
if (clock.now().isBefore(pending.watermark().plus(transactionCooldown))) {
logger.atInfo().log(
"Ignoring within %s cooldown: %s", transactionCooldown, pending);
return false;
@@ -384,8 +390,8 @@ public final class RdeStagingAction implements Runnable {
// In theory, BRDA deposits should be on a specific day of the week, but in manual mode, let the
// user create deposits on other days. But dates should definitely be at the start of the day;
// otherwise, confusion is likely.
for (DateTime watermark : watermarks) {
if (!watermark.equals(watermark.withTimeAtStartOfDay())) {
for (Instant watermark : watermarks) {
if (!watermark.equals(watermark.truncatedTo(DAYS))) {
throw new BadRequestException("Watermarks must be at the start of a day.");
}
}
@@ -398,7 +404,7 @@ public final class RdeStagingAction implements Runnable {
new ImmutableSetMultimap.Builder<>();
for (String tld : tlds) {
for (DateTime watermark : watermarks) {
for (Instant watermark : watermarks) {
for (RdeMode mode : modes) {
pendingsBuilder.put(
tld,

View File

@@ -14,6 +14,7 @@
package google.registry.rde;
import static com.google.common.base.Verify.verify;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static com.jcraft.jsch.ChannelSftp.OVERWRITE;
@@ -25,7 +26,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.rde.RdeModule.RDE_REPORT_QUEUE;
import static google.registry.rde.RdeUtils.findMostRecentPrefixForWatermark;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static java.util.Arrays.asList;
@@ -65,12 +66,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Action that securely uploads an RDE XML file from Cloud Storage to a trusted third party (such as
@@ -133,7 +134,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
}
@Override
public void runWithLock(final DateTime watermark) throws Exception {
public void runWithLock(Instant watermark) throws Exception {
// If a prefix is not provided,try to determine the prefix. This should only happen when the RDE
// upload cron job runs to catch up any un-retried (i. e. expected) RDE failures.
String actualPrefix =
@@ -142,7 +143,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
Optional<Cursor> cursor =
tm().transact(
() -> tm().loadByKeyIfPresent(Cursor.createScopedVKey(RDE_STAGING, Tld.get(tld))));
DateTime stagingCursorTime = getCursorTimeOrStartOfTime(cursor);
Instant stagingCursorTime = getCursorTimeOrStartOfTime(cursor);
if (isBeforeOrAt(stagingCursorTime, watermark)) {
throw new NoContentException(
String.format(
@@ -150,23 +151,23 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
+ "last RDE staging completion was before %s",
tld, watermark, stagingCursorTime));
}
DateTime sftpCursorTime =
Instant sftpCursorTime =
tm().transact(
() ->
tm().loadByKeyIfPresent(Cursor.createScopedVKey(RDE_UPLOAD_SFTP, Tld.get(tld))))
.map(Cursor::getCursorTime)
.orElse(START_OF_TIME);
Duration timeSinceLastSftp = new Duration(sftpCursorTime, clock.nowUtc());
if (timeSinceLastSftp.isShorterThan(sftpCooldown)) {
.orElse(START_INSTANT);
Duration timeSinceLastSftp = Duration.between(sftpCursorTime, clock.now());
if (timeSinceLastSftp.compareTo(sftpCooldown) < 0) {
throw new NoContentException(
String.format(
"Waiting on %d minute SFTP cooldown for TLD %s to send %s upload; "
+ "last upload attempt was at %s (%d minutes ago)",
sftpCooldown.getStandardMinutes(),
sftpCooldown.toMinutes(),
tld,
watermark,
sftpCursorTime,
timeSinceLastSftp.getStandardMinutes()));
timeSinceLastSftp.toMinutes()));
}
int revision =
RdeRevision.getCurrentRevision(tld, watermark, FULL)
@@ -189,10 +190,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
logger.atInfo().log(
"Updating RDE cursor '%s' for TLD '%s' following successful upload.", RDE_UPLOAD_SFTP, tld);
tm().transact(
() ->
tm().put(
Cursor.createScoped(
RDE_UPLOAD_SFTP, tm().getTransactionTime(), Tld.get(tld))));
() -> tm().put(Cursor.createScoped(RDE_UPLOAD_SFTP, tm().getTxTime(), Tld.get(tld))));
response.setContentType(PLAIN_TEXT_UTF_8);
response.setPayload(String.format("OK %s %s\n", tld, watermark));
}
@@ -222,7 +220,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
*/
@VisibleForTesting
private void upload(
BlobId xmlFile, long xmlLength, DateTime watermark, String name, String nameWithoutPrefix)
BlobId xmlFile, long xmlLength, Instant watermark, String name, String nameWithoutPrefix)
throws Exception {
logger.atInfo().log("Uploading XML file '%s' to remote path '%s'.", xmlFile, uploadUrl);
try (InputStream gcsInput = gcsUtils.openInputStream(xmlFile);

View File

@@ -14,6 +14,7 @@
package google.registry.rde;
import static google.registry.util.DateTimeUtils.LOWERCASE_TIMESTAMP_FORMATTER;
import static google.registry.util.HexDumper.dumpHex;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -28,10 +29,7 @@ import google.registry.xml.XmlException;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.joda.time.DateTime;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.time.Instant;
/** Helper methods for RDE. */
public final class RdeUtils {
@@ -42,15 +40,11 @@ public final class RdeUtils {
/** Regular expression for extracting creation timestamp from a raw XML deposit. */
private static final Pattern WATERMARK_PATTERN = Pattern.compile("[<:]watermark>\\s*([^<\\s]+)");
/** Standard ISO date/time formatter without milliseconds. Used for watermarks. */
private static final DateTimeFormatter DATETIME_FORMATTER =
ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();
/**
* Look at some bytes from {@code xmlInput} to ensure it appears to be a FULL XML deposit and
* then use a regular expression to extract the watermark timestamp which is returned.
* Look at some bytes from {@code xmlInput} to ensure it appears to be a FULL XML deposit and then
* use a regular expression to extract the watermark timestamp which is returned.
*/
public static DateTime peekWatermark(BufferedInputStream xmlInput)
public static Instant peekWatermark(BufferedInputStream xmlInput)
throws IOException, XmlException {
xmlInput.mark(PEEK_SIZE);
byte[] peek = new byte[PEEK_SIZE];
@@ -70,16 +64,16 @@ public final class RdeUtils {
if (!watermarkMatcher.find()) {
throw new XmlException("Could not find RDE watermark in XML");
}
return DATETIME_FORMATTER.parseDateTime(watermarkMatcher.group(1));
return Instant.parse(watermarkMatcher.group(1));
}
/** Find the most recent folder in the given GCS bucket for the given watermark. */
public static String findMostRecentPrefixForWatermark(
DateTime watermark, String bucket, String tld, GcsUtils gcsUtils) throws NoContentException {
Instant watermark, String bucket, String tld, GcsUtils gcsUtils) throws NoContentException {
// The prefix is always in the format of: rde-2022-02-21t00-00-00z-2022-02-21t00-07-33z, where
// the first datetime is the watermark and the second one is the time when the RDE beam job
// launched. We search for the latest folder that starts with "rde-[watermark]".
String partialPrefix = String.format("rde-%s", watermark.toString("yyyy-MM-dd't'HH-mm-ss'z'"));
String partialPrefix = String.format("rde-%s", LOWERCASE_TIMESTAMP_FORMATTER.format(watermark));
String latestFilenameSuffix = null;
try {
latestFilenameSuffix =
@@ -106,8 +100,8 @@ public final class RdeUtils {
* big-endian byte-array which is then converted to a base32 string without padding that's no
* longer than 13 chars because {@code 13 = Ceiling[Log[32, 2^64]]}. How lucky!
*/
public static String timestampToId(ReadableInstant timestamp) {
byte[] bytes = ByteBuffer.allocate(8).putLong(timestamp.getMillis()).array();
public static String timestampToId(Instant timestamp) {
byte[] bytes = ByteBuffer.allocate(8).putLong(timestamp.toEpochMilli()).array();
return BaseEncoding.base32().omitPadding().encode(bytes);
}

View File

@@ -26,12 +26,12 @@ import com.google.common.io.Closer;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.time.Instant;
import java.util.Collection;
import javax.annotation.concurrent.NotThreadSafe;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.joda.time.DateTime;
/**
* Stream that performs the full RyDE encryption.
@@ -63,7 +63,7 @@ public final class RydeEncoder extends FilterOutputStream {
OutputStream sigOutput,
long dataLength,
String filenamePrefix,
DateTime modified,
Instant modified,
PGPKeyPair signingKey,
Collection<PGPPublicKey> receiverKeys) {
super(null);
@@ -110,7 +110,7 @@ public final class RydeEncoder extends FilterOutputStream {
OutputStream sigOutput;
Long dataLength;
String filenamePrefix;
DateTime modified;
Instant modified;
PGPKeyPair signingKey;
ImmutableList<PGPPublicKey> receiverKeys;
@@ -131,7 +131,7 @@ public final class RydeEncoder extends FilterOutputStream {
}
/** Sets the information about the unencoded data that will follow. */
public Builder setFileMetadata(String filenamePrefix, long dataLength, DateTime modified) {
public Builder setFileMetadata(String filenamePrefix, long dataLength, Instant modified) {
this.filenamePrefix = filenamePrefix;
this.dataLength = dataLength;
this.modified = modified;

View File

@@ -15,18 +15,18 @@
package google.registry.rde;
import static org.bouncycastle.openpgp.PGPLiteralData.BINARY;
import static org.joda.time.DateTimeZone.UTC;
import google.registry.util.ImprovedInputStream;
import google.registry.util.ImprovedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.time.Instant;
import javax.annotation.CheckReturnValue;
import javax.annotation.WillNotClose;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
import org.joda.time.DateTime;
/**
* Input/Output stream for reading/writing PGP literal data layer.
@@ -54,12 +54,12 @@ final class RydeFileEncoding {
*/
@CheckReturnValue
static ImprovedOutputStream openPgpFileWriter(
@WillNotClose OutputStream os, String filename, DateTime modified) {
@WillNotClose OutputStream os, String filename, Instant modified) {
try {
return new ImprovedOutputStream(
"PgpFileWriter",
new PGPLiteralDataGenerator()
.open(os, BINARY, filename, modified.toDate(), new byte[BUFFER_SIZE]));
.open(os, BINARY, filename, Timestamp.from(modified), new byte[BUFFER_SIZE]));
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -68,12 +68,12 @@ final class RydeFileEncoding {
/** Input stream to a PGP file's data that also holds the file's metadata. */
static class PgpFileInputStream extends ImprovedInputStream {
private final String filename;
private final DateTime modified;
private final Instant modified;
private PgpFileInputStream(PGPLiteralData literal) {
super("PgpFileReader", literal.getDataStream());
filename = literal.getFileName();
modified = new DateTime(literal.getModificationTime(), UTC);
modified = literal.getModificationTime().toInstant();
}
/** Returns the name of the original file. */
@@ -82,7 +82,7 @@ final class RydeFileEncoding {
}
/** Returns the time this file was created or modified. */
DateTime getModified() {
Instant getModified() {
return modified;
}
}

View File

@@ -16,6 +16,8 @@ package google.registry.rde;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.io.ByteStreams;
import google.registry.util.ImprovedInputStream;
@@ -24,9 +26,9 @@ import google.registry.util.PosixTarHeader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import javax.annotation.CheckReturnValue;
import javax.annotation.WillNotClose;
import org.joda.time.DateTime;
/** Single-file POSIX tar archive creator that wraps an {@link OutputStream}. */
final class RydeTar {
@@ -41,18 +43,19 @@ final class RydeTar {
*/
@CheckReturnValue
static ImprovedOutputStream openTarWriter(
@WillNotClose OutputStream os, long expectedSize, String filename, DateTime modified) {
@WillNotClose OutputStream os, long expectedSize, String filename, Instant modified) {
checkArgument(expectedSize >= 0);
checkArgument(filename.endsWith(".xml"),
"Ryde expects tar archive to contain a filename with an '.xml' extension.");
try {
os.write(new PosixTarHeader.Builder()
.setName(filename)
.setSize(expectedSize)
.setMtime(modified)
.build()
.getBytes());
os.write(
new PosixTarHeader.Builder()
.setName(filename)
.setSize(expectedSize)
.setMtime(toDateTime(modified))
.build()
.getBytes());
return new ImprovedOutputStream("RydeTarWriter", os) {
/** Writes the end of archive marker. */
@Override
@@ -92,8 +95,8 @@ final class RydeTar {
}
/** Returns the creation/modification time of the file archived in this TAR. */
DateTime getModified() {
return header.getMtime();
Instant getModified() {
return toInstant(header.getMtime());
}
}

View File

@@ -17,6 +17,7 @@ package google.registry.reporting;
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import static java.time.ZoneOffset.UTC;
import com.google.api.services.dataflow.Dataflow;
import dagger.Module;
@@ -28,11 +29,11 @@ import google.registry.request.Parameter;
import google.registry.util.Clock;
import google.registry.util.GoogleCredentialsBundle;
import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Optional;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.YearMonth;
import org.joda.time.format.ISODateTimeFormat;
/** Dagger module for injecting common settings for all reporting tasks. */
@Module
@@ -84,8 +85,9 @@ public class ReportingModule {
static Optional<YearMonth> provideYearMonthOptional(HttpServletRequest req) {
Optional<String> optionalYearMonthStr = extractOptionalParameter(req, PARAM_YEAR_MONTH);
try {
return optionalYearMonthStr.map(s -> YearMonth.parse(s, ISODateTimeFormat.yearMonth()));
} catch (IllegalArgumentException e) {
return optionalYearMonthStr.map(
s -> YearMonth.parse(s, DateTimeFormatter.ofPattern("yyyy-MM")));
} catch (IllegalArgumentException | DateTimeParseException e) {
throw new BadRequestException(
String.format(
"yearMonth must be in yyyy-MM format, got %s instead",
@@ -101,7 +103,7 @@ public class ReportingModule {
static YearMonth provideYearMonth(
@Parameter(PARAM_YEAR_MONTH) Optional<YearMonth> yearMonthOptional,
@Parameter(PARAM_DATE) LocalDate date) {
return yearMonthOptional.orElseGet(() -> new YearMonth(date.minusMonths(1)));
return yearMonthOptional.orElseGet(() -> YearMonth.from(date.minusMonths(1)));
}
/** Extracts an optional date in yyyy-MM-dd format from the request. */
@@ -110,8 +112,8 @@ public class ReportingModule {
static Optional<LocalDate> provideDateOptional(HttpServletRequest req) {
Optional<String> optionalDateString = extractOptionalParameter(req, PARAM_DATE);
try {
return optionalDateString.map(s -> LocalDate.parse(s, ISODateTimeFormat.yearMonthDay()));
} catch (IllegalArgumentException e) {
return optionalDateString.map(s -> LocalDate.parse(s, DateTimeFormatter.ISO_LOCAL_DATE));
} catch (IllegalArgumentException | DateTimeParseException e) {
throw new BadRequestException(
String.format(
"date must be in yyyy-MM-dd format, got %s instead",
@@ -127,8 +129,7 @@ public class ReportingModule {
@Provides
@Parameter(PARAM_DATE)
static LocalDate provideDate(HttpServletRequest req, Clock clock) {
return provideDateOptional(req)
.orElseGet(() -> new LocalDate(clock.nowUtc(), DateTimeZone.UTC));
return provideDateOptional(req).orElseGet(() -> LocalDate.ofInstant(clock.now(), UTC));
}
/** Constructs a {@link Dataflow} API client with default settings. */

View File

@@ -28,8 +28,8 @@ import google.registry.reporting.billing.BillingModule.InvoiceDirectoryPrefix;
import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.InternetAddress;
import java.time.YearMonth;
import java.util.Optional;
import org.joda.time.YearMonth;
/** Utility functions for sending emails involving monthly invoices. */
public class BillingEmailUtils {

View File

@@ -25,7 +25,7 @@ import jakarta.inject.Qualifier;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import org.joda.time.YearMonth;
import java.time.YearMonth;
/** Module for dependencies required by monthly billing actions. */
@Module

View File

@@ -39,8 +39,8 @@ import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import java.io.IOException;
import org.joda.time.Duration;
import org.joda.time.YearMonth;
import java.time.Duration;
import java.time.YearMonth;
/**
* Invokes the {@code InvoicingPipeline} beam template via the REST api, and enqueues the {@link
@@ -114,7 +114,7 @@ public class GenerateInvoicesAction implements Runnable {
String.format("%s/%s_metadata.json", stagingBucketUrl, PIPELINE_NAME))
.setParameters(
new ImmutableMap.Builder<String, String>()
.put("yearMonth", yearMonth.toString("yyyy-MM"))
.put("yearMonth", yearMonth.toString())
.put("invoiceFilePrefix", invoiceFilePrefix)
.put("billingBucketUrl", billingBucketUrl)
.put("registryEnvironment", RegistryEnvironment.get().name())
@@ -145,7 +145,7 @@ public class GenerateInvoicesAction implements Runnable {
jobId,
ReportingModule.PARAM_YEAR_MONTH,
yearMonth.toString()),
Duration.standardMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES)));
Duration.ofMinutes(ReportingModule.ENQUEUE_DELAY_MINUTES)));
}
response.setStatus(SC_OK);
response.setPayload(String.format("Launched invoicing pipeline: %s", jobId));

View File

@@ -35,7 +35,7 @@ import google.registry.request.Response;
import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import java.io.IOException;
import org.joda.time.YearMonth;
import java.time.YearMonth;
/**
* Uploads the results of the {@link google.registry.beam.billing.InvoicingPipeline}.

View File

@@ -23,10 +23,9 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.util.SqlTemplate;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.joda.time.LocalDate;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
/** Utility class that produces SQL queries used to generate activity reports from Bigquery. */
public final class ActivityReportingQueryBuilder implements QueryBuilder {
@@ -64,9 +63,9 @@ public final class ActivityReportingQueryBuilder implements QueryBuilder {
/** Sets the month we're doing activity reporting for, and returns the view query map. */
@Override
public ImmutableMap<String, String> getViewQueryMap(YearMonth yearMonth) {
LocalDate firstDayOfMonth = yearMonth.toLocalDate(1);
LocalDate firstDayOfMonth = yearMonth.atDay(1);
// The pattern-matching is inclusive, so we subtract 1 day to only report that month's data.
LocalDate lastDayOfMonth = yearMonth.toLocalDate(1).plusMonths(1).minusDays(1);
LocalDate lastDayOfMonth = yearMonth.atDay(1).plusMonths(1).minusDays(1);
ImmutableMap.Builder<String, String> queriesBuilder = ImmutableMap.builder();
String operationalRegistrarsQuery;
@@ -81,20 +80,20 @@ public final class ActivityReportingQueryBuilder implements QueryBuilder {
queriesBuilder.put(getTableName(DNS_COUNTS, yearMonth), dnsCountsQuery);
// Convert reportingMonth into YYYYMMDD format for Bigquery table partition pattern-matching.
DateTimeFormatter logTableFormatter = DateTimeFormat.forPattern("yyyyMMdd");
DateTimeFormatter logTableFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String monthlyLogsQuery =
SqlTemplate.create(getQueryFromFile(MONTHLY_LOGS + ".sql"))
.put("PROJECT_ID", projectId)
.put("FIRST_DAY_OF_MONTH", logTableFormatter.print(firstDayOfMonth))
.put("LAST_DAY_OF_MONTH", logTableFormatter.print(lastDayOfMonth))
.put("FIRST_DAY_OF_MONTH", logTableFormatter.format(firstDayOfMonth))
.put("LAST_DAY_OF_MONTH", logTableFormatter.format(lastDayOfMonth))
.build();
queriesBuilder.put(getTableName(MONTHLY_LOGS, yearMonth), monthlyLogsQuery);
String eppQuery =
SqlTemplate.create(getQueryFromFile(EPP_METRICS + ".sql"))
.put("PROJECT_ID", projectId)
.put("FIRST_DAY_OF_MONTH", logTableFormatter.print(firstDayOfMonth))
.put("LAST_DAY_OF_MONTH", logTableFormatter.print(lastDayOfMonth))
.put("FIRST_DAY_OF_MONTH", logTableFormatter.format(firstDayOfMonth))
.put("LAST_DAY_OF_MONTH", logTableFormatter.format(lastDayOfMonth))
.build();
queriesBuilder.put(getTableName(EPP_METRICS, yearMonth), eppQuery);

View File

@@ -18,9 +18,9 @@ import com.google.common.io.Resources;
import google.registry.bigquery.BigqueryUtils.TableType;
import google.registry.util.ResourceUtils;
import google.registry.util.SqlTemplate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutionException;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
/**
* DNS Count query that relies on a table Cloud DNS publishes internally to Google.
@@ -76,7 +76,7 @@ public class CloudDnsCountQueryCoordinator extends DnsCountQueryCoordinator {
.put("PROJECT_ID", projectId)
.put("DATASET_ID", icannReportingDataSet)
.put("TABLE_ID", TABLE_ID)
.put("YEAR_MONTH", DateTimeFormat.forPattern("yyyyMM").print(yearMonth));
.put("YEAR_MONTH", DateTimeFormatter.ofPattern("yyyyMM").format(yearMonth));
return queryTemplate.build();
}
}

View File

@@ -25,7 +25,7 @@ import google.registry.bigquery.BigqueryConnection;
import google.registry.config.RegistryConfig.Config;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.joda.time.YearMonth;
import java.time.YearMonth;
/**
* Methods for preparing and querying DNS statistics.

View File

@@ -16,7 +16,7 @@ package google.registry.reporting.icann;
import google.registry.util.ResourceUtils;
import google.registry.util.SqlTemplate;
import org.joda.time.YearMonth;
import java.time.YearMonth;
/** DNS Count query where returned values are all -1. */
public class DummyDnsCountQueryCoordinator extends DnsCountQueryCoordinator {

View File

@@ -40,9 +40,9 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
/**
* Class that uploads a CSV file to ICANN's endpoint via an HTTP PUT call.
@@ -148,7 +148,7 @@ public class IcannHttpReporter {
ReportType reportType = ReportType.valueOf(Ascii.toUpperCase(elements.get(0)));
// Re-add hyphen between year and month, because ICANN is inconsistent between filename and URL
String yearMonth =
YearMonth.parse(elements.get(1), DateTimeFormat.forPattern("yyyyMM")).toString("yyyy-MM");
YearMonth.parse(elements.get(1), DateTimeFormatter.ofPattern("yyyyMM")).toString();
return new URL(String.format("%s/%s/%s", getUrlPrefix(reportType), tld, yearMonth));
}

View File

@@ -28,8 +28,8 @@ import google.registry.request.HttpException.BadRequestException;
import google.registry.request.Parameter;
import jakarta.inject.Named;
import jakarta.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.Optional;
import org.joda.time.Duration;
/** Module for dependencies required by ICANN monthly transactions/activity reporting. */
@Module
@@ -101,7 +101,7 @@ public final class IcannReportingModule {
.setExecutorService(MoreExecutors.newDirectExecutorService())
.setDatasetId(icannReportingDataSet)
.setOverwrite(true)
.setPollInterval(Duration.standardSeconds(1))
.setPollInterval(Duration.ofSeconds(1))
.build();
} catch (Throwable e) {
throw new RuntimeException("Could not initialize BigqueryConnection!", e);

View File

@@ -38,6 +38,8 @@ import google.registry.gcs.GcsUtils;
import google.registry.reporting.icann.IcannReportingModule.ReportType;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -47,8 +49,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
/**
* Class containing methods for staging ICANN monthly reports on GCS.
@@ -258,7 +258,7 @@ public class IcannReportingStager {
"%s-%s-%s.csv",
tld,
Ascii.toLowerCase(reportType.toString()),
DateTimeFormat.forPattern("yyyyMM").print(yearMonth));
DateTimeFormatter.ofPattern("yyyyMM").format(yearMonth));
final BlobId gcsFilename =
BlobId.of(reportingBucket, String.format("%s/%s", subdir, reportFilename));
gcsUtils.createFromBytes(gcsFilename, reportBytes);

View File

@@ -41,10 +41,10 @@ import google.registry.util.EmailMessage;
import google.registry.util.Retrier;
import jakarta.inject.Inject;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import org.joda.time.Duration;
import org.joda.time.YearMonth;
import org.joda.time.format.DateTimeFormat;
/**
* Action that generates monthly ICANN activity and transactions reports.
@@ -138,7 +138,7 @@ public final class IcannReportingStagingAction implements Runnable {
cloudTasksUtils.enqueue(
CRON_QUEUE,
cloudTasksUtils.createTaskWithDelay(
IcannReportingUploadAction.class, POST, null, Duration.standardMinutes(2)));
IcannReportingUploadAction.class, POST, null, Duration.ofMinutes(2)));
} else {
logger.atInfo().log("Would have enqueued report upload");
}
@@ -166,6 +166,7 @@ public final class IcannReportingStagingAction implements Runnable {
return IcannReportingModule.checkSubdirValid(
overrideSubdir.orElse(
String.format(
"%s/%s", DEFAULT_SUBDIR, DateTimeFormat.forPattern("yyyy-MM").print(yearMonth))));
"%s/%s",
DEFAULT_SUBDIR, DateTimeFormatter.ofPattern("yyyy-MM").format(yearMonth))));
}
}

Some files were not shown because too many files have changed in this diff Show More