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:
12
GEMINI.md
12
GEMINI.md
@@ -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.
|
||||
|
||||
@@ -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}. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
123
console-webapp/package-lock.json
generated
123
console-webapp/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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?");
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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).",
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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], "
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.persistence.converter;
|
||||
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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}.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user