1
0
mirror of https://github.com/google/nomulus synced 2026-05-15 12:21:43 +00:00

Compare commits

...

11 Commits

Author SHA1 Message Date
Juan Celhay
0998d5485c add additional label to nomulus deployments (#3046) 2026-05-14 20:01:18 +00:00
Juan Celhay
1bff89085b Build Cloud Deploy artifacts via Cloud Build job (#3044)
* add README

* updating comments/files
2026-05-14 15:35:32 +00:00
Weimin Yu
d9d83205c7 Verify user can send email (#3045)
Change the CannedScriptExecutionAction to send a email
message as a user-specified G workspace user.

This change is part of b/510340944, to verify that a newly
added dedicated sender is properly set up for sending emails.

Once the new sender is tested, the changes in this PR can be
dropped.
2026-05-14 15:13:57 +00:00
Ben McIlwain
56fe588b56 Complete Joda-Time to java.time migration (#3039)
This completes the exhaustive refactoring of foundational temporal types from Joda-Time to the native java.time API across the entire codebase.

- Replaced org.joda.time.DateTime, Instant, LocalDate, and Duration with java.time equivalents.
- Audited and updated Clock implementations (FakeClock, SystemClock). Added nowMillis(), nowDate(), and nowDateTime() to eliminate repetitive conversions and maintain parallel naming.
- Replaced ZonedDateTime with OffsetDateTime globally per go/avoid-zdt. OffsetDateTime is a better fit as we use a hardcoded ZoneOffset.UTC throughout the system, making geographical time zone rules (like daylight saving time) irrelevant and preventing serialization ambiguities. Added a presubmit check.
- Completely removed all transitional bridge methods from DateTimeUtils and deleted obsolete converters (e.g., DateTimeConverter).
- Updated testing infrastructure, Apache Beam pipelines, custom JCommander parameters, and networking modules to solely rely on java.time primitives.
- Retained the lone necessary org.joda.time.Instant usage in SafeBrowsingTransforms required by the Apache Beam API.
- Cleared Gradle lockfiles and removed the joda-time dependency entirely from the build configuration.
2026-05-13 16:07:19 +00:00
gbrodman
b33c2f4874 Add rdeEppParams to RDE output (#3041)
We mostly had the xsd code for this already, we just never actually used
it and added it to the output. Note that I had to make some changes to
allow the expected format (where some of the elements are empty).
2026-05-13 14:38:07 +00:00
gbrodman
b8f14fef8d Update Hibernate deps to 7.3.4 (#3040)
The fix for https://hibernate.atlassian.net/browse/HHH-20276 was
included in 7.3.4 and will be included in version 8 in the future. 8.x
is still in alpha though so we don't want to use it yet.
2026-05-12 17:58:49 +00:00
gbrodman
8047d1e3e3 Use remote caches in RDAP queries (#3034)
Note that this primarily affects domain lookups. We choose to use the
remote cache for hosts based on repo ID (not host name), so the remote
caches are not particularly useful for host lookups. We chose this
because the number of domain queries is orders of magnitude higher than
the number of host queries.
2026-05-12 16:28:36 +00:00
gbrodman
5854ccf00d Add (remote) cache metrics (#3033)
This only applies to the CacheModule-provided caches because we don't
want to have to deal with all the various other caches. We'll want to
know the various ratios between types of cache hits/misses when
evaluating the usefulness of the remote caching.
2026-05-11 18:19:52 +00:00
Ben McIlwain
b69d51add1 Refactor foundational temporal types to java.time (#3036)
* Migrates core classes (Clock, Sleeper, TransactionManager) and extensive domain models from Joda-Time to java.time.
* Restores original public API method names while substituting parameters/return values with `java.time.Instant`.
* Updates JAXB XJC `bindings.xjb` to natively generate `java.time.Instant` and `java.time.LocalDate`, eliminating `toDateTime` wrapper methods.
* Fixes XML serializers (`DateAdapter`) to robustly convert OffsetDateTime timezone strings to UTC.
* Cleans up redundant imports and Checkstyle failures across the codebase.

Remaining Joda-Time surface area to migrate in future tasks:
* Command-line parameters (e.g. `DateTimeParameter`, `DateParameter`, `IntervalParameter`) in `google.registry.tools.params`.
* EPP/RDAP flow testing infrastructure (`EppTestCase`, `RdapActionBaseTestCase`, `FlowTestCase`).
* Beam pipelines and Load Testing modules (`Spec11PipelineTest`, `RdePipelineTest`, `RegistryJpaReadTest`, `EppClient`).
* Utility bridges and converters (`DateTimeUtils.toDateTime/toInstant`, `DateTimeConverter`, `UtcDateTimeAdapter`).
* Remaining UI Console tests and Actions.
2026-05-08 21:04:00 +00:00
Weimin Yu
60d3653b46 Add smoke test for BEAM pipelines (#3037)
Created a smoke test to cover unit test gaps wrt BEAM:
- The Java and SDK compatibility in the pipeline container image
- The JPA setup in the pipelines

Both issues above can only be tested in a real pipeline.

This PR defines a new pipeline that performs a lightweight SQL
query and minimal processing. The build process can launch it
in a test environment to verify that the pipelines in the build
can run. The run script is also provided.
2026-05-07 20:41:13 +00:00
gbrodman
80eefc6498 Fix remote cache prefixing by handling it all in the Jedis client (#3035)
Found this out while testing metrics. In hindsight, not the best idea to
handle prefixing outside of the client itself. Instead, we'll enforce
the prefixing closer to Valkey, all in one place.
2026-05-07 20:28:56 +00:00
529 changed files with 4040 additions and 5274 deletions

8
.gitignore vendored
View File

@@ -1,5 +1,5 @@
/bazel-*
**/.idea/**
.jetskicli
######################################################################
# Java Ignores
@@ -115,11 +115,5 @@ cloudbuild-caches/
**/node_modules/**
/repos/
# Compiled JS/CSS code
core/**/registrar_bin*.js
core/**/registrar_dbg*.js
core/**/registrar_bin*.css
core/**/registrar_dbg*.css
# jEnv
.java-version

View File

@@ -13,21 +13,14 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Verification**: Before finalizing any change, scan the imports section for redundancy.
- **License Headers**: When creating new files, ensure the license header uses the current year (e.g., 2026). Existing files should retain their original year.
## 2. Time and Precision Handling (java.time Migration)
## 2. Time and Precision Handling
- **Idiomatic java.time Usage:** Avoid redundant conversions between `Instant` and `DateTime`. If a field or parameter is an `Instant`, use it directly. Do not convert to `DateTime` just to call a deprecated method if an `Instant` alternative exists or can be easily created. Furthermore, you should not call `toInstant()` or `toDateTime()` conversion methods when not strictly necessary; always prefer to use an alternative method that returns the correct type if one exists (e.g. use `tm().getTxTime()` which returns an `Instant` instead of calling `tm().getTransactionTime().toInstant()`).
- **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 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).
- **Clock Injection:**
- Avoid direct calls to `Instant.now()`, `DateTime.now()`, `ZonedDateTime.now()`, or `System.currentTimeMillis()`.
- Avoid direct calls to `Instant.now()`, `OffsetDateTime.now()`, or `System.currentTimeMillis()`.
- Inject `google.registry.util.Clock` (production) or `google.registry.testing.FakeClock` (tests).
- Use `clock.nowDate()` to get a `ZonedDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time. Avoid using the Unix epoch (`START_INSTANT`) unless specifically testing epoch-related logic; instead, use realistic dates and vary them across different test suites to ensure logic isn't dependent on a specific "standard" date.
- Use `clock.nowDate()` to get a `LocalDate` in UTC, or `clock.nowDateTime()` to get an `OffsetDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time.
- **Beam Pipelines:**
- Ensure `Clock` is serializable (it is by default in this project) when used in Beam `DoFn`s.
- Pass the `Clock` through the constructor or via Dagger provider methods in the pipeline module.
@@ -42,19 +35,21 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Test Components:** Use `TestRegistryToolComponent` for command-line tool tests to bridge the gap between `main` and `nonprod/test` source sets.
### 4. Database Consistency
- **JPA Converters:** Be aware that JPA converters (like `DateTimeConverter`) may perform truncation or transformation. Ensure application-level logic matches these transformations to avoid "dirty" state or unexpected diffs.
- **Transaction Management:**
- **Top-Level:** Define database transactions (`tm().transact(...)`) at the highest possible level in the call chain (e.g., in an Action, a Command, or a Flow). This ensures all operations are atomic and handled by the retry logic.
- **DAO Methods:** Avoid declaring transactions inside low-level DAO methods. Use `tm().assertInTransaction()` to ensure that these methods are only called within a valid transactional context.
- **Utility/Cache Methods:** Use `tm().reTransact(...)` for utility methods or Caffeine cache loaders that might be invoked from both transactional and non-transactional paths.
- `reTransact` will join an existing transaction if one is present (acting as a no-op) or start a new one if not.
- This is particularly useful for in-memory caches where the loader must be able to fetch data regardless of whether the caller is currently in a transaction.
- **Transactional Time:** Ensure code that relies on `tm().getTransactionTime()` is executed within a transaction context.
- **Test Helpers & Timestamps:** If a static test helper method (like in `DatabaseHelper`) needs the database transaction time but might be called from outside a transaction, using `tm().reTransact(tm()::getTxTime)` is acceptable. However, NEVER wrap it redundantly like `tm().transact(() -> tm().reTransact(tm()::getTxTime))`. If you are just setting an arbitrary timestamp in a test where the exact DB transaction time isn't strictly required, prefer `Instant.now()` or `clock.now()` to avoid creating unnecessary database transactions.
- **Production Code:** In production code, if a flow fails because it is calling `getTxTime()` outside of a transaction, you must wrap the *caller* in a transaction instead of adding an unnecessary `reTransact()` around `getTxTime()`.
- **Transactional Time:** Ensure code that relies on `tm().getTransactionTime()` (or `tm().getTxTime()`) is executed within a transaction context.
### 5. Testing Best Practices
- **FakeClock and Sleeper:** Use `FakeClock` and `Sleeper` for any logic involving timeouts, delays, or expiration.
- **Empirical Reproduction:** Before fixing a bug, always create a test case that reproduces the failure.
- **Base Classes:** Leverage `CommandTestCase`, `EppToolCommandTestCase`, etc., to reduce boilerplate and ensure consistent setup (e.g., clock initialization).
- **Gradle Test Patterns:** When running tests to investigate fixes in the "core" directory, try to first use the "standardTest" Gradle task. It is faster than the "test" task, which includes the "fragileTest" task. Only run the full "test" task after "standardTest" succeeds.
### 6. Project Dependencies
- **Common Module:** When using `Clock` or other core utilities in a new or separate module (like `load-testing`), ensure `implementation project(':common')` is added to the module's `build.gradle`.
@@ -93,9 +88,8 @@ This document captures high-level architectural patterns, lessons learned from l
- **Transaction Management:** The codebase uses a custom wrapper around JPA. Always use `tm()` (from `TransactionManagerFactory`) to interact with the database.
- **Dependency Injection:** Dagger 2 is used extensively. If you see "cannot find symbol" errors for classes starting with `Dagger...`, the project is in a state where annotation processing failed. Fix compilation in core models first to restore generated code.
- **Value Types:** AutoValue and "ImmutableObject" patterns are dominant. Most models follow a `Buildable` pattern with a nested `Builder`.
- **Temporal Logic:** The project is migrating from Joda-Time to `java.time`.
- Core boundaries: `DateTimeUtils.START_OF_TIME_INSTANT` (Unix Epoch) and `END_OF_TIME_INSTANT` (Long.MAX_VALUE / 1000).
- Year Arithmetic: Use `DateTimeUtils.plusYears()` and `DateTimeUtils.minusYears()` to handle February 29th logic correctly.
- **Temporal Logic:** The project uses `java.time` for all temporal representations.
- Core boundaries: `DateTimeUtils.START_INSTANT` (Unix Epoch) and `DateTimeUtils.END_INSTANT` (Long.MAX_VALUE / 1000).
## Source Control
- **Committing:** Always create a new commit on the branch if one hasn't been created yet for the branch's specific work. Only perform amending (`git commit --amend --no-edit`) for subsequent changes once the initial commit has been successfully created.
@@ -113,14 +107,11 @@ This document captures high-level architectural patterns, lessons learned from l
## Self-Review Guidelines
Before finalizing any PR or declaring a task complete, you MUST perform a thorough, rigorous self-review of your entire diff. Run `git diff HEAD^` (or review the staged changes) and actively verify the following against every modified line:
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.time.Duration` and `org.joda.time.Duration`), one MUST remain fully qualified to avoid a compilation conflict.
2. **Redundant Conversions:** Did I use `toDateTime(clock.now())` where `clock.nowUtc()` would suffice? Did I use `toDateTime(END_INSTANT)` instead of `END_OF_TIME`? Did I use `.toInstant()` or `.toDateTime()` on something that could be avoided by using a different method overload (e.g., `tm().getTxTime()`)?
3. **Verbose Math:** Did I write any verbose time conversions inline? Are there `DateTimeUtils` methods I should be using instead? If not, should I abstract this math into `DateTimeUtils`?
4. **Assertion Cleanliness:** Am I polluting test assertions with `toDateTime(...)` wraps? If so, I need to add overloaded assertions to the Truth Subjects instead.
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.
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.util.Date` and `java.sql.Date`), one MUST remain fully qualified to avoid a compilation conflict.
2. **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)?
3. **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?
4. **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.
5. **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.
@@ -129,30 +120,16 @@ Only after actively confirming these checks against your diff are you permitted
### 1. Compiler Warnings are Errors (`-Werror`)
This project treats Error Prone warnings as errors.
- **`@InlineMeSuggester`**: When creating deprecated Joda-Time bridge methods (e.g., `getTimestamp() -> return toDateTime(getTimestampInstant())`), you **MUST** immediately add `@SuppressWarnings("InlineMeSuggester")`. If you don't, the build will fail.
- **Repeatable Annotations**: `@SuppressWarnings` is **NOT** repeatable in this environment. If a method or class already has a suppression (e.g., `@SuppressWarnings("unchecked")`), you must merge them:
-`@SuppressWarnings("unchecked") @SuppressWarnings("InlineMeSuggester")`
-`@SuppressWarnings({"unchecked", "InlineMeSuggester"})`
-`@SuppressWarnings("unchecked") @SuppressWarnings("MustBeClosedChecker")`
-`@SuppressWarnings({"unchecked", "MustBeClosedChecker"})`
### 2. Resolving Ambiguity
- **Null Overloads**: Adding an `Instant` overload to a method that previously took `DateTime` will break all `create(null)` calls. You must cast them: `create((Instant) null)`.
- **Type Erasure**: Methods taking `Optional<DateTime>` and `Optional<Instant>` will clash due to erasure. Use distinct names, e.g., `setAutorenewEndTimeInstant(Optional<Instant> time)`.
### 3. Build Strategy
- **Surgical Changes**: In large-scale migrations, focus on "leaf" nodes first (Utilities -> Models -> Flows -> Actions).
- **PR Size**: Minimize PR size by retaining Joda-Time bridge methods for high-level "Action" and "Flow" classes unless a full migration is requested. Reverting changes to DNS and Reporting logic while updating the underlying models is a valid strategy to keep PRs reviewable.
### 2. Build Strategy
- **Validation**: Always run `./gradlew build -x test` before attempting to run unit tests. Unit tests will not run if there are compilation errors in any part of the `core` module. Before finalizing a PR or declaring a task done, you MUST verify your changes. **Prefer scoped builds** (e.g., `./gradlew :core:build`) if you are only modifying backend Java code. Running the global `./gradlew build` triggers the frontend `console-webapp` build, which unnecessarily runs `npmInstallDeps` and modifies `package-lock.json`. If you must run a global build, you must revert `console-webapp/package-lock.json` afterwards. Do not declare success if formatting checks (e.g., `spotlessCheck` or `javaIncrementalFormatCheck`) or tests fail. If formatting fails, run `./gradlew spotlessApply` and then re-run your build command to verify everything passes.
## 🚫 Common Pitfalls to Avoid
- **Mixing Joda and Java Durations:** Methods like `Tld.get().getRenewGracePeriodLength()` return a **Joda** `Duration`, which cannot be passed directly to `Instant.plus(...)` because it doesn't implement `TemporalAmount`. You MUST use `.plusMillis(duration.getMillis())` instead.
- **Serialization Precision (`.000Z`):** When asserting against or generating XML/YAML files, remember that millisecond precision (`.000Z`) is required. Always use `DateTimeUtils.formatInstant(...)` to format `Instant` objects (it preserves the `.000Z` suffix) instead of `Instant.toString()` (which drops it for exact seconds). We have added custom Jackson `InstantKeySerializer`s for this purpose, but you must keep this precision in mind when manually updating `.xml` or `.yaml` test data.
- **Static Imports:** Methods like `toDateTime`, `toInstant`, `plusYears`, `plusMonths`, and `minusDays` from `DateTimeUtils` MUST be statically imported. Do NOT use them fully qualified (e.g., `DateTimeUtils.plusMonths(...)`).
- **Redundant Parses:** Never write `toDateTime(Instant.parse(...))` or `toInstant(DateTime.parse(...))`. If you need a `DateTime`, use `DateTime.parse(...)` directly. If you need an `Instant`, use `Instant.parse(...)` directly.
- **cloneProjectedAtTime vs cloneProjectedAtInstant:** When converting tests and logic that use `clock.now()` to project resource state into the future or past, do not wrap the Java `Instant` in `toDateTime()` just to call `cloneProjectedAtTime()`. Instead, switch the method call to use the native `cloneProjectedAtInstant()` method which is available on all `EppResource` models.
- **Do not go in circles with the build:** If you see an `InlineMeSuggester` error, apply the suppression to **ALL** similar methods in that file and related files in one turn. Do not fix them one by one. Furthermore, do not run a global `./gradlew build` when a scoped `./gradlew :core:build` or `./gradlew :core:test` is faster and more appropriate. Run global builds only when doing final verification.
- **Exception Conversion in Tests:** When migrating time types (e.g., from Joda `DateTime` to Java `Instant`), be extremely careful with tests that verify parsing failures (e.g., `assertThrows(IllegalArgumentException.class, ...)`). Joda's `DateTime.parse()` throws an `IllegalArgumentException` on failure, but `Instant.parse()` throws a `java.time.format.DateTimeParseException`. You must update the expected exception type in these tests to ensure they actually test the correct behavior, and verify the tests are not failing prematurely on the first line if it contains invalid data meant to be ignored.
- Dagger/AutoValue corruption: If you modify a builder or a component incorrectly, Dagger will fail to generate code, leading to hundreds of "cannot find symbol" errors. If this happens, `git checkout` the last working state of the specific file and re-apply changes more surgically.
- **`replace` tool context**: When using `replace` on large files (like `Tld.java` or `DomainBase.java`), provide significant surrounding context. These files have many similar method signatures (getters/setters) that can lead to incorrect replacements.

View File

@@ -58,7 +58,6 @@ dependencies {
implementation deps['com.google.code.findbugs:jsr305']
implementation deps['com.google.guava:guava']
implementation deps['jakarta.inject:jakarta.inject-api']
implementation deps['joda-time:joda-time']
implementation deps['com.google.flogger:flogger']
implementation deps['io.github.java-diff-utils:java-diff-utils']
implementation deps['com.google.truth:truth']

View File

@@ -2,7 +2,7 @@
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.2.3=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.ben-manes.caffeine:caffeine:3.2.4=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.11.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
@@ -11,8 +11,8 @@ com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor,te
com.google.code.findbugs:jsr305:3.0.2=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.36.0=checkstyle
com.google.errorprone:error_prone_annotations:2.43.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.49.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.flogger:flogger:0.9=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
@@ -37,7 +37,6 @@ io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,testAnnotatio
io.github.java-diff-utils:java-diff-utils:4.16=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
jakarta.inject:jakarta.inject-api:2.0.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
joda-time:joda-time:2.14.1=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
net.sf.saxon:Saxon-HE:12.5=checkstyle
org.antlr:antlr4-runtime:4.13.2=checkstyle

View File

@@ -16,31 +16,37 @@ package google.registry.util;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
/**
* A clock that tells the current time in milliseconds or nanoseconds.
*
* <p>Clocks are technically serializable because they are either a stateless wrapper around the
* system clock, or for testing, are just a wrapper around a DateTime. This means that if you
* system clock, or for testing, are just a wrapper around an Instant. This means that if you
* serialize a clock and deserialize it elsewhere, you won't necessarily get the same time or time
* zone -- what you will get is a functioning clock.
*/
@ThreadSafe
public interface Clock extends Serializable {
/** Returns current time in UTC timezone. */
@Deprecated
DateTime nowUtc();
/** Returns current Instant (which is always in UTC). */
Instant now();
/** Returns the current time as a {@link ZonedDateTime} in UTC. */
default ZonedDateTime nowDate() {
return ZonedDateTime.ofInstant(now(), ZoneOffset.UTC);
/** Returns the current time as an {@link OffsetDateTime} in UTC. */
default OffsetDateTime nowDateTime() {
return OffsetDateTime.ofInstant(now(), ZoneOffset.UTC);
}
/** Returns the current time as a {@link LocalDate} in UTC. */
default LocalDate nowDate() {
return LocalDate.ofInstant(now(), ZoneOffset.UTC);
}
/** Returns the current time in milliseconds since the epoch. */
default long nowMillis() {
return now().toEpochMilli();
}
}

View File

@@ -15,43 +15,22 @@
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;
import com.google.common.collect.Ordering;
import java.sql.Date;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
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, 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);
/**
* A date in the far future that we can treat as infinity.
*
* <p>This value is (2^63-1)/1000 rounded down. Postgres can store dates as 64 bit microseconds,
* 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, UTC);
/**
* An instant in the far future that we can treat as infinity.
*
@@ -66,15 +45,15 @@ public abstract class DateTimeUtils {
*
* <p>Example: {@code 2024-03-27T10:15:30.105Z}
*
* <p>Handles large/negative years by using a sign prefix if necessary, compatible with {@link
* Instant#parse}.
* <p>Note: We deliberately strip the leading {@code +} sign from the formatted year field if
* present. While standard ISO 8601 specifies that years with more than 4 digits should be
* prefixed with a {@code +} sign, W3C XML Schema 1.0 (which our EPP RDE XSD uses) strictly
* forbids leading plus signs in {@code xsd:dateTime} strings. Suppressing the plus sign ensures
* our generated XML continues to pass strict XSD validation for large years (e.g. {@code
* 294247-01-10T04:00:54.775Z}).
*/
private static final DateTimeFormatter ISO_8601_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NORMAL)
.appendPattern("-MM-dd'T'HH:mm:ss.SSS'Z'")
.toFormatter()
.withZone(ZoneOffset.UTC);
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);
/** A formatter that produces lowercase, filename-safe and job-name-safe timestamps. */
public static final DateTimeFormatter LOWERCASE_TIMESTAMP_FORMATTER =
@@ -82,7 +61,8 @@ public abstract class DateTimeUtils {
/** Formats an {@link Instant} to an ISO-8601 string. */
public static String formatInstant(Instant instant) {
return ISO_8601_FORMATTER.format(instant);
String formatted = ISO_8601_FORMATTER.format(instant);
return formatted.startsWith("+") ? formatted.substring(1) : formatted;
}
/**
@@ -93,86 +73,48 @@ public abstract class DateTimeUtils {
* large years (e.g. {@code 294247-01-10T04:00:54.775Z}).
*/
public static Instant parseInstant(String timestamp) {
if (!timestamp.startsWith("+") && !timestamp.startsWith("-")) {
int dashIndex = timestamp.indexOf('-');
if (dashIndex > 4) {
timestamp = "+" + timestamp;
}
}
try {
// Try the standard millisecond precision format first.
return Instant.from(ISO_8601_FORMATTER.parse(timestamp));
return Instant.from(DateTimeFormatter.ISO_INSTANT.parse(timestamp));
} catch (DateTimeParseException e) {
// Fall back to the standard ISO instant parser which handles varied precision.
return Instant.parse(timestamp);
}
}
/** Returns the earliest of a number of given {@link DateTime} instances. */
public static DateTime earliestOf(DateTime first, DateTime... rest) {
return earliestDateTimeOf(Lists.asList(first, rest));
}
/** Returns the earliest of a number of given {@link Instant} instances. */
public static Instant earliestOf(Instant first, Instant... rest) {
return earliestOf(Lists.asList(first, rest));
}
/** Returns the earliest element in a {@link DateTime} iterable. */
public static DateTime earliestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().min(dates);
}
/** Returns the earliest element in a {@link Instant} iterable. */
/** Returns the earliest element in an {@link Instant} iterable. */
public static Instant earliestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().min(instants);
}
/** Returns the latest of a number of given {@link DateTime} instances. */
public static DateTime latestOf(DateTime first, DateTime... rest) {
return latestDateTimeOf(Lists.asList(first, rest));
}
/** Returns the latest of a number of given {@link Instant} instances. */
public static Instant latestOf(Instant first, Instant... rest) {
return latestOf(Lists.asList(first, rest));
}
/** Returns the latest element in a {@link DateTime} iterable. */
public static DateTime latestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().max(dates);
}
/** Returns the latest element in a {@link Instant} iterable. */
/** Returns the latest element in an {@link Instant} iterable. */
public static Instant latestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().max(instants);
}
/** Returns whether the first {@link DateTime} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(DateTime timeToCheck, DateTime timeToCompareTo) {
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);
}
/** Returns whether the first {@link DateTime} is equal to or later than the second. */
public static boolean isAtOrAfter(DateTime timeToCheck, DateTime timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
}
/** Returns whether the first {@link Instant} is equal to or later than the second. */
public static boolean isAtOrAfter(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
@@ -180,16 +122,7 @@ public abstract class DateTimeUtils {
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link DateTime#plusYears} to ensure that we never end up on February 29.
*/
public static DateTime plusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.plusYears(1).plusYears(years - 1);
}
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link java.time.ZonedDateTime#plusYears} to ensure that we never end up on February 29.
* {@link java.time.OffsetDateTime#plusYears} to ensure that we never end up on February 29.
*/
public static Instant plusYears(Instant now, int years) {
checkArgument(years >= 0);
@@ -212,16 +145,7 @@ public abstract class DateTimeUtils {
/**
* Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead
* of {@link DateTime#minusYears} to ensure that we never end up on February 29.
*/
public static DateTime minusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.minusYears(1).minusYears(years - 1);
}
/**
* Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead
* of {@link java.time.ZonedDateTime#minusYears} to ensure that we never end up on February 29.
* of {@link java.time.OffsetDateTime#minusYears} to ensure that we never end up on February 29.
*/
public static Instant minusYears(Instant now, long years) {
checkArgument(years >= 0);
@@ -230,58 +154,9 @@ public abstract class DateTimeUtils {
: now.atZone(ZoneOffset.UTC).minusYears(1).minusYears(years - 1).toInstant();
}
/**
* @deprecated Use {@link #plusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeAddYears(DateTime now, int years) {
return plusYears(now, years);
}
/**
* @deprecated Use {@link #minusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeSubtractYears(DateTime now, int years) {
return minusYears(now, years);
}
public static Date toSqlDate(LocalDate localDate) {
return new Date(localDate.toDateTimeAtStartOfDay().getMillis());
}
public static LocalDate toLocalDate(Date date) {
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. */
@Nullable
public static Instant toInstant(@Nullable DateTime dateTime) {
return (dateTime == null) ? null : Instant.ofEpochMilli(dateTime.getMillis());
}
/** 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(), UTC);
}
/** Convert a java.time {@link java.time.Instant} to a joda {@link org.joda.time.Instant}. */
@Nullable
public static org.joda.time.Instant toJodaInstant(@Nullable java.time.Instant instant) {
return (instant == null) ? null : org.joda.time.Instant.ofEpochMilli(instant.toEpochMilli());
/** Converts an Instant to a java.time.LocalDate in UTC. */
public static LocalDate toLocalDate(Instant instant) {
return instant.atZone(ZoneOffset.UTC).toLocalDate();
}
public static Instant plusHours(Instant instant, long hours) {
@@ -300,11 +175,19 @@ public abstract class DateTimeUtils {
return instant.minus(minutes, ChronoUnit.MINUTES);
}
public static Instant plusDays(Instant instant, int days) {
public static Instant plusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).plusWeeks(weeks).toInstant();
}
public static Instant minusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).minusWeeks(weeks).toInstant();
}
public static Instant plusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).plusDays(days).toInstant();
}
public static Instant minusDays(Instant instant, int days) {
public static Instant minusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).minusDays(days).toInstant();
}
}

View File

@@ -16,7 +16,6 @@ package google.registry.util;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
/**
* An object which accepts requests to put the current thread to sleep.
@@ -31,16 +30,7 @@ public interface Sleeper {
*
* @throws InterruptedException if this thread was interrupted
*/
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));
}
void sleep(Duration duration) throws InterruptedException;
/**
* Puts the current thread to sleep, ignoring interrupts.
@@ -50,35 +40,7 @@ public interface Sleeper {
*
* @see com.google.common.util.concurrent.Uninterruptibles#sleepUninterruptibly
*/
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.
*
* <p>This is a convenience method for {@link #sleep} that properly converts an {@link
* InterruptedException} to a {@link RuntimeException}.
*/
default void sleepInterruptibly(ReadableDuration duration) {
try {
sleep(duration);
} catch (InterruptedException e) {
// Restore current thread's interrupted state.
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted.", e);
}
}
void sleepUninterruptibly(Duration duration);
/**
* Puts the current thread to interruptible sleep.

View File

@@ -15,12 +15,10 @@
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 javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
/** Clock implementation that proxies to the real system clock. */
@ThreadSafe
@@ -31,18 +29,11 @@ public class SystemClock implements Clock {
@Inject
public SystemClock() {}
/** Returns the current time. */
@Override
public DateTime nowUtc() {
return DateTime.now(UTC);
}
@Override
public Instant now() {
// Truncate to milliseconds to match the precision of Joda DateTime and our database schema
// (which uses millisecond precision via DateTimeConverter). This prevents subtle comparison
// bugs where a high-precision Instant would be considered "after" a truncated database
// timestamp.
// Truncate to milliseconds to match the precision of our database schema.
// This prevents subtle comparison bugs where a high-precision Instant would be
// considered "after" a truncated database timestamp.
return Instant.now().truncatedTo(MILLIS);
}
}

View File

@@ -15,13 +15,12 @@
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;
/** Implementation of {@link Sleeper} for production use. */
@ThreadSafe
@@ -33,14 +32,14 @@ public final class SystemSleeper implements Sleeper, Serializable {
public SystemSleeper() {}
@Override
public void sleep(ReadableDuration duration) throws InterruptedException {
checkArgument(duration.getMillis() >= 0);
Thread.sleep(duration.getMillis());
public void sleep(Duration duration) throws InterruptedException {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
Thread.sleep(duration.toMillis());
}
@Override
public void sleepUninterruptibly(ReadableDuration duration) {
checkArgument(duration.getMillis() >= 0);
Uninterruptibles.sleepUninterruptibly(toJavaDuration(duration));
public void sleepUninterruptibly(Duration duration) {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
Uninterruptibles.sleepUninterruptibly(duration);
}
}

View File

@@ -14,18 +14,13 @@
package google.registry.testing;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.time.DateTimeZone.UTC;
import static org.joda.time.Duration.millis;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import google.registry.util.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.ReadableDuration;
import org.joda.time.ReadableInstant;
/** A mock clock for testing purposes that supports telling, setting, and advancing the time. */
@ThreadSafe
@@ -39,14 +34,9 @@ public final class FakeClock implements Clock {
private volatile long autoIncrementStepMs;
/** Creates a FakeClock that starts at START_OF_TIME. */
/** Creates a FakeClock that starts at START_INSTANT. */
public FakeClock() {
this(START_OF_TIME);
}
/** Creates a FakeClock initialized to a specific time. */
public FakeClock(ReadableInstant startTime) {
setTo(startTime);
this(START_INSTANT);
}
/** Creates a FakeClock initialized to a specific time. */
@@ -54,12 +44,6 @@ public final class FakeClock implements Clock {
setTo(startTime);
}
/** Returns the current time. */
@Override
public DateTime nowUtc() {
return new DateTime(currentTimeMillis.addAndGet(autoIncrementStepMs), UTC);
}
@Override
public Instant now() {
return Instant.ofEpochMilli(currentTimeMillis.addAndGet(autoIncrementStepMs));
@@ -74,31 +58,30 @@ public final class FakeClock implements Clock {
* @param autoIncrementStep the new auto increment duration
* @return this
*/
public FakeClock setAutoIncrementStep(ReadableDuration autoIncrementStep) {
this.autoIncrementStepMs = autoIncrementStep.getMillis();
/**
* Sets the increment applied to the clock whenever it is queried. The increment is zero by
* default: the clock is left unchanged when queried.
*
* <p>Passing a duration of zero to this method effectively unsets the auto increment mode.
*
* @param autoIncrementStep the new auto increment duration
* @return this
*/
public FakeClock setAutoIncrementStep(Duration autoIncrementStep) {
this.autoIncrementStepMs = autoIncrementStep.toMillis();
return this;
}
/** Advances clock by one millisecond. */
public void advanceOneMilli() {
advanceBy(millis(1));
advanceBy(Duration.ofMillis(1));
}
/** Advances clock by some duration. */
public void advanceBy(ReadableDuration duration) {
currentTimeMillis.addAndGet(duration.getMillis());
}
/** Advances clock by some duration. */
public void advanceBy(java.time.Duration duration) {
public void advanceBy(Duration duration) {
currentTimeMillis.addAndGet(duration.toMillis());
}
/** Sets the time to the specified instant. */
public void setTo(ReadableInstant time) {
currentTimeMillis.set(time.getMillis());
}
/** Sets the time to the specified instant. */
public void setTo(Instant time) {
currentTimeMillis.set(time.toEpochMilli());
@@ -106,7 +89,7 @@ public final class FakeClock implements Clock {
/** Invokes {@link #setAutoIncrementStep} with one millisecond-step. */
public FakeClock setAutoIncrementByOneMilli() {
return setAutoIncrementStep(Duration.millis(1));
return setAutoIncrementStep(Duration.ofMillis(1));
}
/** Disables the auto-increment mode. */

View File

@@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import google.registry.util.Sleeper;
import java.io.Serializable;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
/** Sleeper implementation for unit tests that advances {@link FakeClock} rather than sleep. */
@ThreadSafe
@@ -35,8 +35,8 @@ public final class FakeSleeper implements Sleeper, Serializable {
}
@Override
public void sleep(ReadableDuration duration) throws InterruptedException {
checkArgument(duration.getMillis() >= 0);
public void sleep(Duration duration) throws InterruptedException {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
if (Thread.interrupted()) {
throw new InterruptedException();
}
@@ -44,8 +44,8 @@ public final class FakeSleeper implements Sleeper, Serializable {
}
@Override
public void sleepUninterruptibly(ReadableDuration duration) {
checkArgument(duration.getMillis() >= 0);
public void sleepUninterruptibly(Duration duration) {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
clock.advanceBy(duration);
}
}

View File

@@ -409,4 +409,3 @@ if __name__ == '__main__':
sys.exit(main(sys.argv))
except Abort as ex:
sys.exit(1)

View File

@@ -102,6 +102,22 @@ PRESUBMITS = {
{"node_modules/", ".idea"}, REQUIRED):
"Source files must end in a newline.",
# Files must not end with extraneous blank lines
PresubmitCheck(
r".*\n\n$",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea", "nomulus.golden.sql"},
):
"Source files must not end with extraneous blank lines.",
# Duplicate empty lines
PresubmitCheck(
r".*\n\n\n.*",
("java", "js", "soy", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea"},
):
"Source files must not contain duplicate empty lines.",
# System.(out|err).println should only appear in tools/ or load-testing/
PresubmitCheck(
r".*\bSystem\s*\.\s*(?:out|err)\s*\.\s*print.*", "java", {
@@ -153,7 +169,16 @@ PRESUBMITS = {
PresubmitCheck(
r".*java\.util\.Date.*",
"java",
{"/node_modules/", "JpaTransactionManagerImpl.java", "DateTimeUtils.java"},
{
"/node_modules/",
"JpaTransactionManagerImpl.java",
"DateTimeUtils.java",
"SelfSignedCaCertificate.java",
"X509Utils.java",
"TmchCertificateAuthority.java",
"DelegatedCredentials.java",
"SslInitializerTestUtils.java"
},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
PresubmitCheck(
@@ -194,79 +219,12 @@ PRESUBMITS = {
{},
):
"Do not use .isEqualTo(Optional.of(...)). Use Truth's .hasValue(...) instead.",
# TODO: Remove the java.time migration presubmit checks below once the entire codebase has been migrated to java.time.
PresubmitCheck(
r".*toDateTime\(\s*toInstant\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not double-wrap toDateTime(toInstant(...)).",
PresubmitCheck(
r".*toInstant\(\s*toDateTime\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not double-wrap toInstant(toDateTime(...)).",
PresubmitCheck(
r".*toInstant\([^;]*[cC]lock\.nowUtc\(\).*",
r".*java\.time\.ZonedDateTime.*",
"java",
{},
):
"Do not use toInstant(clock.nowUtc()). Use clock.now() instead.",
PresubmitCheck(
r".*toDateTime\([^;]*[cC]lock\.now\(\).*",
"java",
{},
):
"Do not use toDateTime(clock.now()). Use clock.nowUtc() instead.",
PresubmitCheck(
r".*toInstant\([^;]*tm\(\)\.getTransactionTime\(\).*",
"java",
{},
):
"Do not use toInstant(tm().getTransactionTime()). Use tm().getTxTime() instead.",
PresubmitCheck(
r".*toDateTime\([^;]*tm\(\)\.getTxTime\(\).*",
"java",
{},
):
"Do not use toDateTime(tm().getTxTime()). Use tm().getTransactionTime() instead.",
PresubmitCheck(
r".*\(\s*Instant\s*\)\s*(?:this\.)?(?:fakeClock|clock)\.now\(\s*\).*",
"java",
{},
):
"Do not unnecessarily cast clock.now() to Instant.",
PresubmitCheck(
r".*toDateTime\(\s*Instant\.now\(.*",
"java",
{},
):
"Do not wrap Instant.now() in toDateTime. Use DateTime.now(UTC) directly.",
PresubmitCheck(
r".*toInstant\(\s*DateTime\.now\(.*",
"java",
{},
):
"Do not wrap DateTime.now() in toInstant. Use Instant.now().truncatedTo(ChronoUnit.MILLIS) directly.",
PresubmitCheck(
r".*toDateTime\(\s*Instant\.parse\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap Instant.parse in toDateTime. Use DateTime.parse directly.",
PresubmitCheck(
r".*toInstant\(\s*DateTime\.parse\(.*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap DateTime.parse in toInstant. Use Instant.parse directly.",
PresubmitCheck(
r".*cloneProjectedAtTime\(\s*toDateTime\(.*",
"java",
{},
):
"Do not use cloneProjectedAtTime(toDateTime(...)). Use cloneProjectedAtInstant(...) instead.",
"Do not use java.time.ZonedDateTime. Use java.time.OffsetDateTime per go/avoid-zdt.",
PresubmitCheck(
r".*ZoneId\.of\(\s*\"UTC\"\s*\).*",
"java",
@@ -274,29 +232,11 @@ PRESUBMITS = {
):
"Do not use ZoneId.of(\"UTC\"). Use java.time.ZoneOffset.UTC.",
PresubmitCheck(
r".*toDateTime\(\s*END_INSTANT\s*\).*",
r".*org\.joda\.time.*",
"java",
{"DateTimeUtilsTest.java"},
{"SafeBrowsingTransforms.java"},
):
"Do not wrap END_INSTANT in toDateTime. Use END_OF_TIME.",
PresubmitCheck(
r".*toInstant\(\s*END_OF_TIME\s*\).*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap END_OF_TIME in toInstant. Use END_INSTANT.",
PresubmitCheck(
r".*toDateTime\(\s*START_INSTANT\s*\).*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap START_INSTANT in toDateTime. Use START_OF_TIME.",
PresubmitCheck(
r".*toInstant\(\s*START_OF_TIME\s*\).*",
"java",
{"DateTimeUtilsTest.java"},
):
"Do not wrap START_OF_TIME in toInstant. Use START_INSTANT."
"Do not use Joda-Time. Use java.time instead.",
}
# Note that this regex only works for one kind of Flyway file. If we want to

View File

@@ -629,15 +629,15 @@
}
},
"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==",
"version": "25.7.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.7.0.tgz",
"integrity": "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"undici-types": "~7.19.0"
"undici-types": "~7.21.0"
}
},
"node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": {
@@ -744,9 +744,9 @@
}
},
"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==",
"version": "7.21.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.21.0.tgz",
"integrity": "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==",
"dev": true,
"license": "MIT",
"optional": true,

View File

@@ -198,7 +198,6 @@ dependencies {
implementation deps['jakarta.persistence:jakarta.persistence-api']
implementation deps['jakarta.servlet:jakarta.servlet-api']
implementation deps['jakarta.xml.bind:jakarta.xml.bind-api']
implementation deps['joda-time:joda-time']
implementation deps['org.antlr:antlr4']
implementation deps['org.antlr:antlr4-runtime']
implementation deps['org.apache.avro:avro']
@@ -479,7 +478,6 @@ Optional<List<String>> getToolArgsList() {
return Optional.empty()
}
// To run the nomulus tools with these command line tokens:
// "--foo", "bar baz", "--qux=quz"
// gradle core:registryTool --args="--foo 'bar baz' --qux=quz"
@@ -579,6 +577,11 @@ if (environment == 'alpha') {
mainClass: 'google.registry.beam.resave.ResaveAllEppResourcesPipeline',
metaData: 'google/registry/beam/resave_all_epp_resources_pipeline_metadata.json'
],
smokeTest:
[
mainClass: 'google.registry.beam.common.SmokeTestPipeline',
metaData: 'google/registry/beam/smoke_test_pipeline_metadata.json'
],
]
project.tasks.create("stageBeamPipelines") {
doLast {
@@ -814,7 +817,6 @@ test {
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
// When we override tests, we also break the cleanTest command.
cleanTest.dependsOn(cleanFragileTest, cleanStandardTest,
cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest)

View File

@@ -13,9 +13,8 @@ com.fasterxml.jackson.datatype:jackson-datatype-joda:2.20.2=compileClasspath,dep
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.woodstox:woodstox-core:7.0.0=testCompileClasspath,testRuntimeClasspath
com.fasterxml:classmate:1.7.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.2.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.2.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-api:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport-zerodep:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -36,7 +35,7 @@ com.google.api-client:google-api-client-servlet:2.7.0=deploy_jar,nonprodRuntimeC
com.google.api-client:google-api-client-servlet:2.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api-client:google-api-client:2.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -47,7 +46,7 @@ com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.111.0=compileC
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.65.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -68,27 +67,27 @@ com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.111.0=compile
com.google.api.grpc:proto-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.60.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.65.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.66.0=testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.57.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:api-common:2.62.0=testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.63.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-grpc:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.80.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-httpjson:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.80.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20260227-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-rev20251012-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20250606-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260402-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260413-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260421-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260428-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260427-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iam:v2-rev20250502-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -99,8 +98,10 @@ com.google.apis:google-api-services-sheets:v4-rev20260213-2.0.0=compileClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20260317-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20251118-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.apis:google-api-services-storage:v1-rev20260204-2.0.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-credentials:1.47.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.47.0=testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor
@@ -121,13 +122,13 @@ com.google.cloud:google-cloud-bigquerystorage:3.21.0=compileClasspath,deploy_jar
com.google.cloud:google-cloud-bigtable:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-compute:1.82.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.54.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-http:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.85.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.131.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.132.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.148.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -194,10 +195,10 @@ com.google.oauth-client:google-oauth-client-servlet:1.36.0=deploy_jar,nonprodRun
com.google.oauth-client:google-oauth-client-servlet:1.39.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.oauth-client:google-oauth-client:1.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.33.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.protobuf:protobuf-java-util:4.35.0-RC1=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.35.0-RC2=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.21.7=soy
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.35.0-RC1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:4.35.0-RC2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2024-02-26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.4.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -228,8 +229,8 @@ com.squareup:kotlinpoet:1.11.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-runtime:4.1.2=deploy_jar,jaxb,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-tools:4.1.2=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.7=jaxb
com.sun.xml.bind.external:rngom:4.0.7=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.8=jaxb
com.sun.xml.bind.external:rngom:4.0.8=jaxb
com.sun.xml.dtd-parser:dtd-parser:1.5.1=jaxb
com.zaxxer:HikariCP:7.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-beanutils:commons-beanutils:1.10.1=checkstyle
@@ -254,41 +255,41 @@ io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,nonprodAnnota
io.github.java-diff-utils:java-diff-utils:4.16=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.ss-bhatt:testcontainers-valkey:1.0.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-alts:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-api:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-auth:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-context:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-core:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-googleapis:1.80.0=testRuntimeClasspath
io.grpc:grpc-googleapis:1.81.0=testRuntimeClasspath
io.grpc:grpc-grpclb:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-grpclb:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-grpclb:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-inprocess:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-netty-shaded:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-opentelemetry:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf-lite:1.80.0=testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.81.0=testRuntimeClasspath
io.grpc:grpc-protobuf:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.80.0=testRuntimeClasspath
io.grpc:grpc-rls:1.81.0=testRuntimeClasspath
io.grpc:grpc-services:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-services:1.80.0=testRuntimeClasspath
io.grpc:grpc-services:1.81.0=testRuntimeClasspath
io.grpc:grpc-stub:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-stub:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-stub:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-util:1.80.0=testRuntimeClasspath
io.grpc:grpc-util:1.81.0=testRuntimeClasspath
io.grpc:grpc-xds:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-xds:1.80.0=testRuntimeClasspath
io.grpc:grpc-xds:1.81.0=testRuntimeClasspath
io.netty:netty-buffer:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -320,26 +321,26 @@ io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.1
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.semconv:opentelemetry-semconv:1.29.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-bom:1.42.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-context:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-extension-incubator:1.35.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.62.0=testCompileClasspath,testRuntimeClasspath
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.protostuff:protostuff-api:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -348,14 +349,16 @@ io.protostuff:protostuff-core:1.8.0=compileClasspath,deploy_jar,nonprodCompileCl
io.protostuff:protostuff-runtime:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.1.4=jaxb
jakarta.activation:jakarta.activation-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.mail:jakarta.mail-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.persistence:jakarta.persistence-api:3.2.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.servlet:jakarta.servlet-api:6.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.transaction:jakarta.transaction-api:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=compileClasspath,jaxb,nonprodCompileClasspath,testCompileClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=jaxb
jakarta.xml.bind:jakarta.xml.bind-api:4.1.0-M1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
@@ -366,8 +369,8 @@ junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileCl
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.17.7=compileClasspath,nonprodCompileClasspath
net.bytebuddy:byte-buddy:1.17.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:12.5=checkstyle
@@ -428,7 +431,7 @@ org.apache.sshd:sshd-common:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.21=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.22=testCompileClasspath,testRuntimeClasspath
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -439,11 +442,10 @@ org.checkerframework:checker-compat-qual:2.5.3=annotationProcessor,compileClassp
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.19.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.33.0=soy
org.checkerframework:checker-qual:3.49.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
org.checkerframework:checker-qual:3.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.49.3=checkstyle
org.checkerframework:checker-qual:3.52.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.24=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.26=testCompileClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.27=testCompileClasspath,testRuntimeClasspath
org.codehaus.plexus:plexus-classworlds:2.6.0=checkstyle
org.codehaus.plexus:plexus-component-annotations:2.1.0=checkstyle
org.codehaus.plexus:plexus-container-default:2.1.0=checkstyle
@@ -453,43 +455,43 @@ org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCo
org.eclipse.angus:angus-activation:2.0.3=jaxb
org.eclipse.angus:angus-activation:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.angus:jakarta.mail:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.8=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.5.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.7=jaxb
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.9=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.8=jaxb
org.glassfish.jaxb:jaxb-core:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.7=jaxb
org.glassfish.jaxb:jaxb-core:4.0.8=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-runtime:4.0.7=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.7=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.8=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.8=jaxb
org.glassfish.jaxb:txw2:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.7=jaxb
org.glassfish.jaxb:xsom:4.0.7=jaxb
org.glassfish.jaxb:txw2:4.0.8=jaxb
org.glassfish.jaxb:xsom:4.0.8=jaxb
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-core:1.3=nonprodCompileClasspath,nonprodRuntimeClasspath
org.hamcrest:hamcrest-core:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-library:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest:2.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.hamcrest:hamcrest:3.0=testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.1.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jacoco:org.jacoco.agent:0.8.14=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.14=jacocoAnt
org.jacoco:org.jacoco.core:0.8.14=jacocoAnt
org.jacoco:org.jacoco.report:0.8.14=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jboss.logging:jboss-logging:3.6.1.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jboss.logging:jboss-logging:3.6.3.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jcommander:jcommander:2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-bom:1.4.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-metadata-jvm:2.2.20=annotationProcessor,testAnnotationProcessor
@@ -548,26 +550,26 @@ org.ow2.asm:asm:9.7.1=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm:9.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.9=jacocoAnt
org.pcollections:pcollections:4.0.1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.7.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.postgresql:postgresql:42.7.11=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v145:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v148:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.44.0=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.36=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -591,12 +593,12 @@ tools.jackson.core:jackson-core:3.1.1=compileClasspath,deploy_jar,nonprodCompile
tools.jackson.core:jackson-databind:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson:jackson-bom:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-api:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-tools:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-utility:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.10.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool,shadow

View File

@@ -54,9 +54,15 @@ public class BatchModule {
static final int DEFAULT_MAX_QPS = 10;
@Provides
@Parameter("url")
static String provideUrl(HttpServletRequest req) {
return extractRequiredParameter(req, "url");
@Parameter("sender")
static String provideSender(HttpServletRequest req) {
return extractRequiredParameter(req, "sender");
}
@Provides
@Parameter("receiver")
static String provideReceiver(HttpServletRequest req) {
return extractRequiredParameter(req, "receiver");
}
@Provides

View File

@@ -16,30 +16,32 @@ package google.registry.batch;
import static google.registry.request.Action.Method.GET;
import static google.registry.request.Action.Method.POST;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.services.gmail.Gmail;
import com.google.common.flogger.FluentLogger;
import dagger.Lazy;
import google.registry.config.RegistryConfig.Config;
import google.registry.groups.GmailClient;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.UrlConnectionService;
import google.registry.request.UrlConnectionUtils;
import google.registry.request.auth.Auth;
import google.registry.util.EmailMessage;
import google.registry.util.Retrier;
import jakarta.inject.Inject;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
/**
* Action that executes a canned script specified by the caller.
*
* <p>This class provides a hook for invoking hard-coded methods. The main use case is to verify in
* Sandbox and Production environments new features that depend on environment-specific
* configurations. For example, the {@code DelegatedCredential}, which requires correct GWorkspace
* configuration, has been tested this way. Since it is a hassle to add or remove endpoints, we keep
* this class all the time.
* configurations.
*
* <p>This action can be invoked using the Nomulus CLI command: {@code nomulus -e ${env} curl
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript}'}
* --service BACKEND -X POST -d 'sender=sender@example.com' -d 'receiver=receiver@example.com' -u
* '/_dr/task/executeCannedScript'}
*/
@Action(
service = Action.Service.BACKEND,
@@ -50,39 +52,50 @@ import javax.net.ssl.HttpsURLConnection;
public class CannedScriptExecutionAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Inject UrlConnectionService urlConnectionService;
@Inject Lazy<Gmail> gmail;
@Inject Retrier retrier;
@Inject
@Config("isEmailSendingEnabled")
boolean isEmailSendingEnabled;
@Inject Response response;
@Inject
@Parameter("url")
String url;
@Parameter("sender")
String sender;
@Inject
@Parameter("receiver")
String receiver;
@Inject
CannedScriptExecutionAction() {}
@Override
public void run() {
Integer responseCode = null;
String responseContent = null;
// For b/510340944, validating a new G Workspace user can send email. Code below can be
// removed or changed afterward.
try {
logger.atInfo().log("Connecting to: %s", url);
HttpsURLConnection connection =
(HttpsURLConnection) urlConnectionService.createConnection(new URL(url));
responseCode = connection.getResponseCode();
logger.atInfo().log("Code: %d", responseCode);
logger.atInfo().log("Headers: %s", connection.getHeaderFields());
responseContent = new String(UrlConnectionUtils.getResponseBytes(connection), UTF_8);
logger.atInfo().log("Response: %s", responseContent);
logger.atInfo().log("Sending email from %s to %s", sender, receiver);
GmailClient gmailClient =
new GmailClient(
gmail, retrier, isEmailSendingEnabled, sender, sender, new InternetAddress(sender));
gmailClient.sendEmail(
EmailMessage.newBuilder()
.addRecipient(new InternetAddress(receiver))
.setSubject(String.format("Email send test from %s", sender))
.setBody(String.format("This is a test email sent from %s to %s.", sender, receiver))
.build());
response.setPayload("Email sent successfully.");
} catch (AddressException e) {
logger.atWarning().withCause(e).log(
"Invalid email address: sender=%s, receiver=%s", sender, receiver);
response.setStatus(400);
response.setPayload("Invalid email address provided.");
} catch (Exception e) {
logger.atWarning().withCause(e).log("Connection to %s failed", url);
logger.atSevere().withCause(e).log("Failed to send email");
throw new RuntimeException(e);
} finally {
if (responseCode != null) {
response.setStatus(responseCode);
}
if (responseContent != null) {
response.setPayload(responseContent);
}
}
}
}

View File

@@ -27,7 +27,6 @@ import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_BATCH_SIZE;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static google.registry.request.RequestParameters.PARAM_TLDS;
import static google.registry.util.DateTimeUtils.toInstant;
import static google.registry.util.RegistryEnvironment.PRODUCTION;
import com.google.common.base.Strings;
@@ -48,11 +47,11 @@ import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import jakarta.persistence.TypedQuery;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Deletes all prober {@link Domain}s and their subordinate history entries, poll messages, and
@@ -74,7 +73,7 @@ public class DeleteProberDataAction implements Runnable {
* <p>In practice, the prober's connection will time out well before this duration. This includes
* a decent buffer.
*/
private static final Duration DOMAIN_USED_DURATION = Duration.standardHours(1);
private static final Duration DOMAIN_USED_DURATION = Duration.ofHours(1);
/**
* The minimum amount of time we want a domain to be "soft deleted".
@@ -82,7 +81,7 @@ public class DeleteProberDataAction implements Runnable {
* <p>The domain has to remain soft deleted for at least enough time for the DNS task to run and
* remove it from DNS itself. This is probably on the order of minutes.
*/
private static final Duration SOFT_DELETE_DELAY = Duration.standardHours(1);
private static final Duration SOFT_DELETE_DELAY = Duration.ofHours(1);
// Domains to delete must:
// 1. Be in one of the prober TLDs
@@ -93,7 +92,7 @@ public class DeleteProberDataAction implements Runnable {
// prevents accidental double-map with the same key from immediately deleting active domains)
//
// Note: creationTime must be compared to a Java object (CreateAutoTimestamp) but deletionTime can
// be compared directly to the SQL timestamp (it's a DateTime)
// be compared directly to the SQL timestamp (it's an Instant)
private static final String DOMAIN_QUERY_STRING =
"FROM Domain d WHERE d.tld IN :tlds AND d.domainName NOT LIKE 'nic.%%' AND"
+ " (d.subordinateHosts IS NULL OR array_length(d.subordinateHosts) = 0) AND"
@@ -150,7 +149,7 @@ public class DeleteProberDataAction implements Runnable {
AtomicInteger softDeletedDomains = new AtomicInteger();
AtomicInteger hardDeletedDomains = new AtomicInteger();
AtomicReference<ImmutableList<Domain>> domainsBatch = new AtomicReference<>();
DateTime startTime = clock.nowUtc();
Instant startTime = clock.now();
do {
tm().transact(
TRANSACTION_REPEATABLE_READ,
@@ -169,7 +168,7 @@ public class DeleteProberDataAction implements Runnable {
hardDeletedDomains.get(), batchSize);
// Automatically kill the job if it is running for over 20 hours
} while (clock.nowUtc().isBefore(startTime.plusHours(20))
} while (clock.now().isBefore(startTime.plus(Duration.ofHours(20)))
&& domainsBatch.get().size() == batchSize);
logger.atInfo().log(
"%s %d domains.",
@@ -183,15 +182,14 @@ public class DeleteProberDataAction implements Runnable {
ImmutableSet<String> deletableTlds,
AtomicInteger softDeletedDomains,
AtomicInteger hardDeletedDomains,
DateTime now) {
Instant now) {
TypedQuery<Domain> query =
tm().query(DOMAIN_QUERY_STRING, Domain.class)
.setParameter("tlds", deletableTlds)
.setParameter(
"creationTimeCutoff",
CreateAutoTimestamp.create(toInstant(now.minus(DOMAIN_USED_DURATION))))
.setParameter("nowMinusSoftDeleteDelay", toInstant(now.minus(SOFT_DELETE_DELAY)))
.setParameter("now", toInstant(now));
"creationTimeCutoff", CreateAutoTimestamp.create(now.minus(DOMAIN_USED_DURATION)))
.setParameter("nowMinusSoftDeleteDelay", now.minus(SOFT_DELETE_DELAY))
.setParameter("now", now);
ImmutableList<Domain> domainList =
query.setMaxResults(batchSize).getResultStream().collect(toImmutableList());
ImmutableList.Builder<String> domainRepoIdsToHardDelete = new ImmutableList.Builder<>();

View File

@@ -19,7 +19,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
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;
@@ -238,8 +237,7 @@ public class RelockDomainAction implements Runnable {
}
}
Duration timeBeforeRetry = previousAttempts < ATTEMPTS_BEFORE_SLOWDOWN ? TEN_MINUTES : ONE_HOUR;
domainLockUtils.enqueueDomainRelock(
toJodaDuration(timeBeforeRetry), oldUnlockRevisionId, previousAttempts + 1);
domainLockUtils.enqueueDomainRelock(timeBeforeRetry, oldUnlockRevisionId, previousAttempts + 1);
}
private void sendSuccessEmail(RegistryLock oldLock) {

View File

@@ -16,7 +16,6 @@ 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.PreconditionsUtils.checkArgumentNotNull;
import static java.time.ZoneOffset.UTC;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
@@ -131,11 +130,11 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
registrar,
registrar.getClientCertificate().isPresent()
&& certificateChecker.shouldReceiveExpiringNotification(
toDateTime(registrar.getLastExpiringCertNotificationSentDate()),
registrar.getLastExpiringCertNotificationSentDate(),
registrar.getClientCertificate().get()),
registrar.getFailoverClientCertificate().isPresent()
&& certificateChecker.shouldReceiveExpiringNotification(
toDateTime(registrar.getLastExpiringFailoverCertNotificationSentDate()),
registrar.getLastExpiringFailoverCertNotificationSentDate(),
registrar.getFailoverClientCertificate().get())))
.filter(
registrarInfo ->
@@ -155,7 +154,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
Optional<String> certificate) {
if (certificate.isEmpty()
|| !certificateChecker.shouldReceiveExpiringNotification(
toDateTime(lastExpiringCertNotificationSentDate), certificate.get())) {
lastExpiringCertNotificationSentDate, certificate.get())) {
return false;
}
try {

View File

@@ -63,25 +63,20 @@ public class SyncRemoteCacheAction implements Runnable {
private final LockHandler lockHandler;
private final Response response;
private final Optional<SimplifiedJedisClient<Domain>> domainJedisClient;
private final Optional<SimplifiedJedisClient<Host>> hostJedisClient;
private final Optional<SimplifiedJedisClient> jedisClient;
@Inject
public SyncRemoteCacheAction(
LockHandler lockHandler,
Response response,
Optional<SimplifiedJedisClient<Domain>> domainJedisClient,
Optional<SimplifiedJedisClient<Host>> hostJedisClient) {
LockHandler lockHandler, Response response, Optional<SimplifiedJedisClient> jedisClient) {
this.lockHandler = lockHandler;
this.response = response;
this.domainJedisClient = domainJedisClient;
this.hostJedisClient = hostJedisClient;
this.jedisClient = jedisClient;
}
@Override
public void run() {
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
if (domainJedisClient.isEmpty() || hostJedisClient.isEmpty()) {
if (jedisClient.isEmpty()) {
response.setStatus(SC_NO_CONTENT);
response.setPayload("No Jedis/Valkey configuration found");
return;
@@ -134,7 +129,7 @@ public class SyncRemoteCacheAction implements Runnable {
return 0;
}
logger.atInfo().log("Processing %d domains", domains.size());
processResources(domainJedisClient.get(), domains, Domain::getDomainName);
processResources(Domain.class, domains, Domain::getDomainName);
setNewCursorTime(domains, REMOTE_CACHE_DOMAIN_SYNC);
return domains.size();
}
@@ -154,13 +149,13 @@ public class SyncRemoteCacheAction implements Runnable {
return 0;
}
logger.atInfo().log("Processing %d hosts", hosts.size());
processResources(hostJedisClient.get(), hosts, Host::getRepoId);
processResources(Host.class, hosts, Host::getRepoId);
setNewCursorTime(hosts, REMOTE_CACHE_HOST_SYNC);
return hosts.size();
}
private <T extends EppResource> void processResources(
SimplifiedJedisClient<T> jedisClient, List<T> resources, Function<T, String> getKeyFunction) {
Class<T> clazz, List<T> resources, Function<T, String> getKeyFunction) {
ImmutableList.Builder<String> toDeleteBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<SimplifiedJedisClient.JedisResource<T>> toSaveBuilder =
new ImmutableList.Builder<>();
@@ -176,9 +171,9 @@ public class SyncRemoteCacheAction implements Runnable {
ImmutableList<String> toDelete = toDeleteBuilder.build();
ImmutableList<SimplifiedJedisClient.JedisResource<T>> toSave = toSaveBuilder.build();
jedisClient.deleteAll(toDelete);
jedisClient.get().deleteAll(clazz, toDelete);
logger.atInfo().log("Invalidated %d from the remote cache", toDelete.size());
jedisClient.setAll(toSave);
jedisClient.get().setAll(toSave);
logger.atInfo().log("Set %d in the remote cache", toSave.size());
}

View File

@@ -14,6 +14,7 @@
package google.registry.beam.billing;
import static google.registry.util.DateTimeUtils.toLocalDate;
import static java.time.ZoneOffset.UTC;
import com.google.common.base.Joiner;
@@ -23,7 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;
import org.apache.beam.sdk.coders.AtomicCoder;
@@ -39,8 +39,8 @@ import org.jetbrains.annotations.NotNull;
* A record representing a single billable event, parsed from a {@code SchemaAndRecord}.
*
* @param id The unique ID for the {@code BillingEvent} associated with this event.
* @param billingTime The DateTime (in UTC) this event becomes billable.
* @param eventTime The DateTime (in UTC) this event was generated.
* @param billingTime The Instant (in UTC) this event becomes billable.
* @param eventTime The Instant (in UTC) this event was generated.
* @param registrarId The billed registrar's name.
* @param billingId The billed registrar's billing account key.
* @param poNumber The Purchase Order number.
@@ -164,11 +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(), UTC).toLocalDate().withDayOfMonth(1).toString(),
toLocalDate(billingTime()).withDayOfMonth(1).toString(),
years() == 0
? ""
: ZonedDateTime.ofInstant(billingTime(), UTC)
.toLocalDate()
: toLocalDate(billingTime())
.withDayOfMonth(1)
.plusYears(years())
.minusDays(1)
@@ -226,7 +225,6 @@ public record BillingEvent(
"UnitPriceCurrency",
"PONumber");
/** Generates the CSV header for the overall invoice. */
static String invoiceHeader() {
return Joiner.on(",").join(INVOICE_HEADERS);

View File

@@ -311,7 +311,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
for (Instant eventTime : eventTimesToExpand) {
recurrenceLastExpansionTime = latestOf(recurrenceLastExpansionTime, eventTime);
oneTimesToExpandCounter.inc();
Instant billingTime = eventTime.plusMillis(tld.getAutoRenewGracePeriodLength().getMillis());
Instant billingTime = eventTime.plus(tld.getAutoRenewGracePeriodLength());
// Note that the DomainHistory is created as of transaction time, as opposed to event time.
// This might be counterintuitive because other DomainHistories are created at the time
// mutation events occur, such as in DomainDeleteFlow or DomainRenewFlow. Therefore, it is

View File

@@ -22,12 +22,10 @@ import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import java.io.Serializable;
import java.time.Instant;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/** Interface for query instances used by {@link RegistryJpaIO.Read}. */
public interface RegistryQuery<T> extends Serializable {
@@ -61,11 +59,7 @@ public interface RegistryQuery<T> extends Serializable {
if (parameters != null) {
parameters.forEach(
(key, value) -> {
if (value instanceof DateTime dt) {
query.setParameter(key, Instant.ofEpochMilli(dt.getMillis()));
} else {
query.setParameter(key, value);
}
query.setParameter(key, value);
});
}
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);

View File

@@ -0,0 +1,76 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.beam.common;
import static com.google.common.base.Verify.verify;
import com.google.common.flogger.FluentLogger;
import google.registry.model.tld.Tld;
import google.registry.persistence.transaction.CriteriaQueryBuilder;
import java.io.Serializable;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.coders.StringUtf8Coder;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.Count;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;
/**
* For smoke test in the build/deployment process.
*
* <p>There two coverage gaps in unit tests for BEAM pipelines:
*
* <ul>
* <li>The compatibility of the JVM and SDK in the pipeline image
* <li>The JPA setup, which is performed by the {@link RegistryPipelineWorkerInitializer}
* </ul>
*
* <p>This classes defines a pipeline that performs one quick database query. The pipeline is
* expected to complete quickly, and the build or deployment process may launch it on GCP and wait
* for its completion to be certain that all aspects are tested for Nomulus pipelines.
*/
public class SmokeTestPipeline implements Serializable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public static void main(String[] args) {
PipelineOptionsFactory.register(RegistryPipelineOptions.class);
RegistryPipelineOptions options =
PipelineOptionsFactory.fromArgs(args).withValidation().as(RegistryPipelineOptions.class);
runPipeline(options);
}
static PipelineResult runPipeline(RegistryPipelineOptions options) {
Pipeline pipeline = Pipeline.create(options);
pipeline
.apply(
"Read Tlds",
RegistryJpaIO.read(() -> CriteriaQueryBuilder.create(Tld.class).build(), Tld::getTldStr)
.withCoder(StringUtf8Coder.of()))
.apply("Count Tlds", Count.globally())
.apply(
"Verify Count",
ParDo.of(
new DoFn<Long, Void>() {
@DoFn.ProcessElement
public void processElement(@Element Long count) {
logger.atInfo().log("Tld count: %s", count);
verify(count > 0, "Expecting 1 or more, got %s.", count);
}
}));
return pipeline.run();
}
}

View File

@@ -220,6 +220,9 @@ public class RdeIO {
}
}
output.write(marshaller.marshalRdeEppParams());
counter.increment(RdeResourceType.EPP_PARAMS);
// Output XML that says how many resources were emitted.
header = counter.makeHeader(tld, mode);
output.write(marshaller.marshalOrDie(new XjcRdeHeaderElement(header)));

View File

@@ -17,7 +17,6 @@ package google.registry.beam.resave;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.toInstant;
import static org.apache.beam.sdk.values.TypeDescriptors.integers;
import com.google.common.collect.ImmutableList;
@@ -33,6 +32,7 @@ import google.registry.model.host.Host;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
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.StringUtf8Coder;
@@ -43,13 +43,12 @@ import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.transforms.WithKeys;
import org.apache.beam.sdk.util.ShardedKey;
import org.apache.beam.sdk.values.KV;
import org.joda.time.DateTime;
/**
* A Dataflow Flex pipeline that resaves changed EPP resources in SQL.
*
* <p>Due to the way that Hibernate works, if an entity is unchanged by {@link
* EppResource#cloneProjectedAtTime(DateTime)} it will not actually be re-persisted to the database.
* EppResource#cloneProjectedAtTime(Instant)} it will not actually be re-persisted to the database.
* Thus, the only actual changes occur when objects are changed by projecting them to now, such as
* when a pending transfer is resolved.
*/
@@ -158,14 +157,14 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<String>> element) {
tm().transact(
() -> {
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
ImmutableList<VKey<? extends EppResource>> keys =
Streams.stream(element.getValue())
.map(repoId -> VKey.create(clazz, repoId))
.collect(toImmutableList());
ImmutableList<EppResource> mappedResources =
tm().loadByKeys(keys).values().stream()
.map(r -> r.cloneProjectedAtTime(toInstant(now)))
.map(r -> r.cloneProjectedAtTime(now))
.collect(toImmutableList());
tm().putAll(mappedResources);
});

View File

@@ -14,7 +14,6 @@
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;
@@ -132,7 +131,13 @@ public class SafeBrowsingTransforms {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach(
(kv) -> context.output(kv, toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
kv -> {
// The Apache Beam API requires org.joda.time.Instant here.
@SuppressWarnings("UnnecessarilyFullyQualified")
org.joda.time.Instant timestamp =
org.joda.time.Instant.ofEpochMilli(clock.nowMillis());
context.output(kv, timestamp, GlobalWindow.INSTANCE);
});
}
}

View File

@@ -35,6 +35,8 @@ import google.registry.util.Retrier;
import google.registry.util.UtilsModule;
import jakarta.inject.Singleton;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.YearMonth;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.coders.KvCoder;
@@ -50,9 +52,6 @@ import org.apache.beam.sdk.values.KV;
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.TypeDescriptor;
import org.apache.beam.sdk.values.TypeDescriptors;
import org.joda.time.LocalDate;
import org.joda.time.YearMonth;
import org.joda.time.format.ISODateTimeFormat;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -76,7 +75,7 @@ public class Spec11Pipeline implements Serializable {
* @see google.registry.reporting.spec11.Spec11EmailUtils
*/
public static String getSpec11ReportFilePath(LocalDate localDate) {
YearMonth yearMonth = new YearMonth(localDate);
YearMonth yearMonth = YearMonth.from(localDate);
return String.format("icann/spec11/%s/SPEC11_MONTHLY_REPORT_%s", yearMonth, localDate);
}
@@ -155,7 +154,7 @@ public class Spec11Pipeline implements Serializable {
static void saveToSql(
PCollection<KV<DomainNameInfo, ThreatMatch>> threatMatches, Spec11PipelineOptions options) {
LocalDate date = LocalDate.parse(options.getDate(), ISODateTimeFormat.date());
LocalDate date = LocalDate.parse(options.getDate());
String transformId = "Spec11 Threat Matches";
threatMatches
.apply(

View File

@@ -114,11 +114,7 @@ public final class DownloadScheduler {
}
private boolean isTimeAgain(BsaDownload mostRecent, Duration interval) {
return mostRecent
.getCreationTime()
.plusMillis(interval.toMillis())
.minusMillis(CRON_JITTER.toMillis())
.isBefore(clock.now());
return mostRecent.getCreationTime().plus(interval).minus(CRON_JITTER).isBefore(clock.now());
}
/**

View File

@@ -0,0 +1,51 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import com.google.common.collect.ImmutableSet;
import com.google.monitoring.metrics.IncrementableMetric;
import com.google.monitoring.metrics.LabelDescriptor;
import com.google.monitoring.metrics.MetricRegistryImpl;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
/** Metrics tracking effectiveness of local and remote EPP resource caching. */
@Singleton
public class CacheMetrics {
public enum CacheHitType {
LOCAL,
REMOTE,
MISS,
MISS_NONEXISTENT
}
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
ImmutableSet.of(
LabelDescriptor.create("cache_name", "The type of the cache (domain/host)."),
LabelDescriptor.create("hit_type", "The type of cache hit or miss."));
private static final IncrementableMetric cacheLookups =
MetricRegistryImpl.getDefault()
.newIncrementableMetric(
"/cache/lookups", "Count of cache lookups", "count", LABEL_DESCRIPTORS);
@Inject
public CacheMetrics() {}
public void recordLookup(String cacheName, CacheHitType hitType) {
cacheLookups.increment(cacheName, hitType.toString());
}
}

View File

@@ -85,37 +85,30 @@ public final class CacheModule {
@Provides
@Singleton
public static Optional<SimplifiedJedisClient<Domain>> provideDomainJedisClient(
Optional<UnifiedJedis> jedis) {
return jedis.map(j -> SimplifiedJedisClient.create(Domain.class, j));
}
@Provides
@Singleton
public static Optional<SimplifiedJedisClient<Host>> provideHostJedisClient(
Optional<UnifiedJedis> jedis) {
return jedis.map(j -> SimplifiedJedisClient.create(Host.class, j));
public static Optional<SimplifiedJedisClient> provideJedisClient(Optional<UnifiedJedis> jedis) {
return jedis.map(SimplifiedJedisClient::new);
}
@Provides
@Singleton
public static DomainCache provideDomainCache(
Optional<SimplifiedJedisClient<Domain>> domainJedisClient, Clock clock) {
if (domainJedisClient.isEmpty()) {
Optional<SimplifiedJedisClient> jedisClient, Clock clock, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return domainName ->
ForeignKeyUtils.loadResourceByCache(Domain.class, domainName, clock.now());
}
return new MultilayerDomainCache(domainJedisClient.get(), clock);
return new MultilayerDomainCache(jedisClient.get(), clock, cacheMetrics);
}
@Provides
@Singleton
public static HostCache provideHostCache(Optional<SimplifiedJedisClient<Host>> hostJedisClient) {
if (hostJedisClient.isEmpty()) {
public static HostCache provideHostCache(
Optional<SimplifiedJedisClient> jedisClient, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return repoId ->
Optional.ofNullable(EppResource.loadByCache(VKey.create(Host.class, repoId)));
}
return new MultilayerHostCache(hostJedisClient.get());
return new MultilayerHostCache(jedisClient.get(), cacheMetrics);
}
@Provides

View File

@@ -32,14 +32,15 @@ public class MultilayerDomainCache extends MultilayerEppResourceCache<Domain>
private final Clock clock;
public MultilayerDomainCache(SimplifiedJedisClient<Domain> jedisClient, Clock clock) {
super(jedisClient);
public MultilayerDomainCache(
SimplifiedJedisClient jedisClient, Clock clock, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
this.clock = clock;
}
@Override
public Optional<Domain> loadByDomainName(String domainName) {
return loadFromCaches(domainName);
return loadFromCaches(Domain.class, domainName);
}
@Override
@@ -56,11 +57,6 @@ public class MultilayerDomainCache extends MultilayerEppResourceCache<Domain>
.map(domain -> domain.cloneProjectedAtTime(now));
}
@Override
protected String getJedisPrefix() {
return "d_";
}
@Override
protected boolean shouldPersistToRemoteCache(Domain domain) {
return Tld.get(domain.getTld()).getTldType().equals(Tld.TldType.REAL);

View File

@@ -35,45 +35,49 @@ public abstract class MultilayerEppResourceCache<V extends EppResource> {
.maximumSize(RegistryConfig.getEppResourceMaxCachedEntries())
.build();
private final SimplifiedJedisClient<V> jedisClient;
private final SimplifiedJedisClient jedisClient;
private final CacheMetrics cacheMetrics;
protected MultilayerEppResourceCache(SimplifiedJedisClient<V> jedisClient) {
protected MultilayerEppResourceCache(
SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
this.jedisClient = jedisClient;
this.cacheMetrics = cacheMetrics;
}
protected abstract Optional<V> loadFromDatabase(String key);
protected abstract String getJedisPrefix();
protected boolean shouldPersistToRemoteCache(V value) {
return true;
}
protected Optional<V> loadFromCaches(String key) {
protected Optional<V> loadFromCaches(Class<V> clazz, String key) {
// hopefully the resource is in the local cache
Optional<V> possibleValue = Optional.ofNullable(localCache.getIfPresent(key));
if (possibleValue.isPresent()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.LOCAL);
return possibleValue;
}
// if not, try the remote cache
String jedisKey = getJedisPrefix() + key;
possibleValue = jedisClient.get(jedisKey);
possibleValue = jedisClient.get(clazz, key);
if (possibleValue.isPresent()) {
localCache.put(key, possibleValue.get());
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.REMOTE);
return possibleValue;
}
// lastly, try the DB
return loadFromDatabase(key)
.map(
v -> {
// Optional has no direct "peek" functionality to fill the caches
if (shouldPersistToRemoteCache(v)) {
jedisClient.set(new SimplifiedJedisClient.JedisResource<>(jedisKey, v));
}
localCache.put(key, v);
return v;
});
possibleValue = loadFromDatabase(key);
if (possibleValue.isEmpty()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS_NONEXISTENT);
return possibleValue;
}
V value = possibleValue.get();
if (shouldPersistToRemoteCache(value)) {
jedisClient.set(new SimplifiedJedisClient.JedisResource<>(key, value));
}
localCache.put(key, value);
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS);
return possibleValue;
}
}

View File

@@ -27,13 +27,13 @@ import java.util.Optional;
*/
public class MultilayerHostCache extends MultilayerEppResourceCache<Host> implements HostCache {
public MultilayerHostCache(SimplifiedJedisClient<Host> jedisClient) {
super(jedisClient);
public MultilayerHostCache(SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
}
@Override
public Optional<Host> loadByRepoId(String repoId) {
return loadFromCaches(repoId);
return loadFromCaches(Host.class, repoId);
}
@Override
@@ -41,9 +41,4 @@ public class MultilayerHostCache extends MultilayerEppResourceCache<Host> implem
return replicaTm()
.transact(() -> replicaTm().loadByKeyIfPresent(VKey.create(Host.class, repoId)));
}
@Override
protected String getJedisPrefix() {
return "h_";
}
}

View File

@@ -14,13 +14,17 @@
package google.registry.cache;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
@@ -39,54 +43,57 @@ import redis.clients.jedis.params.SetParams;
* <p>{@link UnifiedJedis} pairs key-value types, so we need the key to be serialized to a byte
* array as well.
*/
public class SimplifiedJedisClient<V extends EppResource> {
public class SimplifiedJedisClient {
public record JedisResource<V extends EppResource>(String key, V value) {}
private static final ImmutableMap<Class<? extends EppResource>, String> TYPE_PREFIXES =
ImmutableMap.of(
Domain.class, "d_",
Host.class, "h_");
private static final ImmutableMap<Class<? extends EppResource>, Schema<? extends EppResource>>
VALUE_SCHEMAS =
ImmutableMap.of(
Domain.class, RuntimeSchema.getSchema(Domain.class),
Host.class, RuntimeSchema.getSchema(Host.class));
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final int BATCH_SIZE = 500;
private final Schema<V> valueSchema;
private final UnifiedJedis jedis;
public static <V extends EppResource> SimplifiedJedisClient<V> create(
Class<V> valueClass, UnifiedJedis jedis) {
Schema<V> valueSchema = RuntimeSchema.getSchema(valueClass);
return new SimplifiedJedisClient<>(valueSchema, jedis);
}
private SimplifiedJedisClient(Schema<V> valueSchema, UnifiedJedis jedis) {
this.valueSchema = valueSchema;
SimplifiedJedisClient(UnifiedJedis jedis) {
this.jedis = jedis;
}
/** Gets the value from the remote cache. Returns null if it does not exist. */
public Optional<V> get(String key) {
public <V extends EppResource> Optional<V> get(Class<V> clazz, String key) {
checkNotNull(key, "Key cannot be null");
byte[] data = jedis.get(key.getBytes(StandardCharsets.UTF_8));
return Optional.ofNullable(data).map(this::deserialize);
byte[] data = jedis.get(convertKey(clazz, key));
return Optional.ofNullable(data).map(d -> deserialize(clazz, d));
}
/** Sets the value in the remote cache. */
public void set(JedisResource<V> resource) {
public <V extends EppResource> void set(JedisResource<V> resource) {
checkNotNull(resource.key, "Key cannot be null");
checkNotNull(resource.value, "Value cannot be null");
jedis.set(
resource.key.getBytes(StandardCharsets.UTF_8),
convertKey(resource.value.getClass(), resource.key),
serialize(resource.value),
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli()));
}
/** Sets multiple values in the remote cache using a Jedis {@link AbstractPipeline}. */
public void setAll(ImmutableCollection<JedisResource<V>> resources) {
public <V extends EppResource> void setAll(ImmutableCollection<JedisResource<V>> resources) {
logger.atInfo().log("Processing %d resources", resources.size());
for (Iterable<JedisResource<V>> batch : Iterables.partition(resources, BATCH_SIZE)) {
try (AbstractPipeline pipeline = jedis.pipelined()) {
batch.forEach(
resource ->
pipeline.set(
resource.key.getBytes(StandardCharsets.UTF_8),
convertKey(resource.value.getClass(), resource.key),
serialize(resource.value),
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli())));
pipeline.sync();
@@ -106,18 +113,18 @@ public class SimplifiedJedisClient<V extends EppResource> {
* <p>This could also be accomplished by using {@link #setAll(ImmutableCollection)} with
* expiration times that are in the past, but this is clearer.
*/
public void deleteAll(ImmutableCollection<String> keys) {
public void deleteAll(Class<?> valueType, ImmutableCollection<String> keys) {
// we use a reasonably small batch size to avoid overwhelming the network
for (Iterable<String> batch : Iterables.partition(keys, BATCH_SIZE)) {
byte[][] keysToUnlink =
Streams.stream(batch)
.map(key -> key.getBytes(StandardCharsets.UTF_8))
.toArray(byte[][]::new);
Streams.stream(batch).map(key -> convertKey(valueType, key)).toArray(byte[][]::new);
jedis.unlink(keysToUnlink);
}
}
private byte[] serialize(V value) {
private <V extends EppResource> byte[] serialize(V value) {
@SuppressWarnings("unchecked")
Schema<V> valueSchema = (Schema<V>) getValueSchema(value.getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
return ProtostuffIOUtil.toByteArray(value, valueSchema, buffer);
@@ -126,10 +133,22 @@ public class SimplifiedJedisClient<V extends EppResource> {
}
}
private V deserialize(byte[] data) {
private <V extends EppResource> V deserialize(Class<V> clazz, byte[] data) {
// We use protobufs because other deserializers don't play nicely with immutable collections
Schema<V> valueSchema = getValueSchema(clazz);
V value = valueSchema.newMessage();
ProtostuffIOUtil.mergeFrom(data, value, valueSchema);
return value;
}
private byte[] convertKey(Class<?> clazz, String key) {
checkArgument(TYPE_PREFIXES.containsKey(clazz), "Unknown class type %s", clazz);
return (TYPE_PREFIXES.get(clazz) + key).getBytes(StandardCharsets.UTF_8);
}
@SuppressWarnings("unchecked")
private <V extends EppResource> Schema<V> getValueSchema(Class<V> clazz) {
checkArgument(VALUE_SCHEMAS.containsKey(clazz), "Unknown class type %s", clazz);
return (Schema<V>) VALUE_SCHEMAS.get(clazz);
}
}

View File

@@ -45,6 +45,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.ServiceLoader;
import org.apache.commons.codec.binary.Base64;
@@ -154,7 +155,7 @@ public class DelegatedCredentials extends GoogleCredentials {
@Override
public AccessToken refreshAccessToken() throws IOException {
JsonFactory jsonFactory = JSON_FACTORY;
long currentTime = clock.nowUtc().getMillis();
long currentTime = clock.nowMillis();
String assertion = createAssertion(jsonFactory, currentTime);
GenericData tokenRequest = new GenericData();
@@ -195,7 +196,7 @@ public class DelegatedCredentials extends GoogleCredentials {
GenericData responseData = response.parseAs(GenericData.class);
String accessToken = validateString(responseData, "access_token", PARSE_ERROR_PREFIX);
int expiresInSeconds = validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX);
return new AccessToken(accessToken, clock.nowUtc().plusSeconds(expiresInSeconds).toDate());
return new AccessToken(accessToken, Date.from(clock.now().plusSeconds(expiresInSeconds)));
}
String createAssertion(JsonFactory jsonFactory, long currentTime) throws IOException {

View File

@@ -18,7 +18,7 @@ import static com.google.common.base.Suppliers.memoize;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap;
import static google.registry.config.ConfigUtils.makeUrl;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.Comparator.naturalOrder;
@@ -50,14 +50,14 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.net.URI;
import java.net.URL;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Duration;
/**
* Central clearing-house for all configuration.
@@ -225,7 +225,7 @@ public final class RegistryConfig {
*/
@Provides
@Config("databaseRetention")
public static java.time.Duration provideDatabaseRetention() {
public static Duration provideDatabaseRetention() {
return getDatabaseRetention();
}
@@ -271,7 +271,7 @@ public final class RegistryConfig {
@Provides
@Config("brdaDayOfWeek")
public static int provideBrdaDayOfWeek() {
return DateTimeConstants.TUESDAY;
return DayOfWeek.TUESDAY.getValue();
}
/**
@@ -281,8 +281,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("brdaInterval")
public static java.time.Duration provideBrdaInterval() {
return java.time.Duration.ofDays(7);
public static Duration provideBrdaInterval() {
return Duration.ofDays(7);
}
/**
@@ -315,8 +315,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("publishDnsUpdatesLockDuration")
public static java.time.Duration providePublishDnsUpdatesLockDuration() {
return java.time.Duration.ofMinutes(3);
public static Duration providePublishDnsUpdatesLockDuration() {
return Duration.ofMinutes(3);
}
/**
@@ -343,8 +343,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("readDnsRefreshRequestsActionRuntime")
public static java.time.Duration provideReadDnsRefreshRequestsRuntime() {
return java.time.Duration.ofSeconds(45);
public static Duration provideReadDnsRefreshRequestsRuntime() {
return Duration.ofSeconds(45);
}
/**
@@ -354,8 +354,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultATtl")
public static java.time.Duration provideDnsDefaultATtl() {
return java.time.Duration.ofHours(1);
public static Duration provideDnsDefaultATtl() {
return Duration.ofHours(1);
}
/**
@@ -365,8 +365,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultNsTtl")
public static java.time.Duration provideDnsDefaultNsTtl() {
return java.time.Duration.ofHours(3);
public static Duration provideDnsDefaultNsTtl() {
return Duration.ofHours(3);
}
/**
@@ -376,8 +376,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("dnsDefaultDsTtl")
public static java.time.Duration provideDnsDefaultDsTtl() {
return java.time.Duration.ofHours(1);
public static Duration provideDnsDefaultDsTtl() {
return Duration.ofHours(1);
}
@Provides
@@ -757,8 +757,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeInterval")
public static java.time.Duration provideRdeInterval() {
return java.time.Duration.ofDays(1);
public static Duration provideRdeInterval() {
return Duration.ofDays(1);
}
/**
@@ -768,8 +768,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeReportLockTimeout")
public static java.time.Duration provideRdeReportLockTimeout() {
return java.time.Duration.ofMinutes(1);
public static Duration provideRdeReportLockTimeout() {
return Duration.ofMinutes(1);
}
/**
@@ -792,8 +792,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeUploadLockTimeout")
public static java.time.Duration provideRdeUploadLockTimeout() {
return java.time.Duration.ofMinutes(30);
public static Duration provideRdeUploadLockTimeout() {
return Duration.ofMinutes(30);
}
/**
@@ -805,8 +805,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("rdeUploadSftpCooldown")
public static java.time.Duration provideRdeUploadSftpCooldown() {
return java.time.Duration.ofHours(2);
public static Duration provideRdeUploadSftpCooldown() {
return Duration.ofHours(2);
}
/**
@@ -841,8 +841,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("sheetLockTimeout")
public static java.time.Duration provideSheetLockTimeout() {
return java.time.Duration.ofHours(1);
public static Duration provideSheetLockTimeout() {
return Duration.ofHours(1);
}
/**
@@ -865,8 +865,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("emailThrottleDuration")
public static java.time.Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.misc.emailThrottleSeconds);
public static Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
return Duration.ofSeconds(config.misc.emailThrottleSeconds);
}
/**
@@ -946,8 +946,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("sshTimeout")
public static java.time.Duration provideSshTimeout() {
return java.time.Duration.ofSeconds(30);
public static Duration provideSshTimeout() {
return Duration.ofSeconds(30);
}
/**
@@ -957,8 +957,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("transactionCooldown")
public static java.time.Duration provideTransactionCooldown() {
return java.time.Duration.ofMinutes(5);
public static Duration provideTransactionCooldown() {
return Duration.ofMinutes(5);
}
/**
@@ -1034,7 +1034,7 @@ public final class RegistryConfig {
@Provides
@Config("metricsWriteInterval")
public static Duration provideMetricsWriteInterval(RegistryConfigSettings config) {
return Duration.standardSeconds(config.monitoring.writeIntervalSeconds);
return Duration.ofSeconds(config.monitoring.writeIntervalSeconds);
}
/**
@@ -1148,8 +1148,8 @@ public final class RegistryConfig {
@Provides
@Config("tokenRefreshDelay")
public static java.time.Duration provideTokenRefreshDelay(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.credentialOAuth.tokenRefreshDelaySeconds);
public static Duration provideTokenRefreshDelay(RegistryConfigSettings config) {
return Duration.ofSeconds(config.credentialOAuth.tokenRefreshDelaySeconds);
}
/** OAuth client ID used by the nomulus tool. */
@@ -1186,28 +1186,28 @@ public final class RegistryConfig {
@Provides
@Config("maxValidityDaysSchedule")
public static ImmutableSortedMap<DateTime, Integer> provideValidityDaysMap(
public static ImmutableSortedMap<Instant, Integer> provideValidityDaysMap(
RegistryConfigSettings config) {
return config.sslCertificateValidation.maxValidityDaysSchedule.entrySet().stream()
.collect(
toImmutableSortedMap(
naturalOrder(),
e ->
"START_OF_TIME".equals(e.getKey())
? START_OF_TIME
: DateTime.parse(e.getKey()),
"START_INSTANT".equals(e.getKey())
? START_INSTANT
: Instant.parse(e.getKey()),
Entry::getValue));
}
@Provides
@Config("expirationWarningDays")
public static int provideExpirationWarningDays(RegistryConfigSettings config) {
public static long provideExpirationWarningDays(RegistryConfigSettings config) {
return config.sslCertificateValidation.expirationWarningDays;
}
@Provides
@Config("expirationWarningIntervalDays")
public static int provideExpirationWarningIntervalDays(RegistryConfigSettings config) {
public static long provideExpirationWarningIntervalDays(RegistryConfigSettings config) {
return config.sslCertificateValidation.expirationWarningIntervalDays;
}
@@ -1327,15 +1327,15 @@ public final class RegistryConfig {
@Provides
@Config("bsaLockLeaseExpiry")
public static java.time.Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
return java.time.Duration.ofMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
public static Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
return Duration.ofMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
}
/** Returns the desired interval between successive BSA downloads. */
@Provides
@Config("bsaDownloadInterval")
public static java.time.Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
return java.time.Duration.ofMinutes(config.bsa.bsaDownloadIntervalMinutes);
public static Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
return Duration.ofMinutes(config.bsa.bsaDownloadIntervalMinutes);
}
/**
@@ -1344,8 +1344,8 @@ public final class RegistryConfig {
*/
@Provides
@Config("bsaMaxNopInterval")
public static java.time.Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
return java.time.Duration.ofHours(config.bsa.bsaMaxNopIntervalHours);
public static Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
return Duration.ofHours(config.bsa.bsaMaxNopIntervalHours);
}
@Provides
@@ -1356,16 +1356,14 @@ public final class RegistryConfig {
@Provides
@Config("domainCreateTxnCommitTimeLag")
public static java.time.Duration provideDomainCreateTxnCommitTimeLag(
RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
public static Duration provideDomainCreateTxnCommitTimeLag(RegistryConfigSettings config) {
return Duration.ofSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
}
@Provides
@Config("bsaValidationMaxStaleness")
public static java.time.Duration provideBsaValidationMaxStaleness(
RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
public static Duration provideBsaValidationMaxStaleness(RegistryConfigSettings config) {
return Duration.ofSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
}
@Provides
@@ -1376,8 +1374,8 @@ public final class RegistryConfig {
@Provides
@Config("bsaAuthTokenExpiry")
public static java.time.Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.bsa.authTokenExpirySeconds);
public static Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
return Duration.ofSeconds(config.bsa.authTokenExpirySeconds);
}
@Provides
@@ -1490,8 +1488,8 @@ public final class RegistryConfig {
*
* @see google.registry.tools.server.GenerateZoneFilesAction
*/
public static java.time.Duration getDatabaseRetention() {
return java.time.Duration.ofDays(30);
public static Duration getDatabaseRetention() {
return Duration.ofDays(30);
}
public static boolean areServersLocal() {
@@ -1507,8 +1505,8 @@ public final class RegistryConfig {
}
/** Returns the amount of time a singleton should be cached, before expiring. */
public static java.time.Duration getSingletonCacheRefreshDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds);
public static Duration getSingletonCacheRefreshDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds);
}
/**
@@ -1517,13 +1515,13 @@ public final class RegistryConfig {
* @see google.registry.model.tld.label.ReservedList
* @see google.registry.model.tld.label.PremiumList
*/
public static java.time.Duration getDomainLabelListCacheDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds);
public static Duration getDomainLabelListCacheDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds);
}
/** Returns the amount of time a singleton should be cached in persist mode, before expiring. */
public static java.time.Duration getSingletonCachePersistDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds);
public static Duration getSingletonCachePersistDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds);
}
/**
@@ -1545,8 +1543,8 @@ public final class RegistryConfig {
/**
* Returns the amount of time an EPP resource or key should be cached in memory before expiring.
*/
public static java.time.Duration getEppResourceCachingDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds);
public static Duration getEppResourceCachingDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds);
}
/** Returns the maximum number of EPP resources and keys to keep in in-memory cache. */
@@ -1555,8 +1553,8 @@ public final class RegistryConfig {
}
/** Returns the amount of time that a particular claims list should be cached. */
public static java.time.Duration getClaimsListCacheDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.claimsListCachingSeconds);
public static Duration getClaimsListCacheDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.claimsListCachingSeconds);
}
/** Returns the email address that outgoing emails from the app are sent from. */
@@ -1639,7 +1637,6 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
}
/** A discount for all sunrise domain creates, between 0.0 (no discount) and 1.0 (free). */
public static double getSunriseDomainCreateDiscount() {
return CONFIG_SETTINGS.get().registryPolicy.sunriseDomainCreateDiscount;

View File

@@ -214,8 +214,8 @@ public class RegistryConfigSettings {
/** Configuration for the certificate checker. */
public static class SslCertificateValidation {
public Map<String, Integer> maxValidityDaysSchedule;
public int expirationWarningDays;
public int expirationWarningIntervalDays;
public long expirationWarningDays;
public long expirationWarningIntervalDays;
public int minimumRsaKeyLength;
public Set<String> allowedEcdsaCurves;
public String expirationWarningEmailBodyText;

View File

@@ -71,7 +71,6 @@
<max-backoff>180s</max-backoff>
</queue>
<!-- Queue for tasks that communicate with TMCH MarksDB webserver. -->
<queue>
<name>marksdb</name>

View File

@@ -476,7 +476,7 @@ sslCertificateValidation:
# The entry key is the date closest before the date the certificate was issued
# and the entry value is the applicable maximum validity days for that certificate.
maxValidityDaysSchedule:
"START_OF_TIME": 825
"START_INSTANT": 825
"2020-09-01T00:00:00Z": 398
# The number of days before a certificate expires that indicates the
# certificate is nearing expiration and warnings should be sent.

View File

@@ -17,7 +17,6 @@ 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;
@@ -151,7 +150,7 @@ public final class DnsUtils {
if (tldName.isPresent()) {
Tld tld = Tld.get(tldName.get().toString());
if (tld.getDnsAPlusAaaaTtl().isPresent()) {
dnsAPlusAaaaTtl = toJavaDuration(tld.getDnsAPlusAaaaTtl().get());
dnsAPlusAaaaTtl = tld.getDnsAPlusAaaaTtl().get();
}
}
return dnsAPlusAaaaTtl.toSeconds();

View File

@@ -44,7 +44,6 @@ 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;
@@ -151,7 +150,6 @@ public class CloudDnsWriter extends BaseDnsWriter {
.setTtl(
(int)
tld.getDnsDsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(defaultDsTtl)
.toSeconds())
.setType("DS")
@@ -179,7 +177,6 @@ public class CloudDnsWriter extends BaseDnsWriter {
.setTtl(
(int)
tld.getDnsNsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(defaultNsTtl)
.toSeconds())
.setType("NS")

View File

@@ -34,7 +34,6 @@ 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;
@@ -196,7 +195,6 @@ public class DnsUpdateWriter extends BaseDnsWriter {
toAbsoluteName(domain.getDomainName()),
DClass.IN,
tld.getDnsDsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(dnsDefaultDsTtl)
.toSeconds(),
signerData.getKeyTag(),
@@ -239,7 +237,6 @@ public class DnsUpdateWriter extends BaseDnsWriter {
toAbsoluteName(domain.getDomainName()),
DClass.IN,
tld.getDnsNsTtl()
.map(DateTimeUtils::toJavaDuration)
.orElse(dnsDefaultNsTtl)
.toSeconds(),
toAbsoluteName(hostName));

View File

@@ -60,7 +60,8 @@ public class CheckApiMetrics {
}
public void recordProcessingTime(CheckApiMetric metric) {
long elapsedTime = metric.endTimestamp().getMillis() - metric.startTimestamp().getMillis();
long elapsedTime =
metric.endTimestamp().toEpochMilli() - metric.startTimestamp().toEpochMilli();
processingTime.record(
elapsedTime,
metric.tier().map(Tier::getDisplayLabel).orElse(""),

View File

@@ -98,7 +98,7 @@ public class EppMetrics {
String eppStatusCode =
metric.getStatus().isPresent() ? String.valueOf(metric.getStatus().get().code) : "";
long processingTime =
metric.getEndTimestamp().getMillis() - metric.getStartTimestamp().getMillis();
metric.getEndTimestamp().toEpochMilli() - metric.getStartTimestamp().toEpochMilli();
String commandName = metric.getCommandName().orElse("");
String tld = metric.getTld().orElse("");
requestTime.record(processingTime, commandName, getTrafficType(tld).toString(), eppStatusCode);

View File

@@ -49,4 +49,3 @@ public class EppTlsAction implements Runnable {
inputXmlBytes);
}
}

View File

@@ -71,6 +71,4 @@ public class StatelessRequestSessionMetadata extends SessionMetadata {
throw new UnsupportedOperationException();
}
}

View File

@@ -15,15 +15,15 @@
package google.registry.flows.certs;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.plusDays;
import static google.registry.util.DateTimeUtils.toLocalDate;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import jakarta.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
@@ -33,6 +33,8 @@ import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.stream.Collectors;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jce.ECNamedCurveTable;
@@ -41,51 +43,49 @@ import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
import org.bouncycastle.util.io.pem.PemObjectGenerator;
import org.bouncycastle.util.io.pem.PemWriter;
import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator;
import org.joda.time.Days;
/** A utility to check that a given certificate meets our requirements */
public class CertificateChecker {
private final ImmutableSortedMap<DateTime, Integer> maxValidityLengthSchedule;
private final int expirationWarningDays;
private final ImmutableSortedMap<Instant, Integer> maxValidityLengthSchedule;
private final long expirationWarningDays;
private final int minimumRsaKeyLength;
private final Clock clock;
private final ImmutableSet<String> allowedEcdsaCurves;
private final int expirationWarningIntervalDays;
private final long expirationWarningIntervalDays;
/**
* Constructs a CertificateChecker instance with the specified configuration parameters.
*
* <p>The max validity length schedule is a sorted map of {@link DateTime} to {@link Integer}
* <p>The max validity length schedule is a sorted map of {@link Instant} to {@link Integer}
* entries representing a maximum validity period for certificates issued on or after that date.
* The first entry must have a key of {@link DateTimeUtils#START_OF_TIME}, such that every
* possible date has an applicable max validity period. Since security requirements tighten over
* time, the max validity periods will be decreasing as the date increases.
* The first entry must have a key of {@link google.registry.util.DateTimeUtils#START_INSTANT},
* such that every possible date has an applicable max validity period. Since security
* requirements tighten over time, the max validity periods will be decreasing as the date
* increases.
*
* <p>The validity length schedule used by all major Web browsers as of 2020Q4 would be
* represented as:
*
* <pre>
* ImmutableSortedMap.of(
* START_OF_TIME, 825,
* DateTime.parse("2020-09-01T00:00:00Z"), 398
* START_INSTANT, 825,
* Instant.parse("2020-09-01T00:00:00Z"), 398
* );
* </pre>
*/
@Inject
public CertificateChecker(
@Config("maxValidityDaysSchedule")
ImmutableSortedMap<DateTime, Integer> maxValidityDaysSchedule,
@Config("expirationWarningDays") int expirationWarningDays,
@Config("expirationWarningIntervalDays") int expirationWarningIntervalDays,
ImmutableSortedMap<Instant, Integer> maxValidityDaysSchedule,
@Config("expirationWarningDays") long expirationWarningDays,
@Config("expirationWarningIntervalDays") long expirationWarningIntervalDays,
@Config("minimumRsaKeyLength") int minimumRsaKeyLength,
@Config("allowedEcdsaCurves") ImmutableSet<String> allowedEcdsaCurves,
Clock clock) {
checkArgument(
maxValidityDaysSchedule.containsKey(START_OF_TIME),
"Max validity length schedule must contain an entry for START_OF_TIME");
maxValidityDaysSchedule.containsKey(START_INSTANT),
"Max validity length schedule must contain an entry for START_INSTANT");
this.maxValidityLengthSchedule = maxValidityDaysSchedule;
this.expirationWarningDays = expirationWarningDays;
this.minimumRsaKeyLength = minimumRsaKeyLength;
@@ -94,10 +94,10 @@ public class CertificateChecker {
this.clock = clock;
}
private static int getValidityLengthInDays(X509Certificate certificate) {
DateTime start = toDateTime(certificate.getNotBefore().toInstant());
DateTime end = toDateTime(certificate.getNotAfter().toInstant());
return Days.daysBetween(start.withTimeAtStartOfDay(), end.withTimeAtStartOfDay()).getDays();
private static long getValidityLengthInDays(X509Certificate certificate) {
return ChronoUnit.DAYS.between(
toLocalDate(certificate.getNotBefore().toInstant()),
toLocalDate(certificate.getNotAfter().toInstant()));
}
/** Checks if the curve used for a public key is in the list of acceptable curves. */
@@ -159,16 +159,16 @@ public class CertificateChecker {
ImmutableSet.Builder<CertificateViolation> violations = new ImmutableSet.Builder<>();
// Check if currently in validity period
DateTime now = clock.nowUtc();
if (DateTimeComparator.getInstance().compare(certificate.getNotAfter(), now) < 0) {
Instant now = clock.now();
if (certificate.getNotAfter().toInstant().isBefore(now)) {
violations.add(CertificateViolation.EXPIRED);
} else if (DateTimeComparator.getInstance().compare(certificate.getNotBefore(), now) > 0) {
} else if (certificate.getNotBefore().toInstant().isAfter(now)) {
violations.add(CertificateViolation.NOT_YET_VALID);
}
// Check validity period length
int maxValidityDays =
maxValidityLengthSchedule.floorEntry(new DateTime(certificate.getNotBefore())).getValue();
long maxValidityDays =
maxValidityLengthSchedule.floorEntry(certificate.getNotBefore().toInstant()).getValue();
if (getValidityLengthInDays(certificate) > maxValidityDays) {
violations.add(CertificateViolation.VALIDITY_LENGTH_TOO_LONG);
}
@@ -225,25 +225,24 @@ public class CertificateChecker {
/** Returns whether the client should receive a notification email. */
public boolean shouldReceiveExpiringNotification(
DateTime lastExpiringNotificationSentDate, String certificateStr) {
Instant lastExpiringNotificationSentDate, String certificateStr) {
X509Certificate certificate = getCertificate(certificateStr);
DateTime now = clock.nowUtc();
Instant now = clock.now();
// the expiration date is one day after lastValidDate
DateTime lastValidDate = new DateTime(certificate.getNotAfter());
Instant lastValidDate = certificate.getNotAfter().toInstant();
if (lastValidDate.isBefore(now)) {
return false;
}
/*
* Client should receive a notification if:
* 1) client has never received notification (lastExpiringNotificationSentDate is initially
* set to START_OF_TIME) and the certificate has entered the expiring period, OR
* set to START_INSTANT) and the certificate has entered the expiring period, OR
* 2) client has received notification but the interval between now and
* lastExpiringNotificationSentDate is greater than expirationWarningIntervalDays.
*/
return !lastValidDate.isAfter(now.plusDays(expirationWarningDays))
&& (lastExpiringNotificationSentDate.equals(START_OF_TIME)
|| !lastExpiringNotificationSentDate
.plusDays(expirationWarningIntervalDays)
return !lastValidDate.isAfter(plusDays(now, expirationWarningDays))
&& (lastExpiringNotificationSentDate.equals(START_INSTANT)
|| !plusDays(lastExpiringNotificationSentDate, expirationWarningIntervalDays)
.isAfter(now));
}

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -14,7 +14,6 @@
package google.registry.flows.contact;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;

View File

@@ -53,7 +53,6 @@ import static google.registry.model.tld.label.ReservationType.NAME_COLLISION;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -121,10 +120,9 @@ import google.registry.model.tmch.ClaimsList;
import google.registry.model.tmch.ClaimsListDao;
import google.registry.tmch.LordnTaskUtils.LordnPhase;
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;
/**
* An EPP flow that creates a new domain resource.
@@ -565,7 +563,7 @@ public final class DomainCreateFlow implements MutatingFlow {
ImmutableSet.of(
DomainTransactionRecord.create(
tld.getTldStr(),
now.plusMillis(addGracePeriod.getMillis()),
now.plus(addGracePeriod),
TransactionReportField.netAddsFieldFromYears(period.getValue()),
1)));
}
@@ -603,11 +601,10 @@ public final class DomainCreateFlow implements MutatingFlow {
.setEventTime(now)
.setAllocationToken(allocationToken.map(AllocationToken::createVKey).orElse(null))
.setBillingTime(
now.plusMillis(
(isAnchorTenant
? tld.getAnchorTenantAddGracePeriodLength()
: tld.getAddGracePeriodLength())
.getMillis()))
now.plus(
isAnchorTenant
? tld.getAnchorTenantAddGracePeriodLength()
: tld.getAddGracePeriodLength()))
.setFlags(flagsBuilder.build())
.setDomainHistoryId(domainHistoryId)
.build();
@@ -652,10 +649,9 @@ public final class DomainCreateFlow implements MutatingFlow {
}
private void verifyDomainDoesNotExist() throws ResourceCreateContentionException {
Optional<DateTime> previousDeletionTime =
Optional<Instant> previousDeletionTime =
domainDeletionTimeCache.getDeletionTimeForDomain(targetId);
if (previousDeletionTime.isPresent()
&& !tm().getTxTime().isAfter(toInstant(previousDeletionTime.get()))) {
if (previousDeletionTime.isPresent() && !tm().getTxTime().isAfter(previousDeletionTime.get())) {
throw new ResourceCreateContentionException(targetId);
}
}

View File

@@ -40,9 +40,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
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 static google.registry.util.DateTimeUtils.minusYears;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -101,14 +99,13 @@ import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.model.transfer.TransferStatus;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* An EPP flow that deletes a domain.
@@ -172,10 +169,9 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
eppInput.getSingleExtension(DomainDeleteSuperuserExtension.class);
if (domainDeleteSuperuserExtension.isPresent()) {
redemptionGracePeriodLength =
Duration.standardDays(
domainDeleteSuperuserExtension.get().getRedemptionGracePeriodDays());
Duration.ofDays(domainDeleteSuperuserExtension.get().getRedemptionGracePeriodDays());
pendingDeleteLength =
Duration.standardDays(domainDeleteSuperuserExtension.get().getPendingDeleteDays());
Duration.ofDays(domainDeleteSuperuserExtension.get().getPendingDeleteDays());
}
boolean inAddGracePeriod =
existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.ADD);
@@ -188,11 +184,11 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
: redemptionGracePeriodLength.plus(pendingDeleteLength);
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
historyBuilder.setRevisionId(domainHistoryId.getRevisionId());
Instant deletionTime = now.plusMillis(durationUntilDelete.getMillis());
Instant deletionTime = now.plus(durationUntilDelete);
if (durationUntilDelete.equals(Duration.ZERO)) {
builder.setDeletionTime(now).setStatusValues(null);
} else {
Instant redemptionTime = now.plusMillis(redemptionGracePeriodLength.getMillis());
Instant redemptionTime = now.plus(redemptionGracePeriodLength);
asyncTaskEnqueuer.enqueueAsyncResave(
existingDomain.createVKey(), now, ImmutableSortedSet.of(redemptionTime, deletionTime));
builder
@@ -217,7 +213,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
// Enqueue the deletion poll message if the delete is asynchronous or if requested by a
// superuser (i.e. the registrar didn't request this delete and thus should be notified even if
// it is synchronous).
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
if (durationUntilDelete.compareTo(Duration.ZERO) > 0 || isSuperuser) {
if (RegistryConfig.getNoPollMessageOnDeletionRegistrarIds()
.contains(existingDomain.getCurrentSponsorRegistrarId())) {
logger.atInfo().log(
@@ -233,7 +229,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
// Send a second poll message immediately if the domain is being deleted asynchronously by a
// registrar other than the sponsoring registrar (which will necessarily be a superuser).
if (durationUntilDelete.isLongerThan(Duration.ZERO)
if (durationUntilDelete.compareTo(Duration.ZERO) > 0
&& !registrarId.equals(existingDomain.getPersistedCurrentSponsorRegistrarId())) {
entitiesToInsert.add(
createImmediateDeletePollMessage(existingDomain, domainHistoryId, now, deletionTime));
@@ -250,12 +246,11 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
// Take the amount of registration time being refunded off the expiration time.
// This can be either add grace periods or renew grace periods.
BillingEvent billingEvent = tm().loadByKey(gracePeriod.getBillingEvent());
newExpirationTime =
newExpirationTime.atZone(UTC).minusYears(billingEvent.getPeriodYears()).toInstant();
newExpirationTime = minusYears(newExpirationTime, billingEvent.getPeriodYears());
} 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(UTC).minusYears(1).toInstant();
newExpirationTime = minusYears(newExpirationTime, 1);
}
}
}
@@ -343,7 +338,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
cancelledRecords,
DomainTransactionRecord.create(
domain.getTld(),
now.plusMillis(durationUntilDelete.getMillis()),
now.plus(durationUntilDelete),
inAddGracePeriod
? TransactionReportField.DELETED_DOMAINS_GRACE
: TransactionReportField.DELETED_DOMAINS_NOGRACE,
@@ -420,9 +415,9 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
BillingRecurrence billingRecurrence, GracePeriod gracePeriod, Instant now) {
if (gracePeriod.getType() == GracePeriodStatus.AUTO_RENEW) {
// If we updated the autorenew billing event, reuse it.
DateTime autoRenewTime =
toDateTime(billingRecurrence.getRecurrenceTimeOfYear().getLastInstanceBeforeOrAt(now));
return getDomainRenewCost(targetId, toInstant(autoRenewTime), 1);
Instant autoRenewTime =
billingRecurrence.getRecurrenceTimeOfYear().getLastInstanceBeforeOrAt(now);
return getDomainRenewCost(targetId, autoRenewTime, 1);
}
return tm().loadByKey(checkNotNull(gracePeriod.getBillingEvent())).getCost();
}

View File

@@ -15,6 +15,7 @@
package google.registry.flows.domain;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
@@ -24,9 +25,10 @@ import com.github.benmanes.caffeine.cache.Ticker;
import com.google.common.collect.ImmutableSet;
import google.registry.model.ForeignKeyUtils;
import google.registry.model.domain.Domain;
import google.registry.util.DateTimeUtils;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Optional;
import org.joda.time.DateTime;
/**
* Functionally-static loading cache that keeps track of deletion (AKA drop) times for domains.
@@ -39,7 +41,7 @@ import org.joda.time.DateTime;
*
* <p>The cache is fairly short-lived (as we're concerned about many requests at basically the same
* time), and entries also expire when the drop actually happens. If the domain is re-created after
* a drop, the next load attempt will populate the cache with a deletion time of END_OF_TIME, which
* a drop, the next load attempt will populate the cache with a deletion time of END_INSTANT, which
* will be read from the cache by subsequent attempts.
*
* <p>We take advantage of the fact that Caffeine caches don't store nulls returned from the
@@ -57,8 +59,7 @@ import org.joda.time.DateTime;
public class DomainDeletionTimeCache {
// Max expiry time is ten minutes
private static final long NANOS_IN_ONE_MILLISECOND = 100000L;
private static final long MAX_EXPIRY_NANOS = 10L * 60L * 1000L * NANOS_IN_ONE_MILLISECOND;
private static final long MAX_EXPIRY_NANOS = Duration.ofMinutes(10).toNanos();
private static final int MAX_ENTRIES = 500;
/**
@@ -69,15 +70,15 @@ public class DomainDeletionTimeCache {
*
* <p>NB: the Expiry class requires the return value in <b>nanoseconds</b>, not milliseconds
*/
private static final Expiry<String, DateTime> EXPIRY_POLICY =
private static final Expiry<String, Instant> EXPIRY_POLICY =
new Expiry<>() {
@Override
public long expireAfterCreate(String key, DateTime value, long currentTime) {
public long expireAfterCreate(String key, Instant value, long currentTime) {
// Watch out for Long overflow
long deletionTimeNanos =
value.equals(DateTimeUtils.END_OF_TIME)
value.equals(END_INSTANT)
? Long.MAX_VALUE
: value.getMillis() * NANOS_IN_ONE_MILLISECOND;
: ChronoUnit.NANOS.between(Instant.EPOCH, value);
long nanosUntilDeletion = deletionTimeNanos - currentTime;
return Math.max(0L, Math.min(MAX_EXPIRY_NANOS, nanosUntilDeletion));
}
@@ -85,31 +86,31 @@ public class DomainDeletionTimeCache {
/** Reset the time entirely on update, as if we were creating the entry anew. */
@Override
public long expireAfterUpdate(
String key, DateTime value, long currentTime, long currentDuration) {
String key, Instant value, long currentTime, long currentDuration) {
return expireAfterCreate(key, value, currentTime);
}
/** Reads do not change the expiry duration. */
@Override
public long expireAfterRead(
String key, DateTime value, long currentTime, long currentDuration) {
String key, Instant value, long currentTime, long currentDuration) {
return currentDuration;
}
};
/** Attempt to load the domain's deletion time if the domain exists. */
private static final CacheLoader<String, DateTime> CACHE_LOADER =
private static final CacheLoader<String, Instant> CACHE_LOADER =
(domainName) -> {
ForeignKeyUtils.MostRecentResource mostRecentResource =
ForeignKeyUtils.loadMostRecentResources(
Domain.class, ImmutableSet.of(domainName), false)
.get(domainName);
return mostRecentResource == null ? null : mostRecentResource.getDeletionTime();
return mostRecentResource == null ? null : mostRecentResource.deletionTime();
};
// Unfortunately, maintenance tasks aren't necessarily already in a transaction
private static final Ticker TRANSACTION_TIME_TICKER =
() -> tm().reTransact(() -> tm().getTransactionTime().getMillis() * NANOS_IN_ONE_MILLISECOND);
() -> tm().reTransact(() -> ChronoUnit.NANOS.between(Instant.EPOCH, tm().getTxTime()));
public static DomainDeletionTimeCache create() {
return new DomainDeletionTimeCache(
@@ -120,14 +121,14 @@ public class DomainDeletionTimeCache {
.build(CACHE_LOADER));
}
private final LoadingCache<String, DateTime> cache;
private final LoadingCache<String, Instant> cache;
private DomainDeletionTimeCache(LoadingCache<String, DateTime> cache) {
private DomainDeletionTimeCache(LoadingCache<String, Instant> cache) {
this.cache = cache;
}
/** Returns the domain's deletion time, or null if it doesn't currently exist. */
public Optional<DateTime> getDeletionTimeForDomain(String domainName) {
public Optional<Instant> getDeletionTimeForDomain(String domainName) {
return Optional.ofNullable(cache.get(domainName));
}
}

View File

@@ -124,6 +124,7 @@ import google.registry.tldconfig.idn.IdnLabelValidator;
import google.registry.tools.DigestType;
import google.registry.util.Idn;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
@@ -133,7 +134,6 @@ import java.util.Set;
import javax.annotation.Nullable;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.Duration;
import org.xbill.DNS.DNSSEC.Algorithm;
/** Static utility functions for domain flows. */
@@ -1114,7 +1114,7 @@ public class DomainFlowUtils {
"FROM DomainHistory WHERE modificationTime >= :beginning AND repoId = "
+ ":repoId ORDER BY modificationTime ASC",
DomainHistory.class)
.setParameter("beginning", now.minusMillis(maxSearchPeriod.getMillis()))
.setParameter("beginning", now.minus(maxSearchPeriod))
.setParameter("repoId", domain.getRepoId())
.getResultList();
}

View File

@@ -34,7 +34,7 @@ import static google.registry.flows.domain.token.AllocationTokenFlowUtils.maybeA
import static google.registry.flows.domain.token.AllocationTokenFlowUtils.verifyBulkTokenAllowedOnDomain;
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 google.registry.util.DateTimeUtils.toLocalDate;
import static java.time.ZoneOffset.UTC;
import com.google.common.collect.ImmutableList;
@@ -87,10 +87,10 @@ import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.tld.Tld;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.Duration;
/**
* An EPP flow that renews a domain.
@@ -310,7 +310,7 @@ public final class DomainRenewFlow implements MutatingFlow {
ImmutableSet.of(
DomainTransactionRecord.create(
newDomain.getTld(),
now.plusMillis(renewGracePeriod.getMillis()),
now.plus(renewGracePeriod),
TransactionReportField.netRenewsFieldFromYears(period.getValue()),
1)))
.build();
@@ -335,7 +335,7 @@ public final class DomainRenewFlow implements MutatingFlow {
// If the date they specify doesn't match the expiration, fail. (This is an idempotence check).
if (!command
.getCurrentExpirationDate()
.equals(toDateTime(existingDomain.getRegistrationExpirationTime()).toLocalDate())) {
.equals(toLocalDate(existingDomain.getRegistrationExpirationTime()))) {
throw new IncorrectCurrentExpirationDateException();
}
}
@@ -359,7 +359,7 @@ public final class DomainRenewFlow implements MutatingFlow {
.filter(t -> AllocationToken.TokenBehavior.DEFAULT.equals(t.getTokenBehavior()))
.map(AllocationToken::createVKey)
.orElse(null))
.setBillingTime(now.plusMillis(Tld.get(tld).getRenewGracePeriodLength().getMillis()))
.setBillingTime(now.plus(Tld.get(tld).getRenewGracePeriodLength()))
.setDomainHistoryId(domainHistoryId)
.build();
}

View File

@@ -168,8 +168,7 @@ public final class DomainTransferApproveFlow implements MutatingFlow {
hasBulkToken ? null : existingBillingRecurrence)
.getRenewCost())
.setEventTime(now)
.setBillingTime(
now.plusMillis(Tld.get(tldStr).getTransferGracePeriodLength().getMillis()))
.setBillingTime(now.plus(Tld.get(tldStr).getTransferGracePeriodLength()))
.setDomainHistoryId(domainHistoryId)
.build());
@@ -292,7 +291,7 @@ public final class DomainTransferApproveFlow implements MutatingFlow {
cancelingRecords,
DomainTransactionRecord.create(
newDomain.getTld(),
now.plusMillis(tld.getTransferGracePeriodLength().getMillis()),
now.plus(tld.getTransferGracePeriodLength()),
TRANSFER_SUCCESSFUL,
1)))
.build();

View File

@@ -32,7 +32,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.toDateTime;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException;
@@ -108,8 +107,7 @@ public final class DomainTransferRejectFlow implements MutatingFlow {
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
}
Domain newDomain =
denyPendingTransfer(
existingDomain, TransferStatus.CLIENT_REJECTED, toDateTime(now), registrarId);
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, registrarId);
DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now);
tm().update(newDomain);
tm().insertAll(

View File

@@ -220,7 +220,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
domainTransferRequestSuperuserExtension ->
now.plus(
domainTransferRequestSuperuserExtension.getAutomaticTransferLength(), DAYS))
.orElseGet(() -> now.plusMillis(tld.getAutomaticTransferLength().getMillis()));
.orElseGet(() -> now.plus(tld.getAutomaticTransferLength()));
// 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.
// The gaining registrar is still billed for the extra year; the losing registrar will get a
@@ -368,8 +368,8 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
ImmutableSet.of(
DomainTransactionRecord.create(
tld.getTldStr(),
now.plusMillis(tld.getAutomaticTransferLength().getMillis())
.plusMillis(tld.getTransferGracePeriodLength().getMillis()),
now.plus(tld.getAutomaticTransferLength())
.plus(tld.getTransferGracePeriodLength()),
TransactionReportField.TRANSFER_SUCCESSFUL,
1)))
.build();

View File

@@ -316,8 +316,7 @@ public final class DomainTransferUtils {
.setCost(transferCost)
.setPeriodYears(1)
.setEventTime(automaticTransferTime)
.setBillingTime(
automaticTransferTime.plusMillis(registry.getTransferGracePeriodLength().getMillis()))
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
.setDomainHistoryId(domainHistoryId)
.build();
}

View File

@@ -56,8 +56,9 @@ public final class GmailClient {
private final InternetAddress outgoingEmailAddressWithUsername;
private final InternetAddress replyToEmailAddress;
// TODO(b/510340944): make package private after feature is rolled out
@Inject
GmailClient(
public GmailClient(
Lazy<Gmail> gmail,
Retrier retrier,
@Config("isEmailSendingEnabled") boolean isEmailSendingEnabled,

View File

@@ -41,7 +41,6 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
*/
public final class KeySerializer {
private KeySerializer() {}
/**

View File

@@ -33,13 +33,13 @@ import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import org.joda.time.DateTime;
/**
* Simple load test action that can generate configurable QPSes of various EPP actions.
@@ -160,7 +160,7 @@ public class LoadTestAction implements Runnable {
@Override
public void run() {
validateAndLogRequest();
DateTime initialStartSecond = clock.nowUtc().plusSeconds(delaySeconds);
Instant initialStartSecond = clock.now().plus(Duration.ofSeconds(delaySeconds));
ImmutableList.Builder<String> preTaskXmls = new ImmutableList.Builder<>();
ImmutableList.Builder<String> hostPrefixesBuilder = new ImmutableList.Builder<>();
for (int i = 0; i < successfulDomainCreatesPerSecond; i++) {
@@ -169,12 +169,12 @@ public class LoadTestAction implements Runnable {
preTaskXmls.add(
xmlHostCreateTmpl.replace("%host%", hostPrefix));
}
enqueue(createTasks(preTaskXmls.build(), clock.nowUtc()));
enqueue(createTasks(preTaskXmls.build(), clock.now()));
ImmutableList<String> hostPrefixes = hostPrefixesBuilder.build();
ImmutableList.Builder<Task> tasks = new ImmutableList.Builder<>();
for (int offsetSeconds = 0; offsetSeconds < runSeconds; offsetSeconds++) {
DateTime startSecond = initialStartSecond.plusSeconds(offsetSeconds);
Instant startSecond = initialStartSecond.plus(Duration.ofSeconds(offsetSeconds));
// The first "failed" creates might actually succeed if the object doesn't already exist, but
// that shouldn't affect the load numbers.
tasks.addAll(
@@ -265,12 +265,11 @@ public class LoadTestAction implements Runnable {
return name.toString();
}
private ImmutableList<Task> createTasks(ImmutableList<String> xmls, DateTime start) {
private ImmutableList<Task> createTasks(ImmutableList<String> xmls, Instant start) {
ImmutableList.Builder<Task> tasks = new ImmutableList.Builder<>();
for (int i = 0; i < xmls.size(); i++) {
// Space tasks evenly within across a second.
Instant scheduleTime =
Instant.ofEpochMilli(start.plusMillis((int) (1000.0 / xmls.size() * i)).getMillis());
Instant scheduleTime = start.plus(Duration.ofMillis((long) (1000.0 / xmls.size() * i)));
tasks.add(
cloudTasksUtils
.createTask(

View File

@@ -21,7 +21,6 @@ import dagger.Module;
import dagger.Provides;
import google.registry.request.Parameter;
import jakarta.servlet.http.HttpServletRequest;
import org.joda.time.Minutes;
/**
* Dagger module for loadtest package.
@@ -42,15 +41,13 @@ public final class LoadTestModule {
@Provides
@Parameter("delaySeconds")
static int provideDelaySeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "delaySeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "delaySeconds").orElse(60);
}
@Provides
@Parameter("runSeconds")
static int provideRunSeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "runSeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "runSeconds").orElse(60);
}
@Provides

View File

@@ -42,6 +42,7 @@ import google.registry.model.tld.Tld.TldState;
import google.registry.persistence.VKey;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -51,7 +52,6 @@ import java.util.Set;
import java.util.SortedMap;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.Duration;
/** A collection of static utility classes/functions to convert entities to/from YAML files. */
public class EntityYamlUtils {
@@ -337,7 +337,7 @@ public class EntityYamlUtils {
public TimedTransitionProperty<TldState> deserialize(
JsonParser jp, DeserializationContext context) throws IOException {
SortedMap<String, String> valueMap = jp.readValueAs(SortedMap.class);
return TimedTransitionProperty.fromValueMapInstant(
return TimedTransitionProperty.fromValueMap(
valueMap.keySet().stream()
.collect(
toImmutableSortedMap(
@@ -363,7 +363,7 @@ public class EntityYamlUtils {
public TimedTransitionProperty<Money> deserialize(JsonParser jp, DeserializationContext context)
throws IOException {
SortedMap<String, LinkedHashMap<String, Object>> valueMap = jp.readValueAs(SortedMap.class);
return TimedTransitionProperty.fromValueMapInstant(
return TimedTransitionProperty.fromValueMap(
valueMap.keySet().stream()
.collect(
toImmutableSortedMap(
@@ -393,7 +393,7 @@ public class EntityYamlUtils {
public TimedTransitionProperty<FeatureStatus> deserialize(
JsonParser jp, DeserializationContext context) throws IOException {
SortedMap<String, String> valueMap = jp.readValueAs(SortedMap.class);
return TimedTransitionProperty.fromValueMapInstant(
return TimedTransitionProperty.fromValueMap(
valueMap.keySet().stream()
.collect(
toImmutableSortedMap(

View File

@@ -115,7 +115,7 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
* <ul>
* <li>For deleted resources, this is in the past.
* <li>For pending-delete resources, this is in the near future.
* <li>For active resources, this is {@code END_OF_TIME}.
* <li>For active resources, this is {@code END_INSTANT}.
* </ul>
*
* <p>This scheme allows for setting pending deletes in the future and having them magically drop

View File

@@ -20,7 +20,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
@@ -39,7 +38,6 @@ import java.time.Instant;
import java.util.Comparator;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/** Utilities for working with {@link EppResource}. */
public final class EppResourceUtils {
@@ -65,18 +63,12 @@ public final class EppResourceUtils {
return String.format("%X-%s", repoId, roidSuffix);
}
/** Helper to call {@link EppResource#cloneProjectedAtTime} without warnings. */
@SuppressWarnings("unchecked")
private static <T extends EppResource> T cloneProjectedAtTime(T resource, DateTime now) {
return (T) resource.cloneProjectedAtTime(toInstant(now));
}
/**
* Returns a Function that transforms an EppResource to the given DateTime, suitable for use with
* Returns a Function that transforms an EppResource to the given Instant, suitable for use with
* Iterables.transform() over a collection of EppResources.
*/
public static <T extends EppResource> Function<T, T> transformAtTime(final DateTime now) {
return (T resource) -> cloneProjectedAtTime(resource, now);
public static <T extends EppResource> Function<T, T> transformAtTime(final Instant now) {
return (T resource) -> (T) resource.cloneProjectedAtTime(now);
}
public static boolean isActive(EppResource resource, Instant time) {
@@ -84,28 +76,10 @@ public final class EppResourceUtils {
&& time.isBefore(resource.getDeletionTime());
}
/**
* @deprecated Use {@link #isActive(EppResource, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static boolean isActive(EppResource resource, DateTime time) {
return isActive(resource, toInstant(time));
}
public static boolean isDeleted(EppResource resource, Instant time) {
return !isActive(resource, time);
}
/**
* @deprecated Use {@link #isDeleted(EppResource, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static boolean isDeleted(EppResource resource, DateTime time) {
return isDeleted(resource, toInstant(time));
}
/** Process an automatic transfer on a domain. */
public static void setAutomaticTransferSuccessProperties(
DomainBase.Builder<?, ?> builder, DomainTransferData transferData) {
@@ -173,16 +147,6 @@ public final class EppResourceUtils {
: null);
}
/**
* @deprecated Use {@link #loadAtPointInTime(EppResource, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <T extends EppResource> T loadAtPointInTime(
final T resource, final DateTime timestamp) {
return loadAtPointInTime(resource, toInstant(timestamp));
}
/**
* Returns the most recent revision of a given EppResource before or at the provided timestamp,
* falling back to using the resource as-is if there are no revisions.
@@ -207,21 +171,6 @@ public final class EppResourceUtils {
return resourceAtPointInTime;
}
/**
* Returns a set of {@link VKey} for domains that reference a specified host.
*
* @param key the referent key
* @param now the logical time of the check /** Returns the domains that are linked to this host
* at the given time.
* @deprecated Use {@link #getLinkedDomainKeys(VKey, Instant, Integer)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static ImmutableSet<VKey<Domain>> getLinkedDomainKeys(
VKey<Host> key, DateTime now, @Nullable Integer limit) {
return getLinkedDomainKeys(key, toInstant(now), limit);
}
/** Returns the domains that are linked to this host at the given time. */
public static ImmutableSet<VKey<Domain>> getLinkedDomainKeys(
VKey<Host> key, Instant now, @Nullable Integer limit) {
@@ -246,17 +195,6 @@ public final class EppResourceUtils {
});
}
/**
* Returns whether this host is linked to any domains at the given time.
*
* @deprecated Use {@link #isLinked(VKey, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static boolean isLinked(VKey<Host> key, DateTime now) {
return isLinked(key, toInstant(now));
}
/** Returns whether this resource is linked to any domains at the given time. */
public static boolean isLinked(VKey<Host> key, Instant now) {
return !getLinkedDomainKeys(key, now, 1).isEmpty();

View File

@@ -20,8 +20,6 @@ import static google.registry.config.RegistryConfig.getEppResourceCachingDuratio
import static google.registry.config.RegistryConfig.getEppResourceMaxCachedEntries;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.LoadingCache;
@@ -43,7 +41,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import org.joda.time.DateTime;
/**
* Util class for mapping a foreign key to a {@link VKey} or {@link EppResource}.
@@ -65,30 +62,7 @@ public final class ForeignKeyUtils {
Domain.class, "domainName",
Host.class, "hostName");
public record MostRecentResource(String repoId, Instant deletionTime) {
/**
* @deprecated Use {@link #deletionTime()}
*/
@Deprecated
public DateTime getDeletionTime() {
return toDateTime(deletionTime);
}
}
/**
* Loads an optional {@link VKey} to an {@link EppResource} from the database by foreign key.
*
* <p>Returns empty if no resource with this foreign key was ever created, or if the most recently
* created resource was deleted before time "now".
*
* @deprecated Use {@link #loadKey(Class, String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> Optional<VKey<E>> loadKey(
Class<E> clazz, String foreignKey, DateTime now) {
return loadKey(clazz, foreignKey, toInstant(now));
}
public record MostRecentResource(String repoId, Instant deletionTime) {}
/**
* Loads an optional {@link VKey} to an {@link EppResource} from the database by foreign key.
@@ -101,21 +75,6 @@ public final class ForeignKeyUtils {
return Optional.ofNullable(loadKeys(clazz, ImmutableList.of(foreignKey), now).get(foreignKey));
}
/**
* Loads an {@link EppResource} from the database by foreign key.
*
* <p>Returns null if no resource with this foreign key was ever created or if the most recently
* created resource was deleted before time "now".
*
* @deprecated Use {@link #loadResource(Class, String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> Optional<E> loadResource(
Class<E> clazz, String foreignKey, DateTime now) {
return loadResource(clazz, foreignKey, toInstant(now));
}
/**
* Loads an {@link EppResource} from the database by foreign key.
*
@@ -129,22 +88,6 @@ public final class ForeignKeyUtils {
loadResources(clazz, ImmutableList.of(foreignKey), now).get(foreignKey));
}
/**
* Load a map of {@link String} foreign keys to {@link VKey}s to {@link EppResource} that are
* active at or after the specified moment in time.
*
* <p>The returned map will omit any foreign keys for which the {@link EppResource} doesn't exist
* or has been soft-deleted.
*
* @deprecated Use {@link #loadKeys(Class, Collection, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> ImmutableMap<String, VKey<E>> loadKeys(
Class<E> clazz, Collection<String> foreignKeys, DateTime now) {
return loadKeys(clazz, foreignKeys, toInstant(now));
}
/**
* Load a map of {@link String} foreign keys to {@link VKey}s to {@link EppResource} that are
* active at or after the specified moment in time.
@@ -159,20 +102,6 @@ public final class ForeignKeyUtils {
.collect(toImmutableMap(Entry::getKey, e -> VKey.create(clazz, e.getValue().repoId())));
}
/**
* Load a map of {@link String} foreign keys to the {@link EppResource} that are active at or
* after the specified moment in time.
*
* <p>The returned map will omit any foreign keys for which the {@link EppResource} doesn't exist
* or has been soft-deleted.
*/
@SuppressWarnings({"unchecked", "InlineMeSuggester"})
@Deprecated
public static <E extends EppResource> ImmutableMap<String, E> loadResources(
Class<E> clazz, Collection<String> foreignKeys, DateTime now) {
return loadResources(clazz, foreignKeys, toInstant(now));
}
/**
* Load a map of {@link String} foreign keys to the {@link EppResource} that are active at or
* after the specified moment in time.
@@ -198,7 +127,7 @@ public final class ForeignKeyUtils {
* should monotonically increase as one cannot create a domain/host/contact with the same foreign
* key without soft deleting the existing resource first. However, in test, there's no such
* guarantee and one must make sure that no two resources with the same foreign key exist with the
* same max {@code deleteTime}, usually {@code END_OF_TIME}, lest this method throws an error due
* same max {@code deleteTime}, usually {@code END_INSTANT}, lest this method throws an error due
* to duplicate keys.
*/
public static <E extends EppResource>
@@ -322,25 +251,6 @@ public final class ForeignKeyUtils {
foreignKeyToRepoIdCache = createForeignKeyToRepoIdCache(effectiveExpiry);
}
/**
* Load a list of {@link VKey} to {@link EppResource} instances by class and foreign key strings
* that are active at or after the specified moment in time, using the cache if enabled.
*
* <p>The returned map will omit any keys for which the {@link EppResource} doesn't exist or has
* been soft-deleted.
*
* <p>Don't use the cached version of this method unless you really need it for performance
* reasons, and are OK with the trade-offs in loss of transactional consistency.
*
* @deprecated Use {@link #loadKeysByCacheIfEnabled(Class, Collection, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> ImmutableMap<String, VKey<E>> loadKeysByCacheIfEnabled(
Class<E> clazz, Collection<String> foreignKeys, DateTime now) {
return loadKeysByCacheIfEnabled(clazz, foreignKeys, toInstant(now));
}
/**
* Load a list of {@link VKey} to {@link EppResource} instances by class and foreign key strings
* that are active at or after the specified moment in time, using the cache if enabled.
@@ -367,18 +277,6 @@ public final class ForeignKeyUtils {
e -> VKey.create(clazz, e.getValue().get().repoId())));
}
/**
* Loads an optional {@link VKey} to an {@link EppResource} using the cache.
*
* @deprecated Use {@link #loadKeyByCache(Class, String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> Optional<VKey<E>> loadKeyByCache(
Class<E> clazz, String foreignKey, DateTime now) {
return loadKeyByCache(clazz, foreignKey, toInstant(now));
}
/** Loads an optional {@link VKey} to an {@link EppResource} using the cache. */
public static <E extends EppResource> Optional<VKey<E>> loadKeyByCache(
Class<E> clazz, String foreignKey, Instant now) {
@@ -461,33 +359,6 @@ public final class ForeignKeyUtils {
foreignKeyToResourceCache = createForeignKeyToResourceCache(effectiveExpiry);
}
/**
* Loads the last created version of an {@link EppResource} from the database by foreign key,
* using a cache, if caching is enabled in config settings.
*
* <p>Returns null if no resource with this foreign key was ever created, or if the most recently
* created resource was deleted before time "now".
*
* <p>Loading an {@link EppResource} by itself is not sufficient to know its current state since
* it may have various expirable conditions and status values that might implicitly change its
* state as time progresses even if it has not been updated in the database. Rather, the resource
* must be combined with a timestamp to view its current state. We use a global last updated
* timestamp to guarantee monotonically increasing write times, and forward our projected time to
* the greater of this timestamp or "now". This guarantees that we're not projecting into the
* past.
*
* <p>Do not call this cached version for anything that needs transactional consistency. It should
* only be used when it's OK if the data is potentially being out of date, e.g. RDAP.
*
* @deprecated Use {@link #loadResourceByCacheIfEnabled(Class, String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> Optional<E> loadResourceByCacheIfEnabled(
Class<E> clazz, String foreignKey, DateTime now) {
return loadResourceByCacheIfEnabled(clazz, foreignKey, toInstant(now));
}
/**
* Loads the last created version of an {@link EppResource} from the database by foreign key,
* using a cache, if caching is enabled in config settings.
@@ -513,22 +384,6 @@ public final class ForeignKeyUtils {
: loadResource(clazz, foreignKey, now);
}
/**
* Loads the last created version of an {@link EppResource} from the replica database by foreign
* key, using a cache.
*
* <p>This method ignores the config setting for caching, and is reserved for use cases that can
* tolerate slightly stale data.
*
* @deprecated Use {@link #loadResourceByCache(Class, String, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <E extends EppResource> Optional<E> loadResourceByCache(
Class<E> clazz, String foreignKey, DateTime now) {
return loadResourceByCache(clazz, foreignKey, toInstant(now));
}
/**
* Loads the last created version of an {@link EppResource} from the replica database by foreign
* key, using a cache.

View File

@@ -22,7 +22,6 @@ import static google.registry.model.tld.Tld.TldState.GENERAL_AVAILABILITY;
import static google.registry.model.tld.Tld.TldState.START_DATE_SUNRISE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -46,6 +45,7 @@ import google.registry.persistence.VKey;
import google.registry.tools.IamClient;
import google.registry.util.CidrAddressBlock;
import google.registry.util.RegistryEnvironment;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
@@ -55,8 +55,6 @@ import java.util.function.Function;
import java.util.regex.Pattern;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/**
* Class to help build and persist all the OT&amp;E entities in the database.
@@ -94,9 +92,9 @@ public final class OteAccountBuilder {
private static final Pattern REGISTRAR_PATTERN = Pattern.compile("^[a-z\\d]{3,14}$");
// Durations are short so that registrars can test with quick transfer (etc.) turnaround.
private static final Duration SHORT_ADD_GRACE_PERIOD = Duration.standardMinutes(60);
private static final Duration SHORT_REDEMPTION_GRACE_PERIOD = Duration.standardMinutes(10);
private static final Duration SHORT_PENDING_DELETE_LENGTH = Duration.standardMinutes(5);
private static final Duration SHORT_ADD_GRACE_PERIOD = Duration.ofMinutes(60);
private static final Duration SHORT_REDEMPTION_GRACE_PERIOD = Duration.ofMinutes(10);
private static final Duration SHORT_PENDING_DELETE_LENGTH = Duration.ofMinutes(5);
private static final String DEFAULT_PREMIUM_LIST = "default_sandbox_list";
@@ -234,8 +232,8 @@ public final class OteAccountBuilder {
}
/** Sets the client certificate to all the OT&amp;E Registrars. */
public OteAccountBuilder setCertificate(String asciiCert, DateTime now) {
return transformRegistrars(builder -> builder.setClientCertificate(asciiCert, toInstant(now)));
public OteAccountBuilder setCertificate(String asciiCert, Instant now) {
return transformRegistrars(builder -> builder.setClientCertificate(asciiCert, now));
}
/** Sets the IP allowlist to all the OT&amp;E Registrars. */

View File

@@ -16,7 +16,6 @@ package google.registry.model;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -33,7 +32,6 @@ import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus;
import java.time.Instant;
import org.joda.time.DateTime;
/** Static utility functions for domain transfers. */
public final class ResourceTransferUtils {
@@ -73,20 +71,6 @@ public final class ResourceTransferUtils {
domain.getDomainName(), actionResult, transferRequestTrid, processedDate);
}
/**
* Create a pending action notification response indicating the resolution of a transfer.
*
* @deprecated Use {@link #createPendingTransferNotificationResponse(Domain, Trid, boolean,
* Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static PendingActionNotificationResponse createPendingTransferNotificationResponse(
Domain domain, Trid transferRequestTrid, boolean actionResult, DateTime processedDate) {
return createPendingTransferNotificationResponse(
domain, transferRequestTrid, actionResult, toInstant(processedDate));
}
/** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */
public static void handlePendingTransferOnDelete(
Domain domain, Domain newDomain, Instant now, HistoryEntry historyEntry) {
@@ -109,18 +93,6 @@ public final class ResourceTransferUtils {
.build());
}
/**
* If there is a transfer out, delete the server-approve entities and enqueue a poll message.
*
* @deprecated Use {@link #handlePendingTransferOnDelete(Domain, Domain, Instant, HistoryEntry)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static void handlePendingTransferOnDelete(
Domain domain, Domain newDomain, DateTime now, HistoryEntry historyEntry) {
handlePendingTransferOnDelete(domain, newDomain, toInstant(now), historyEntry);
}
/**
* Turn a domain into a builder with its pending transfer resolved.
*
@@ -165,18 +137,6 @@ public final class ResourceTransferUtils {
.build();
}
/**
* Resolve a pending transfer by awarding it to the gaining client.
*
* @deprecated Use {@link #approvePendingTransfer(Domain, TransferStatus, Instant)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static Domain approvePendingTransfer(
Domain domain, TransferStatus transferStatus, DateTime now) {
return approvePendingTransfer(domain, transferStatus, toInstant(now));
}
/**
* Resolve a pending transfer by denying it.
*
@@ -193,16 +153,4 @@ public final class ResourceTransferUtils {
.setLastEppUpdateRegistrarId(lastEppUpdateRegistrarId)
.build();
}
/**
* Resolve a pending transfer by denying it.
*
* @deprecated Use {@link #denyPendingTransfer(Domain, TransferStatus, Instant, String)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static Domain denyPendingTransfer(
Domain domain, TransferStatus transferStatus, DateTime now, String lastEppUpdateRegistrarId) {
return denyPendingTransfer(domain, transferStatus, toInstant(now), lastEppUpdateRegistrarId);
}
}

View File

@@ -83,9 +83,9 @@ public class BillingRecurrence extends BillingBase {
*
* <p>Note that this is a recurrence of the event time, not the billing time. The billing time can
* be calculated by adding the relevant grace period length to this date. The reason for this
* requirement is that the event time recurs on a {@link org.joda.time.Period} schedule (same day
* of year, which can be 365 or 366 days later) which is what {@link TimeOfYear} can model,
* whereas the billing time is a fixed {@link org.joda.time.Duration} later.
* requirement is that the event time recurs on a year-based schedule (same day of year, which can
* be 365 or 366 days later) which is what {@link TimeOfYear} can model, whereas the billing time
* is a fixed {@link java.time.Duration} later.
*/
@Embedded
@AttributeOverrides(

View File

@@ -90,9 +90,9 @@ public class Cursor extends UpdateAutoTimestampEntity {
RECURRING_BILLING(false),
/**
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The DateTime
* stored is the last time that registrar changes were successfully synced to the sheet. If
* there were no changes since the last time the action run, the cursor is not updated.
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The Instant stored
* is the last time that registrar changes were successfully synced to the sheet. If there were
* no changes since the last time the action run, the cursor is not updated.
*/
SYNC_REGISTRAR_SHEET(false),

View File

@@ -20,7 +20,6 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.toInstant;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@@ -32,7 +31,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import google.registry.model.Buildable;
import google.registry.model.CacheUtils;
import google.registry.model.EntityYamlUtils.TimedTransitionPropertyFeatureStatusDeserializer;
@@ -49,7 +47,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
@Entity
public class FeatureFlag extends ImmutableObject implements Buildable {
@@ -182,10 +179,6 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
return status;
}
public FeatureStatus getStatus(DateTime time) {
return getStatus(toInstant(time));
}
public FeatureStatus getStatus(Instant time) {
return status.getValueAtTime(time);
}
@@ -194,24 +187,14 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
* Returns whether the flag is active now, or else the flag's default value if it doesn't exist.
*/
public static boolean isActiveNow(FeatureName featureName) {
tm().assertInTransaction();
return isActiveAt(featureName, tm().getTxTime());
}
/**
* Returns whether the flag is active at the given time, or else the flag's default value if it
* doesn't exist.
*/
public static boolean isActiveAt(FeatureName featureName, DateTime dateTime) {
return isActiveAt(featureName, toInstant(dateTime));
}
/**
* Returns whether the flag is active at the given time, or else the flag's default value if it
* doesn't exist.
*/
public static boolean isActiveAt(FeatureName featureName, Instant instant) {
tm().assertInTransaction();
return CACHE
.get(featureName)
.map(flag -> flag.getStatus(instant).equals(ACTIVE))
@@ -244,16 +227,8 @@ public class FeatureFlag extends ImmutableObject implements Buildable {
return this;
}
public Builder setStatusMap(ImmutableSortedMap<DateTime, FeatureStatus> statusMap) {
return setStatusMapInstant(
statusMap.entrySet().stream()
.collect(
ImmutableSortedMap.toImmutableSortedMap(
Ordering.natural(), e -> toInstant(e.getKey()), Map.Entry::getValue)));
}
public Builder setStatusMapInstant(ImmutableSortedMap<Instant, FeatureStatus> statusMap) {
getInstance().status = TimedTransitionProperty.fromValueMapInstant(statusMap);
public Builder setStatusMap(ImmutableSortedMap<Instant, FeatureStatus> statusMap) {
getInstance().status = TimedTransitionProperty.fromValueMap(statusMap);
return this;
}
}

View File

@@ -33,7 +33,7 @@ import jakarta.persistence.Embeddable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.OffsetDateTime;
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, UTC);
OffsetDateTime zdt = OffsetDateTime.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(), UTC).getYear(),
ZonedDateTime.ofInstant(normalizedRange.upperEndpoint(), UTC).getYear());
OffsetDateTime.ofInstant(normalizedRange.lowerEndpoint(), UTC).getYear(),
OffsetDateTime.ofInstant(normalizedRange.upperEndpoint(), UTC).getYear());
return ContiguousSet.create(yearRange, integers()).stream()
.map(this::toInstantWithYear)
.filter(normalizedRange)
@@ -112,13 +112,13 @@ public class TimeOfYear extends ImmutableObject implements UnsafeSerializable {
/** 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, UTC).getYear());
Instant withSameYear = toInstantWithYear(OffsetDateTime.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, UTC).getYear());
Instant withSameYear = toInstantWithYear(OffsetDateTime.ofInstant(end, UTC).getYear());
return isBeforeOrAt(withSameYear, end) ? withSameYear : minusYears(withSameYear, 1);
}

View File

@@ -20,8 +20,6 @@ import static com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.formatInstant;
import static google.registry.util.DateTimeUtils.latestOf;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.collect.ImmutableMultimap;
@@ -34,7 +32,6 @@ import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/**
* An entity property whose value transitions over time. Each value it takes on becomes active at a
@@ -70,6 +67,9 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
checkArgument(
backingMap.containsKey(START_INSTANT),
"Must provide transition entry for the start of time (Unix Epoch)");
checkArgument(
Ordering.natural().equals(backingMap.comparator()),
"Timed transition value map must have transition time keys in chronological order");
this.backingMap = ImmutableSortedMap.copyOfSorted(backingMap);
}
@@ -83,7 +83,7 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
* START_INSTANT}.
*/
public static <V extends Serializable> TimedTransitionProperty<V> withInitialValue(V value) {
return fromValueMapInstant(ImmutableSortedMap.of(START_INSTANT, value));
return fromValueMap(ImmutableSortedMap.of(START_INSTANT, value));
}
/**
@@ -91,53 +91,12 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
* in the given map.
*
* <p>The map must contain a value for {@code START_INSTANT}.
*
* @deprecated Use {@link #fromValueMapInstant(ImmutableSortedMap)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <V extends Serializable> TimedTransitionProperty<V> fromValueMap(
ImmutableSortedMap<DateTime, V> valueMap) {
return fromValueMapInstant(toInstantMap(valueMap));
}
/**
* Returns a {@link TimedTransitionProperty} that contains the transition values and times defined
* in the given map.
*
* <p>The map must contain a value for {@code START_INSTANT}.
*/
public static <V extends Serializable> TimedTransitionProperty<V> fromValueMapInstant(
ImmutableSortedMap<Instant, V> valueMap) {
return new TimedTransitionProperty<>(valueMap);
}
/**
* Returns a {@link TimedTransitionProperty} that contains the transition values and times defined
* in the given map.
*
* <p>The map must contain a value for {@code START_OF_TIME}. The map is also validated against a
* set of allowed transitions.
*
* @deprecated Use {@link #makeInstant(ImmutableSortedMap, ImmutableMultimap, String,
* Serializable, String)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <V extends Serializable> TimedTransitionProperty<V> make(
ImmutableSortedMap<DateTime, V> valueMap,
ImmutableMultimap<V, V> allowedTransitions,
String mapName,
V initialValue,
String initialValueErrorMessage) {
return makeInstant(
toInstantMap(valueMap),
allowedTransitions,
mapName,
initialValue,
initialValueErrorMessage);
}
/**
* Returns a {@link TimedTransitionProperty} that contains the transition values and times defined
* in the given map.
@@ -145,44 +104,27 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
* <p>The map must contain a value for {@code START_INSTANT}. The map is also validated against a
* set of allowed transitions.
*/
public static <V extends Serializable> TimedTransitionProperty<V> makeInstant(
public static <V extends Serializable> TimedTransitionProperty<V> make(
ImmutableSortedMap<Instant, V> valueMap,
ImmutableMultimap<V, V> allowedTransitions,
String mapName,
V initialValue,
String initialValueErrorMessage) {
validateTimedTransitionMapInstant(valueMap, allowedTransitions, mapName);
validateTimedTransitionMap(valueMap, allowedTransitions, mapName);
checkArgument(valueMap.firstEntry().getValue().equals(initialValue), initialValueErrorMessage);
return fromValueMapInstant(valueMap);
}
/**
* Validates a timed transition map.
*
* @deprecated Use {@link #validateTimedTransitionMapInstant(ImmutableSortedMap,
* ImmutableMultimap, String)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static <V extends Serializable> void validateTimedTransitionMap(
ImmutableSortedMap<DateTime, V> valueMap,
ImmutableMultimap<V, V> allowedTransitions,
String mapName) {
validateTimedTransitionMapInstant(toInstantMap(valueMap), allowedTransitions, mapName);
return fromValueMap(valueMap);
}
/** Validates a timed transition map. */
public static <V extends Serializable> void validateTimedTransitionMapInstant(
public static <V extends Serializable> void validateTimedTransitionMap(
ImmutableSortedMap<Instant, V> valueMap,
ImmutableMultimap<V, V> allowedTransitions,
String mapName) {
checkArgument(
Ordering.natural().equals(valueMap.comparator()),
"Timed transition value map must have transition time keys in chronological order");
checkArgument(!valueMap.isEmpty(), "%s map cannot be null or empty.", mapName);
checkArgument(
valueMap.firstKey().equals(START_INSTANT), "%s map must start at START_OF_TIME.", mapName);
valueMap.firstKey().equals(START_INSTANT), "%s map must start at START_INSTANT.", mapName);
V lastValue = null;
for (V value : valueMap.values()) {
@@ -199,17 +141,6 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
}
}
private static <V> ImmutableSortedMap<Instant, V> toInstantMap(
ImmutableSortedMap<DateTime, V> valueMap) {
checkArgument(
Ordering.natural().equals(valueMap.comparator()),
"Timed transition value map must have transition time keys in chronological order");
return valueMap.entrySet().stream()
.collect(
toImmutableSortedMap(
Ordering.natural(), e -> toInstant(e.getKey()), Map.Entry::getValue));
}
/** Checks whether the property is valid. */
public void checkValidity() {
checkState(
@@ -217,39 +148,16 @@ public class TimedTransitionProperty<V extends Serializable> implements UnsafeSe
"Timed transition values missing required entry for the start of time (Unix Epoch)");
}
/** Returns the value of the property that is active at the given time. */
public V getValueAtTime(DateTime time) {
return getValueAtTime(toInstant(time));
}
/** Returns the value of the property that is active at the given time. */
public V getValueAtTime(Instant time) {
return backingMap.floorEntry(latestOf(START_INSTANT, time)).getValue();
}
/** Returns the map of all the transitions that have been defined for this property. */
public ImmutableSortedMap<DateTime, V> toValueMap() {
return backingMap.entrySet().stream()
.collect(
toImmutableSortedMap(
Ordering.natural(), e -> toDateTime(e.getKey()), Map.Entry::getValue));
}
/** Returns the map of all the transitions that have been defined for this property. */
public ImmutableSortedMap<Instant, V> toValueMapInstant() {
public ImmutableSortedMap<Instant, V> toValueMap() {
return backingMap;
}
/**
* Returns the time of the next transition after the given time. Returns null if there is no
* subsequent transition.
*/
@Nullable
public DateTime getNextTransitionAfter(DateTime time) {
Instant nextTransition = getNextTransitionAfter(toInstant(time));
return nextTransition == null ? null : toDateTime(nextTransition);
}
/** Returns the time of the next transition. Returns null if there is no subsequent transition. */
@Nullable
public Instant getNextTransitionAfter(Instant time) {

View File

@@ -30,8 +30,8 @@ import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
@Entity
@WithVKey(Long.class)
@@ -47,7 +47,7 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
@Column(nullable = false)
@Expose
DateTime modificationTime;
Instant modificationTime;
/** The HTTP method (e.g. POST, PUT) used to make this modification. */
@Column(nullable = false)
@@ -76,7 +76,7 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
return revisionId;
}
public DateTime getModificationTime() {
public Instant getModificationTime() {
return modificationTime;
}
@@ -141,7 +141,7 @@ public class ConsoleUpdateHistory extends ImmutableObject implements Buildable {
return super.build();
}
public Builder setModificationTime(DateTime modificationTime) {
public Builder setModificationTime(Instant modificationTime) {
getInstance().modificationTime = modificationTime;
return this;
}

View File

@@ -14,7 +14,6 @@
package google.registry.model.console;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import google.registry.model.Buildable;
@@ -31,7 +30,6 @@ import jakarta.persistence.Id;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
import org.joda.time.DateTime;
/**
* Represents a password reset request of some type.
@@ -64,7 +62,7 @@ public class PasswordResetRequest extends ImmutableObject implements Buildable {
@Column(nullable = false)
String requester;
@Column DateTime fulfillmentTime;
@Column Instant fulfillmentTime;
@Column(nullable = false)
String destinationEmail;
@@ -84,20 +82,11 @@ public class PasswordResetRequest extends ImmutableObject implements Buildable {
return requestTime.getTimestamp();
}
/**
* @deprecated Use {@link #getRequestTime()}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public DateTime getRequestDateTime() {
return toDateTime(requestTime.getTimestamp());
}
public String getRequester() {
return requester;
}
public Optional<DateTime> getFulfillmentTime() {
public Optional<Instant> getFulfillmentTime() {
return Optional.ofNullable(fulfillmentTime);
}
@@ -153,7 +142,7 @@ public class PasswordResetRequest extends ImmutableObject implements Buildable {
return this;
}
public Builder setFulfillmentTime(DateTime fulfillmentTime) {
public Builder setFulfillmentTime(Instant fulfillmentTime) {
getInstance().fulfillmentTime = fulfillmentTime;
return this;
}

View File

@@ -17,10 +17,7 @@
xmlns = @XmlNs(prefix = "contact", namespaceURI = "urn:ietf:params:xml:ns:contact-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcInstantAdapter.class),
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
})
@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(UtcInstantAdapter.class)})
package google.registry.model.contact;
import google.registry.xml.UtcInstantAdapter;

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.EppResource;
import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName;
@@ -145,6 +144,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
// TODO(b/188044616): Determine why Eager loading doesn't work here.
Hibernate.initialize(dsData);
Hibernate.initialize(gracePeriods);
Hibernate.initialize(nsHosts);
}
@Override

View File

@@ -80,7 +80,6 @@ import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Transient;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
@@ -247,7 +246,7 @@ public class DomainBase extends EppResource {
*
* <p>When a domain is scheduled to not autorenew, this field is set to the current value of its
* {@link #registrationExpirationTime}, after which point the next invocation of a periodic
* cronjob will explicitly delete the domain. This field is a DateTime and not a boolean because
* cronjob will explicitly delete the domain. This field is an Instant and not a boolean because
* of edge cases that occur during the autorenew grace period. We need to be able to tell the
* difference domains that have reached their life and must be deleted now, and domains that
* happen to be in the autorenew grace period now but should be deleted in roughly a year.
@@ -359,13 +358,7 @@ public class DomainBase extends EppResource {
return nullToEmptyImmutableCopy(nsHosts);
}
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("unused")
private void setNsHosts(Set<VKey<Host>> nsHosts) {
this.nsHosts = forceEmptyToNull(nsHosts);
}
// Note: for the two methods below, how we wish to treat the Hibernate setters depends on the
// Note: for the three methods below, how we wish to treat the Hibernate setters depends on the
// current state of the object and what's passed in. The key principle is that we wish to maintain
// the link between parent and child objects, meaning that we should keep around whichever of the
// two sets (the parameter vs the class variable and clear/populate that as appropriate).
@@ -374,6 +367,20 @@ public class DomainBase extends EppResource {
// an exception "A collection with cascade=”all-delete-orphan” was no longer referenced by the
// owning entity instance". See https://stackoverflow.com/questions/5587482 for more details.
// Hibernate needs this in order to populate nsHosts but no one else should ever use it
@SuppressWarnings("unused")
private void setNsHosts(Set<VKey<Host>> nsHosts) {
if (this.nsHosts instanceof PersistentSet) {
Set<VKey<Host>> nonNullNsHosts = nullToEmpty(nsHosts);
this.nsHosts.retainAll(nonNullNsHosts);
this.nsHosts.addAll(nonNullNsHosts);
} else if (nsHosts instanceof PersistentSet) {
this.nsHosts = nsHosts;
} else {
this.nsHosts = forceEmptyToNull(nsHosts);
}
}
// Hibernate needs this in order to populate gracePeriods but no one else should ever use it
@SuppressWarnings("unused")
private void setInternalGracePeriods(Set<GracePeriod> gracePeriods) {
@@ -495,8 +502,7 @@ public class DomainBase extends EppResource {
GracePeriodStatus.TRANSFER,
domain.getRepoId(),
transferExpirationTime.plus(
Duration.ofMillis(
Tld.get(domain.getTld()).getTransferGracePeriodLength().getMillis())),
Tld.get(domain.getTld()).getTransferGracePeriodLength()),
transferData.getGainingRegistrarId(),
transferData.getServerApproveBillingEvent())));
} else {
@@ -533,8 +539,7 @@ public class DomainBase extends EppResource {
GracePeriod.createForRecurrence(
GracePeriodStatus.AUTO_RENEW,
domain.getRepoId(),
lastAutorenewTime.plusMillis(
Tld.get(domain.getTld()).getAutoRenewGracePeriodLength().getMillis()),
lastAutorenewTime.plus(Tld.get(domain.getTld()).getAutoRenewGracePeriodLength()),
domain.getCurrentSponsorRegistrarId(),
domain.getAutorenewBillingEvent()));
newLastEppUpdateTime = Optional.of(lastAutorenewTime);
@@ -645,6 +650,7 @@ public class DomainBase extends EppResource {
// cascadable operations and orphan removal.
newDomain.gracePeriods =
newDomain.gracePeriods == null ? ImmutableSet.of() : newDomain.gracePeriods;
newDomain.nsHosts = newDomain.nsHosts == null ? ImmutableSet.of() : newDomain.nsHosts;
newDomain.dsData =
newDomain.dsData == null
? ImmutableSet.of()
@@ -782,7 +788,7 @@ public class DomainBase extends EppResource {
/**
* Sets the autorenew end time, or clears it if empty is passed.
*
* <p>Note that {@link DateTimeUtils#END_OF_TIME} is used as a sentinel value in the database
* <p>Note that {@link DateTimeUtils#END_INSTANT} is used as a sentinel value in the database
* representation to signify that autorenew doesn't end, and is mapped to empty here for the
* purposes of more legible business logic.
*/

View File

@@ -46,10 +46,10 @@ import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlValue;
import java.time.Instant;
import java.time.LocalDate;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.time.LocalDate;
/** A collection of {@link Domain} commands. */
public class DomainCommand {

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.eppoutput.EppResponse.ResponseData;
import google.registry.xml.UtcInstantAdapter;
import jakarta.xml.bind.annotation.XmlElement;

View File

@@ -14,7 +14,6 @@
package google.registry.model.domain;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
import google.registry.model.billing.BillingEvent;

View File

@@ -23,6 +23,7 @@ import com.google.gson.annotations.Expose;
import google.registry.model.Buildable;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.UpdateAutoTimestampEntity;
import google.registry.persistence.converter.DurationUserType;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.AttributeOverride;
@@ -37,10 +38,11 @@ import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import javax.annotation.Nullable;
import org.joda.time.Duration;
import org.hibernate.annotations.Type;
/**
* Represents a registry lock/unlock object, meaning that the domain is locked on the registry
@@ -156,6 +158,8 @@ public final class RegistryLock extends UpdateAutoTimestampEntity implements Bui
/** The duration after which we will re-lock this domain after it is unlocked. */
@Column(columnDefinition = "interval")
@Type(DurationUserType.class)
@Expose
private Duration relockDuration;
public String getRepoId() {

View File

@@ -31,8 +31,8 @@ import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.Period;
import java.util.stream.Stream;
import org.joda.time.Period;
/** Base class for the fee and credit types. */
@XmlTransient

View File

@@ -34,4 +34,3 @@ public abstract class FeeCheckResponseExtensionItem extends FeeQueryResponseExte
}
}
}

View File

@@ -69,4 +69,3 @@ public class FeeInfoCommandExtensionV06
return Optional.empty();
}
}

View File

@@ -36,7 +36,6 @@ public class FeeInfoResponseExtensionV06
/** The command that was checked. */
FeeExtensionCommandDescriptor command;
/** Builder for {@link FeeInfoResponseExtensionV06}. */
public static class Builder
extends FeeQueryResponseExtensionItem.Builder<FeeInfoResponseExtensionV06, Builder> {

View File

@@ -34,7 +34,6 @@ public class FeeCheckResponseExtensionV11
@XmlElement(name = "cd")
ImmutableList<FeeCheckResponseExtensionItemV11> items;
@Override
public void setCurrencyIfSupported(CurrencyUnit currency) {}

View File

@@ -17,9 +17,7 @@
xmlns = @XmlNs(prefix = "launch", namespaceURI = "urn:ietf:params:xml:ns:launch-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
})
@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(UtcInstantAdapter.class)})
package google.registry.model.domain.launch;
import google.registry.xml.UtcInstantAdapter;

View File

@@ -18,9 +18,8 @@
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcInstantAdapter.class),
@XmlJavaTypeAdapter(UtcInstantAdapter.class),
@XmlJavaTypeAdapter(DateAdapter.class)
@XmlJavaTypeAdapter(value = UtcInstantAdapter.class, type = java.time.Instant.class),
@XmlJavaTypeAdapter(value = DateAdapter.class, type = java.time.LocalDate.class)
})
package google.registry.model.domain;

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