mirror of
https://github.com/google/nomulus
synced 2026-05-14 11:51:43 +00:00
Compare commits
10 Commits
proxy-2026
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56fe588b56 | ||
|
|
b33c2f4874 | ||
|
|
b8f14fef8d | ||
|
|
8047d1e3e3 | ||
|
|
5854ccf00d | ||
|
|
b69d51add1 | ||
|
|
60d3653b46 | ||
|
|
80eefc6498 | ||
|
|
74f9f5d478 | ||
|
|
81b3a2fc5b |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -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
|
||||
|
||||
67
GEMINI.md
67
GEMINI.md
@@ -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 `Instant` parameters or local variables as `final` unnecessarily, as it clutters the codebase.
|
||||
- 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`.
|
||||
@@ -77,6 +72,7 @@ Based on historical PR reviews, avoid the following common mistakes:
|
||||
- **Immutable Types:** Declare variables, fields, and return types explicitly as Guava immutable types (e.g., `ImmutableList<T>`, `ImmutableMap<K, V>`) instead of their generic interfaces (`List<T>`, `Map<K, V>`) to clearly communicate immutability contracts to callers. Use `toImmutableList()` and `toImmutableMap()` collectors in streams rather than manually accumulating into an `ArrayList` or `HashMap`.
|
||||
- **Constructors:** Do not perform heavy logic, I/O, or external API calls inside constructors. Initialization logic should be deferred or handled in a factory method or a dedicated startup routine.
|
||||
- **Exception Handling:** Do not catch generic `Exception` or `Throwable` if a more specific exception is expected. Never "log and re-throw" the same exception; either handle it entirely (and log), or throw it up the chain. For batch processes, catch exceptions at the individual item/chunk level so one failure doesn't abort the entire batch.
|
||||
- **Optional Assertions:** Prefer Truth's `.hasValue(...)` over `.isEqualTo(Optional.of(...))` for cleaner and more descriptive assertions on `Optional` types.
|
||||
- **Fail Fast:** Validate inputs and fail fast (using `Preconditions.checkArgument` or similar) at the highest level possible rather than passing invalid state (like `null`s) deeper into business logic.
|
||||
- **Magic Numbers:** Always document magic numbers or hardcoded limits (like `50.0` or `30`) with inline comments explaining the rationale.
|
||||
- **Null Safety and Optional:** Prefer using `Optional` for any variable that is expected to potentially be null. For any other variable that can be null but cannot use an `Optional` (e.g., function parameters or return types where `Optional` is not idiomatic), it MUST be annotated with `@Nullable`. Always use the `javax.annotation.Nullable` annotation.
|
||||
@@ -92,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.
|
||||
@@ -112,13 +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.
|
||||
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.
|
||||
|
||||
@@ -127,49 +120,35 @@ 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.
|
||||
|
||||
---
|
||||
|
||||
# GitHub and Pull Request Protocol
|
||||
## GitHub and Pull Request Protocol
|
||||
|
||||
This protocol defines the standard for interacting with GitHub repositories and processing Pull Request (PR) feedback.
|
||||
|
||||
## 1. Interaction via `gh` CLI
|
||||
### 1. Interaction via `gh` CLI
|
||||
- **Primary Tool:** ALWAYS use the `gh` CLI for all GitHub-related operations (listing PRs, viewing PR content, checking status, adding comments).
|
||||
- **Credential Safety:** Never expose tokens or credentials in shell commands.
|
||||
|
||||
## 2. Processing PR Feedback
|
||||
### 2. Processing PR Feedback
|
||||
- **Systematic Review:** When asked to address PR comments, first fetch all comments using `gh pr view <number> --json reviews,comments`.
|
||||
- **Minimal Scope Expansion:** Address comments surgically. If a fix requires changes beyond a few lines or expands the PR's original scope significantly, DO NOT implement it without explicit user approval. Instead, report the issue to the user.
|
||||
- **Verification:** After addressing feedback, run the full build (`./gradlew build`) and relevant tests to ensure no regressions were introduced.
|
||||
|
||||
## 3. PR Lifecycle Management
|
||||
### 3. PR Lifecycle Management
|
||||
- **One Commit Per PR:** Ensure all changes are squashed into a single, clean commit. Use `git commit --amend --no-edit` for follow-up fixes.
|
||||
- **Clean Workspace:** Always run `git status` and verify the repository state before declaring a task complete.
|
||||
- **Package Lock:** The Gradle build automatically modifies `console-webapp/package-lock.json` via the `npmInstallDeps` task. ALWAYS revert this file (`git checkout console-webapp/package-lock.json`) before staging changes or finalizing a commit unless you explicitly modified NPM dependencies.
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,39 +19,18 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
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.DateTimeZone;
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
/** Utilities methods and constants related to Joda {@link DateTime} objects. */
|
||||
public abstract class DateTimeUtils {
|
||||
|
||||
/** The start of the epoch, in a convenient constant. */
|
||||
@Deprecated public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC);
|
||||
|
||||
/** 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, DateTimeZone.UTC);
|
||||
|
||||
/**
|
||||
* An instant in the far future that we can treat as infinity.
|
||||
*
|
||||
@@ -66,19 +45,24 @@ 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 =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd't'HH-mm-ss'z'").withZone(ZoneOffset.UTC);
|
||||
|
||||
/** Formats an {@link Instant} to an ISO-8601 string. */
|
||||
public static String formatInstant(Instant instant) {
|
||||
return ISO_8601_FORMATTER.format(instant);
|
||||
String formatted = ISO_8601_FORMATTER.format(instant);
|
||||
return formatted.startsWith("+") ? formatted.substring(1) : formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,74 +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);
|
||||
}
|
||||
|
||||
/** 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);
|
||||
@@ -164,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);
|
||||
@@ -196,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);
|
||||
@@ -214,48 +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(), DateTimeZone.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(), DateTimeZone.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) {
|
||||
@@ -274,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
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.
|
||||
@@ -30,7 +30,7 @@ public interface Sleeper {
|
||||
*
|
||||
* @throws InterruptedException if this thread was interrupted
|
||||
*/
|
||||
void sleep(ReadableDuration duration) throws InterruptedException;
|
||||
void sleep(Duration duration) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Puts the current thread to sleep, ignoring interrupts.
|
||||
@@ -40,7 +40,7 @@ public interface Sleeper {
|
||||
*
|
||||
* @see com.google.common.util.concurrent.Uninterruptibles#sleepUninterruptibly
|
||||
*/
|
||||
void sleepUninterruptibly(ReadableDuration duration);
|
||||
void sleepUninterruptibly(Duration duration);
|
||||
|
||||
/**
|
||||
* Puts the current thread to interruptible sleep.
|
||||
@@ -48,7 +48,7 @@ public interface Sleeper {
|
||||
* <p>This is a convenience method for {@link #sleep} that properly converts an {@link
|
||||
* InterruptedException} to a {@link RuntimeException}.
|
||||
*/
|
||||
default void sleepInterruptibly(ReadableDuration duration) {
|
||||
default void sleepInterruptibly(Duration duration) {
|
||||
try {
|
||||
sleep(duration);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
@@ -14,13 +14,11 @@
|
||||
|
||||
package google.registry.util;
|
||||
|
||||
import static org.joda.time.DateTimeZone.UTC;
|
||||
import static java.time.temporal.ChronoUnit.MILLIS;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
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.
|
||||
return Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ 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(Duration.ofMillis(duration.getMillis()));
|
||||
public void sleepUninterruptibly(Duration duration) {
|
||||
checkArgument(!duration.isNegative(), "Duration must be non-negative");
|
||||
Uninterruptibles.sleepUninterruptibly(duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,24 +58,28 @@ 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());
|
||||
}
|
||||
|
||||
/** Sets the time to the specified instant. */
|
||||
public void setTo(ReadableInstant time) {
|
||||
currentTimeMillis.set(time.getMillis());
|
||||
public void advanceBy(Duration duration) {
|
||||
currentTimeMillis.addAndGet(duration.toMillis());
|
||||
}
|
||||
|
||||
/** Sets the time to the specified instant. */
|
||||
@@ -101,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. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,4 +409,3 @@ if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
except Abort as ex:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,8 +26,8 @@ import google.registry.model.EppResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.request.Action;
|
||||
import jakarta.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
/** Helper class to enqueue tasks for handling asynchronous operations in flows. */
|
||||
public final class AsyncTaskEnqueuer {
|
||||
@@ -41,7 +41,7 @@ public final class AsyncTaskEnqueuer {
|
||||
public static final String QUEUE_ASYNC_ACTIONS = "async-actions";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final Duration MAX_ASYNC_ETA = Duration.standardDays(30);
|
||||
private static final Duration MAX_ASYNC_ETA = Duration.ofDays(30);
|
||||
|
||||
private final CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@@ -58,12 +58,12 @@ public final class AsyncTaskEnqueuer {
|
||||
*/
|
||||
public void enqueueAsyncResave(
|
||||
VKey<? extends EppResource> entityKey,
|
||||
DateTime now,
|
||||
ImmutableSortedSet<DateTime> whenToResave) {
|
||||
DateTime firstResave = whenToResave.first();
|
||||
Instant now,
|
||||
ImmutableSortedSet<Instant> whenToResave) {
|
||||
Instant firstResave = whenToResave.first();
|
||||
checkArgument(isBeforeOrAt(now, firstResave), "Can't enqueue a resave to run in the past");
|
||||
Duration etaDuration = new Duration(now, firstResave);
|
||||
if (etaDuration.isLongerThan(MAX_ASYNC_ETA)) {
|
||||
Duration etaDuration = Duration.between(now, firstResave);
|
||||
if (etaDuration.compareTo(MAX_ASYNC_ETA) > 0) {
|
||||
logger.atInfo().log(
|
||||
"Ignoring async re-save of %s; %s is past the ETA threshold of %s.",
|
||||
entityKey, firstResave, MAX_ASYNC_ETA);
|
||||
|
||||
@@ -24,9 +24,9 @@ import static google.registry.request.RequestParameters.extractOptionalBooleanPa
|
||||
import static google.registry.request.RequestParameters.extractOptionalInstantParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
|
||||
import static google.registry.request.RequestParameters.extractOptionalParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredDatetimeParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredInstantParameter;
|
||||
import static google.registry.request.RequestParameters.extractRequiredParameter;
|
||||
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
|
||||
import static google.registry.request.RequestParameters.extractSetOfInstantParameters;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -44,7 +44,6 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Dagger module for injecting common settings for batch actions. */
|
||||
@Module
|
||||
@@ -98,14 +97,14 @@ public class BatchModule {
|
||||
|
||||
@Provides
|
||||
@Parameter(PARAM_REQUESTED_TIME)
|
||||
static DateTime provideRequestedTime(HttpServletRequest req) {
|
||||
return extractRequiredDatetimeParameter(req, PARAM_REQUESTED_TIME);
|
||||
static Instant provideRequestedTime(HttpServletRequest req) {
|
||||
return extractRequiredInstantParameter(req, PARAM_REQUESTED_TIME);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Parameter(PARAM_RESAVE_TIMES)
|
||||
static ImmutableSet<DateTime> provideResaveTimes(HttpServletRequest req) {
|
||||
return extractSetOfDatetimeParameters(req, PARAM_RESAVE_TIMES);
|
||||
static ImmutableSet<Instant> provideResaveTimes(HttpServletRequest req) {
|
||||
return extractSetOfInstantParameters(req, PARAM_RESAVE_TIMES);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -42,10 +42,10 @@ import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* An action that transfers a set of domains from one registrar to another.
|
||||
@@ -158,7 +158,7 @@ public class BulkDomainTransferAction implements Runnable {
|
||||
return null;
|
||||
};
|
||||
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
|
||||
// Send a 200-series status code to prevent this conflicting action from retrying.
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("Could not acquire lock; already running?");
|
||||
|
||||
@@ -52,11 +52,11 @@ import jakarta.inject.Inject;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Utilities for dealing with Cloud Tasks. */
|
||||
public class CloudTasksUtils implements Serializable {
|
||||
@@ -251,7 +251,7 @@ public class CloudTasksUtils implements Serializable {
|
||||
method,
|
||||
service,
|
||||
params,
|
||||
Duration.millis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
|
||||
Duration.ofMillis(random.nextInt((int) SECONDS.toMillis(jitterSeconds.get()))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,12 +302,12 @@ public class CloudTasksUtils implements Serializable {
|
||||
Action.Service service,
|
||||
Multimap<String, String> params,
|
||||
Duration delay) {
|
||||
if (delay.isEqual(Duration.ZERO)) {
|
||||
if (delay.isZero()) {
|
||||
return createTask(path, method, service, params);
|
||||
}
|
||||
checkArgument(delay.isLongerThan(Duration.ZERO), "Negative duration is not supported.");
|
||||
checkArgument(!delay.isNegative(), "Negative duration is not supported.");
|
||||
return Task.newBuilder(createTask(path, method, service, params))
|
||||
.setScheduleTime(Timestamps.fromMillis(clock.nowUtc().plus(delay).getMillis()))
|
||||
.setScheduleTime(Timestamps.fromMillis(clock.now().plus(delay).toEpochMilli()))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,11 @@ import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* An action that deletes all non-renewing domains whose expiration dates have now passed.
|
||||
@@ -116,7 +116,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
|
||||
return null;
|
||||
};
|
||||
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
|
||||
// Send a 200-series status code to prevent this conflicting action from retrying.
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("Could not acquire lock; already running?");
|
||||
|
||||
@@ -115,7 +115,7 @@ public class DeleteLoadTestDataAction implements Runnable {
|
||||
VKey<Host> hostVKey = host.createVKey();
|
||||
// We can remove hosts from linked domains, so we should do so then delete the hosts
|
||||
ImmutableSet<VKey<Domain>> linkedDomains =
|
||||
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.nowUtc(), null);
|
||||
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.now(), null);
|
||||
tm().loadByKeys(linkedDomains)
|
||||
.values()
|
||||
.forEach(
|
||||
|
||||
@@ -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<>();
|
||||
@@ -218,7 +216,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||
// successfully soft-delete the domain (thus leaving its DNS entry published). We soft-delete
|
||||
// it now so that the DNS entry can be handled. The domain will then be hard-deleted the next
|
||||
// time the job is run.
|
||||
if (EppResourceUtils.isActive(domain, tm().getTransactionTime())) {
|
||||
if (EppResourceUtils.isActive(domain, tm().getTxTime())) {
|
||||
if (isDryRun) {
|
||||
logger.atInfo().log(
|
||||
"Would soft-delete the active domain: %s (%s).",
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ExpandBillingRecurrencesAction implements Runnable {
|
||||
() ->
|
||||
tm().loadByKeyIfPresent(Cursor.createGlobalVKey(RECURRING_BILLING))
|
||||
.orElse(Cursor.createGlobal(RECURRING_BILLING, START_INSTANT))
|
||||
.getCursorTimeInstant()));
|
||||
.getCursorTime()));
|
||||
checkArgument(
|
||||
startTime.isBefore(endTime),
|
||||
"Start time (%s) must be before end time (%s)",
|
||||
|
||||
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
@@ -36,13 +37,12 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.tools.DomainLockUtils;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import google.registry.util.EmailMessage;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.mail.internet.AddressException;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Task that re-locks a previously-Registry-Locked domain after a predetermined period of time. */
|
||||
@Action(
|
||||
@@ -59,8 +59,8 @@ public class RelockDomainAction implements Runnable {
|
||||
|
||||
static final int ATTEMPTS_BEFORE_SLOWDOWN = 36; // every ten minutes for six hours then every hour
|
||||
static final int FAILURES_BEFORE_EMAIL = 2; // email after three failures, one half hour
|
||||
private static final Duration TEN_MINUTES = Duration.standardMinutes(10);
|
||||
private static final Duration ONE_HOUR = Duration.standardHours(1);
|
||||
private static final Duration TEN_MINUTES = Duration.ofMinutes(10);
|
||||
private static final Duration ONE_HOUR = Duration.ofHours(1);
|
||||
|
||||
private static final String RELOCK_SUCCESS_EMAIL_TEMPLATE =
|
||||
"""
|
||||
@@ -188,7 +188,7 @@ public class RelockDomainAction implements Runnable {
|
||||
"Domain %s has a pending delete.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
!DateTimeUtils.isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
|
||||
!isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
|
||||
"Domain %s has been deleted.",
|
||||
domainName);
|
||||
checkArgument(
|
||||
|
||||
@@ -30,8 +30,8 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* An action that re-saves a given entity, typically after a certain amount of time has passed.
|
||||
@@ -50,16 +50,16 @@ public class ResaveEntityAction implements Runnable {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final String resourceKey;
|
||||
private final DateTime requestedTime;
|
||||
private final ImmutableSortedSet<DateTime> resaveTimes;
|
||||
private final Instant requestedTime;
|
||||
private final ImmutableSortedSet<Instant> resaveTimes;
|
||||
private final AsyncTaskEnqueuer asyncTaskEnqueuer;
|
||||
private final Response response;
|
||||
|
||||
@Inject
|
||||
ResaveEntityAction(
|
||||
@Parameter(PARAM_RESOURCE_KEY) String resourceKey,
|
||||
@Parameter(PARAM_REQUESTED_TIME) DateTime requestedTime,
|
||||
@Parameter(PARAM_RESAVE_TIMES) ImmutableSet<DateTime> resaveTimes,
|
||||
@Parameter(PARAM_REQUESTED_TIME) Instant requestedTime,
|
||||
@Parameter(PARAM_RESAVE_TIMES) ImmutableSet<Instant> resaveTimes,
|
||||
AsyncTaskEnqueuer asyncTaskEnqueuer,
|
||||
Response response) {
|
||||
this.resourceKey = resourceKey;
|
||||
|
||||
@@ -16,9 +16,8 @@ package google.registry.batch;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.toDateTime;
|
||||
import static google.registry.util.DateTimeUtils.toInstant;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.apache.http.HttpStatus.SC_OK;
|
||||
|
||||
@@ -43,11 +42,10 @@ import google.registry.util.EmailMessage;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.mail.internet.AddressException;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
/** An action that sends notification emails to registrars whose certificates are expiring soon. */
|
||||
@Action(
|
||||
@@ -57,6 +55,7 @@ import org.joda.time.format.DateTimeFormatter;
|
||||
public class SendExpiringCertificateNotificationEmailAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/sendExpiringCertificateNotificationEmail";
|
||||
|
||||
/**
|
||||
* Used as an offset when storing the last notification email sent date.
|
||||
*
|
||||
@@ -65,10 +64,11 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
* next day at 2am, the date difference will be less than a day, which will lead to the date
|
||||
* difference between two successive email sent date being the expected email interval days + 1;
|
||||
*/
|
||||
protected static final Duration UPDATE_TIME_OFFSET = Duration.standardMinutes(10);
|
||||
protected static final Duration UPDATE_TIME_OFFSET = Duration.ofMinutes(10);
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter DATE_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(UTC);
|
||||
|
||||
private final CertificateChecker certificateChecker;
|
||||
private final String expirationWarningEmailBodyText;
|
||||
@@ -130,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 ->
|
||||
@@ -149,7 +149,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
@VisibleForTesting
|
||||
boolean sendNotificationEmail(
|
||||
Registrar registrar,
|
||||
DateTime lastExpiringCertNotificationSentDate,
|
||||
Instant lastExpiringCertNotificationSentDate,
|
||||
CertificateType certificateType,
|
||||
Optional<String> certificate) {
|
||||
if (certificate.isEmpty()
|
||||
@@ -160,8 +160,8 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
try {
|
||||
ImmutableSet<InternetAddress> recipients = getEmailAddresses(registrar, Type.TECH);
|
||||
ImmutableSet<InternetAddress> ccs = getEmailAddresses(registrar, Type.ADMIN);
|
||||
DateTime expirationDate =
|
||||
new DateTime(certificateChecker.getCertificate(certificate.get()).getNotAfter());
|
||||
Instant expirationDate =
|
||||
certificateChecker.getCertificate(certificate.get()).getNotAfter().toInstant();
|
||||
logger.atInfo().log(
|
||||
" %s SSL certificate of registrar '%s' will expire on %s.",
|
||||
certificateType.getDisplayName(), registrar.getRegistrarName(), expirationDate);
|
||||
@@ -190,9 +190,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
* for applicable certificate.
|
||||
*/
|
||||
updateLastNotificationSentDate(
|
||||
registrar,
|
||||
clock.nowUtc().minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
|
||||
certificateType);
|
||||
registrar, clock.now().minus(UPDATE_TIME_OFFSET), certificateType);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
@@ -205,29 +203,29 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
/** Updates the last notification sent date in database. */
|
||||
@VisibleForTesting
|
||||
void updateLastNotificationSentDate(
|
||||
Registrar registrar, DateTime now, CertificateType certificateType) {
|
||||
Registrar registrar, Instant now, CertificateType certificateType) {
|
||||
try {
|
||||
tm().transact(
|
||||
() -> {
|
||||
Registrar.Builder newRegistrar = tm().loadByEntity(registrar).asBuilder();
|
||||
switch (certificateType) {
|
||||
case PRIMARY -> {
|
||||
newRegistrar.setLastExpiringCertNotificationSentDate(toInstant(now));
|
||||
newRegistrar.setLastExpiringCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
"Updated last notification email sent date to %s for %s certificate of "
|
||||
+ "registrar %s.",
|
||||
DATE_FORMATTER.print(now),
|
||||
DATE_FORMATTER.format(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
}
|
||||
case FAILOVER -> {
|
||||
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(toInstant(now));
|
||||
newRegistrar.setLastExpiringFailoverCertNotificationSentDate(now);
|
||||
tm().put(newRegistrar.build());
|
||||
logger.atInfo().log(
|
||||
"Updated last notification email sent date to %s for %s certificate of "
|
||||
+ "registrar %s.",
|
||||
DATE_FORMATTER.print(now),
|
||||
DATE_FORMATTER.format(now),
|
||||
certificateType.getDisplayName(),
|
||||
registrar.getRegistrarName());
|
||||
}
|
||||
@@ -257,7 +255,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
if (registrarInfo.isCertExpiring()
|
||||
&& sendNotificationEmail(
|
||||
registrar,
|
||||
toDateTime(registrar.getLastExpiringCertNotificationSentDate()),
|
||||
registrar.getLastExpiringCertNotificationSentDate(),
|
||||
CertificateType.PRIMARY,
|
||||
registrar.getClientCertificate())) {
|
||||
numEmailsSent++;
|
||||
@@ -265,7 +263,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
if (registrarInfo.isFailOverCertExpiring()
|
||||
&& sendNotificationEmail(
|
||||
registrar,
|
||||
toDateTime(registrar.getLastExpiringFailoverCertNotificationSentDate()),
|
||||
registrar.getLastExpiringFailoverCertNotificationSentDate(),
|
||||
CertificateType.FAILOVER,
|
||||
registrar.getFailoverClientCertificate())) {
|
||||
numEmailsSent++;
|
||||
@@ -300,7 +298,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
@VisibleForTesting
|
||||
@SuppressWarnings("lgtm[java/dereferenced-value-may-be-null]")
|
||||
String getEmailBody(
|
||||
String registrarName, CertificateType type, DateTime expirationDate, String registrarId) {
|
||||
String registrarName, CertificateType type, Instant expirationDate, String registrarId) {
|
||||
checkArgumentNotNull(expirationDate, "Expiration date cannot be null");
|
||||
checkArgumentNotNull(type, "Certificate type cannot be null");
|
||||
checkArgumentNotNull(registrarId, "Registrar Id cannot be null");
|
||||
@@ -308,7 +306,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
|
||||
expirationWarningEmailBodyText,
|
||||
registrarName,
|
||||
type.getDisplayName(),
|
||||
DATE_FORMATTER.print(expirationDate),
|
||||
DATE_FORMATTER.format(expirationDate),
|
||||
registrarId);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
// 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.batch;
|
||||
|
||||
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_DOMAIN_SYNC;
|
||||
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_HOST_SYNC;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.util.DateTimeUtils.START_INSTANT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.cache.SimplifiedJedisClient;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.common.Cursor;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tlds;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
path = SyncRemoteCacheAction.PATH,
|
||||
method = POST,
|
||||
auth = Auth.AUTH_ADMIN)
|
||||
public class SyncRemoteCacheAction implements Runnable {
|
||||
|
||||
public static final String PATH = "/_dr/task/syncRemoteCache";
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private static final String LOCK_NAME = "syncRemoteCacheAction";
|
||||
private static final int BATCH_SIZE = 10000;
|
||||
|
||||
private final LockHandler lockHandler;
|
||||
private final Response response;
|
||||
private final Optional<SimplifiedJedisClient> jedisClient;
|
||||
|
||||
@Inject
|
||||
public SyncRemoteCacheAction(
|
||||
LockHandler lockHandler, Response response, Optional<SimplifiedJedisClient> jedisClient) {
|
||||
this.lockHandler = lockHandler;
|
||||
this.response = response;
|
||||
this.jedisClient = jedisClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
if (jedisClient.isEmpty()) {
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("No Jedis/Valkey configuration found");
|
||||
return;
|
||||
}
|
||||
Callable<Void> runner =
|
||||
() -> {
|
||||
try {
|
||||
runLocked();
|
||||
response.setStatus(SC_OK);
|
||||
} catch (Exception e) {
|
||||
logger.atSevere().withCause(e).log("Errored out during execution.");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setPayload(String.format("Errored out with cause: %s", e));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
|
||||
// Send a 200-series status code to prevent this conflicting action from retrying.
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("Could not acquire lock; already running?");
|
||||
}
|
||||
}
|
||||
|
||||
private void runLocked() {
|
||||
// Note: the transaction ordering means that cursors in our database are updated only if all the
|
||||
// operations for the entity type succeeded. There is no downside to processing the same objects
|
||||
// multiple times if, for some reason, saving the cursor to the DB fails.
|
||||
int syncedDomains = tm().transact(this::syncDomains);
|
||||
int syncedHosts = tm().transact(this::syncHosts);
|
||||
String message = String.format("Synced %d domains and %d hosts.", syncedDomains, syncedHosts);
|
||||
logger.atInfo().log(message);
|
||||
response.setPayload(message);
|
||||
}
|
||||
|
||||
private int syncDomains() {
|
||||
Instant domainCursorTime = getPreviousCursorTime(REMOTE_CACHE_DOMAIN_SYNC);
|
||||
ImmutableSet<String> realTlds = Tlds.getTldsOfType(Tld.TldType.REAL);
|
||||
List<Domain> domains =
|
||||
tm().query(
|
||||
"FROM Domain WHERE updateTimestamp.lastUpdateTime > :cursorTime AND tld IN"
|
||||
+ " :realTlds ORDER BY updateTimestamp ASC",
|
||||
Domain.class)
|
||||
.setParameter("cursorTime", domainCursorTime)
|
||||
.setParameter("realTlds", realTlds)
|
||||
.setMaxResults(BATCH_SIZE)
|
||||
.getResultList();
|
||||
if (domains.isEmpty()) {
|
||||
logger.atInfo().log("No domains to process");
|
||||
return 0;
|
||||
}
|
||||
logger.atInfo().log("Processing %d domains", domains.size());
|
||||
processResources(Domain.class, domains, Domain::getDomainName);
|
||||
setNewCursorTime(domains, REMOTE_CACHE_DOMAIN_SYNC);
|
||||
return domains.size();
|
||||
}
|
||||
|
||||
private int syncHosts() {
|
||||
Instant hostCursorTime = getPreviousCursorTime(REMOTE_CACHE_HOST_SYNC);
|
||||
List<Host> hosts =
|
||||
tm().query(
|
||||
"FROM Host WHERE updateTimestamp.lastUpdateTime > :cursorTime ORDER BY"
|
||||
+ " updateTimestamp ASC",
|
||||
Host.class)
|
||||
.setParameter("cursorTime", hostCursorTime)
|
||||
.setMaxResults(BATCH_SIZE)
|
||||
.getResultList();
|
||||
if (hosts.isEmpty()) {
|
||||
logger.atInfo().log("No hosts to process");
|
||||
return 0;
|
||||
}
|
||||
logger.atInfo().log("Processing %d hosts", hosts.size());
|
||||
processResources(Host.class, hosts, Host::getRepoId);
|
||||
setNewCursorTime(hosts, REMOTE_CACHE_HOST_SYNC);
|
||||
return hosts.size();
|
||||
}
|
||||
|
||||
private <T extends EppResource> void processResources(
|
||||
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<>();
|
||||
|
||||
for (T resource : resources) {
|
||||
String key = getKeyFunction.apply(resource);
|
||||
if (resource.getDeletionTime().isAfter(tm().getTxTime())) {
|
||||
toSaveBuilder.add(new SimplifiedJedisClient.JedisResource<>(key, resource));
|
||||
} else {
|
||||
toDeleteBuilder.add(key);
|
||||
}
|
||||
}
|
||||
ImmutableList<String> toDelete = toDeleteBuilder.build();
|
||||
ImmutableList<SimplifiedJedisClient.JedisResource<T>> toSave = toSaveBuilder.build();
|
||||
|
||||
jedisClient.get().deleteAll(clazz, toDelete);
|
||||
logger.atInfo().log("Invalidated %d from the remote cache", toDelete.size());
|
||||
jedisClient.get().setAll(toSave);
|
||||
logger.atInfo().log("Set %d in the remote cache", toSave.size());
|
||||
}
|
||||
|
||||
private Instant getPreviousCursorTime(Cursor.CursorType cursorType) {
|
||||
return tm().loadByKeyIfPresent(Cursor.createGlobalVKey(cursorType))
|
||||
.map(Cursor::getCursorTime)
|
||||
.orElse(START_INSTANT);
|
||||
}
|
||||
|
||||
private void setNewCursorTime(
|
||||
List<? extends EppResource> resources, Cursor.CursorType cursorType) {
|
||||
Instant lastUpdateTime = Iterables.getLast(resources).getUpdateTimestamp().getTimestamp();
|
||||
tm().put(Cursor.createGlobal(cursorType, lastUpdateTime));
|
||||
logger.atInfo().log("Set new %s cursor time to %s", cursorType, lastUpdateTime);
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
package google.registry.beam;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.util.DateTimeUtils.LOWERCASE_TIMESTAMP_FORMATTER;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -61,7 +62,7 @@ public class BeamUtils {
|
||||
// with a letter and ending with a letter or number. So we replace the "T" and "Z" in ISO 8601
|
||||
// with lowercase letters.
|
||||
String jobName =
|
||||
String.format("%s-%s", prefix, clock.nowUtc().toString("yyyy-MM-dd't'HH-mm-ss'z'"));
|
||||
String.format("%s-%s", prefix, LOWERCASE_TIMESTAMP_FORMATTER.format(clock.now()));
|
||||
checkArgument(
|
||||
Pattern.compile("^[a-z][-a-z0-9]*[a-z0-9]*").matcher(jobName).matches(),
|
||||
"The job name %s is illegal, it consists of only characters [-a-z0-9], "
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
package google.registry.beam.billing;
|
||||
|
||||
import static google.registry.util.DateTimeUtils.toLocalDate;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -22,8 +24,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.regex.Pattern;
|
||||
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.
|
||||
@@ -70,7 +70,7 @@ public record BillingEvent(
|
||||
String flags) {
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'UTC'").withZone(ZoneOffset.UTC);
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'UTC'").withZone(UTC);
|
||||
|
||||
private static final Pattern SYNTHETIC_REGEX = Pattern.compile("SYNTHETIC", Pattern.LITERAL);
|
||||
|
||||
@@ -164,14 +164,10 @@ public record BillingEvent(
|
||||
/** Returns the grouping key for this {@code BillingEvent}, to generate the overall invoice. */
|
||||
InvoiceGroupingKey getInvoiceGroupingKey() {
|
||||
return new InvoiceGroupingKey(
|
||||
ZonedDateTime.ofInstant(billingTime(), ZoneOffset.UTC)
|
||||
.toLocalDate()
|
||||
.withDayOfMonth(1)
|
||||
.toString(),
|
||||
toLocalDate(billingTime()).withDayOfMonth(1).toString(),
|
||||
years() == 0
|
||||
? ""
|
||||
: ZonedDateTime.ofInstant(billingTime(), ZoneOffset.UTC)
|
||||
.toLocalDate()
|
||||
: toLocalDate(billingTime())
|
||||
.withDayOfMonth(1)
|
||||
.plusYears(years())
|
||||
.minusDays(1)
|
||||
@@ -229,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);
|
||||
|
||||
@@ -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
|
||||
@@ -445,7 +445,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
|
||||
Cursor.createGlobalVKey(RECURRING_BILLING))
|
||||
.orElse(
|
||||
Cursor.createGlobal(RECURRING_BILLING, START_INSTANT))
|
||||
.getCursorTimeInstant();
|
||||
.getCursorTime();
|
||||
if (!currentCursorTime.equals(startTime)) {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,8 @@ import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.security.Security;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import org.apache.beam.sdk.options.PipelineOptions;
|
||||
import org.apache.beam.sdk.transforms.DoFn;
|
||||
@@ -66,8 +68,6 @@ import org.apache.beam.sdk.values.PCollection;
|
||||
import org.apache.beam.sdk.values.PDone;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
public class RdeIO {
|
||||
|
||||
@@ -163,7 +163,7 @@ public class RdeIO {
|
||||
// Determine some basic things about the deposit.
|
||||
final RdeMode mode = key.mode();
|
||||
final String tld = key.tld();
|
||||
final DateTime watermark = key.watermark();
|
||||
final Instant watermark = key.watermark();
|
||||
final int revision =
|
||||
Optional.ofNullable(key.revision())
|
||||
.orElseGet(() -> RdeRevision.getNextRevision(tld, watermark, mode));
|
||||
@@ -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)));
|
||||
@@ -259,7 +262,7 @@ public class RdeIO {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
private static final long serialVersionUID = 5822176227753327224L;
|
||||
private static final Duration ENQUEUE_DELAY = Duration.standardMinutes(1);
|
||||
private static final Duration ENQUEUE_DELAY = Duration.ofMinutes(1);
|
||||
|
||||
private final CloudTasksUtils cloudTasksUtils;
|
||||
|
||||
@@ -276,9 +279,9 @@ public class RdeIO {
|
||||
Tld tld = Tld.get(key.tld());
|
||||
Optional<Cursor> cursor =
|
||||
tm().loadByKeyIfPresent(Cursor.createScopedVKey(key.cursor(), tld));
|
||||
DateTime position = getCursorTimeOrStartOfTime(cursor);
|
||||
Instant position = getCursorTimeOrStartOfTime(cursor);
|
||||
checkState(key.interval() != null, "Interval must be present");
|
||||
DateTime newPosition = key.watermark().plus(key.interval());
|
||||
Instant newPosition = key.watermark().plus(key.interval());
|
||||
if (!position.isBefore(newPosition)) {
|
||||
logger.atWarning().log("Cursor has already been rolled forward.");
|
||||
return;
|
||||
|
||||
@@ -27,7 +27,6 @@ import static google.registry.beam.rde.RdePipeline.TupleTags.REVISION_ID;
|
||||
import static google.registry.beam.rde.RdePipeline.TupleTags.SUPERORDINATE_DOMAINS;
|
||||
import static google.registry.model.reporting.HistoryEntryDao.RESOURCE_TYPES_TO_HISTORY_TYPES;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.toInstant;
|
||||
import static google.registry.util.SafeSerializationUtils.safeDeserializeCollection;
|
||||
import static google.registry.util.SafeSerializationUtils.serializeCollection;
|
||||
import static google.registry.util.SerializeUtils.decodeBase64;
|
||||
@@ -72,6 +71,7 @@ import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import org.apache.beam.sdk.Pipeline;
|
||||
import org.apache.beam.sdk.PipelineResult;
|
||||
import org.apache.beam.sdk.coders.KvCoder;
|
||||
@@ -97,7 +97,6 @@ import org.apache.beam.sdk.values.PCollectionTuple;
|
||||
import org.apache.beam.sdk.values.TupleTag;
|
||||
import org.apache.beam.sdk.values.TupleTagList;
|
||||
import org.apache.beam.sdk.values.TypeDescriptor;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Definition of a Dataflow Flex template, which generates RDE/BRDA deposits.
|
||||
@@ -171,7 +170,7 @@ public class RdePipeline implements Serializable {
|
||||
private final transient RdePipelineOptions options;
|
||||
private final ValidationMode mode;
|
||||
private final ImmutableSet<PendingDeposit> pendingDeposits;
|
||||
private final DateTime watermark;
|
||||
private final Instant watermark;
|
||||
private final String rdeBucket;
|
||||
private final byte[] stagingKeyBytes;
|
||||
private final GcsUtils gcsUtils;
|
||||
@@ -190,7 +189,7 @@ public class RdePipeline implements Serializable {
|
||||
this.options = options;
|
||||
this.mode = ValidationMode.valueOf(options.getValidationMode());
|
||||
this.pendingDeposits = decodePendingDeposits(options.getPendings());
|
||||
ImmutableSet<DateTime> potentialWatermarks =
|
||||
ImmutableSet<Instant> potentialWatermarks =
|
||||
pendingDeposits.stream()
|
||||
.map(PendingDeposit::watermark)
|
||||
.distinct()
|
||||
@@ -324,7 +323,7 @@ public class RdePipeline implements Serializable {
|
||||
? "AND resource.tld IN " + "(SELECT id FROM Tld WHERE tldType = 'REAL')"
|
||||
: ""))
|
||||
.replace("%entity%", historyClass.getSimpleName()),
|
||||
ImmutableMap.of("watermark", toInstant(watermark)),
|
||||
ImmutableMap.of("watermark", watermark),
|
||||
Object[].class,
|
||||
row -> KV.of((String) row[0], (long) row[1]))
|
||||
.withCoder(KvCoder.of(StringUtf8Coder.of(), VarLongCoder.of())));
|
||||
@@ -365,7 +364,7 @@ public class RdePipeline implements Serializable {
|
||||
tm().loadByKey(
|
||||
VKey.create(historyEntryClazz, new HistoryEntryId(repoId, revisionId))))
|
||||
.getResourceAtPointInTime()
|
||||
.map(resource -> resource.cloneProjectedAtTime(toInstant(watermark)))
|
||||
.map(resource -> resource.cloneProjectedAtTime(watermark))
|
||||
.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -103,7 +102,7 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
|
||||
* transfers, grace periods).
|
||||
*
|
||||
* <p>The logic of what might have changed is paraphrased from {@link
|
||||
* DomainBase#cloneProjectedAtTime(DateTime)}.
|
||||
* DomainBase#cloneProjectedAtTime(Instant)}.
|
||||
*/
|
||||
private void fastResaveDomains(Pipeline pipeline) {
|
||||
Read<String, String> repoIdRead =
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.io.CharStreams;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import google.registry.util.Retrier;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -132,9 +131,13 @@ public class SafeBrowsingTransforms {
|
||||
if (!domainNameInfoBuffer.isEmpty()) {
|
||||
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
|
||||
results.forEach(
|
||||
(kv) ->
|
||||
context.output(
|
||||
kv, DateTimeUtils.toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
|
||||
kv -> {
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -64,19 +64,19 @@ import google.registry.util.SqlTemplate;
|
||||
import google.registry.util.SystemSleeper;
|
||||
import jakarta.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Class encapsulating parameters and state for accessing the Bigquery API. */
|
||||
public class BigqueryConnection implements AutoCloseable {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private static final Duration MIN_POLL_INTERVAL = Duration.millis(500);
|
||||
private static final Duration MIN_POLL_INTERVAL = Duration.ofMillis(500);
|
||||
|
||||
@NonFinalForTesting
|
||||
private static Sleeper sleeper = new SystemSleeper();
|
||||
@@ -88,7 +88,7 @@ public class BigqueryConnection implements AutoCloseable {
|
||||
private static final String TEMP_DATASET_NAME = "__temp__";
|
||||
|
||||
/** Default time to live for temporary tables. */
|
||||
private static final Duration TEMP_TABLE_TTL = Duration.standardHours(24);
|
||||
private static final Duration TEMP_TABLE_TTL = Duration.ofHours(24);
|
||||
|
||||
/** Bigquery client instance wrapped by this class. */
|
||||
private final Bigquery bigquery;
|
||||
@@ -109,7 +109,7 @@ public class BigqueryConnection implements AutoCloseable {
|
||||
private boolean overwrite = false;
|
||||
|
||||
/** Duration to wait between polls for job status. */
|
||||
private Duration pollInterval = Duration.millis(1000);
|
||||
private Duration pollInterval = Duration.ofSeconds(1);
|
||||
|
||||
BigqueryConnection(Bigquery bigquery, Clock clock) {
|
||||
this.bigquery = bigquery;
|
||||
@@ -146,9 +146,9 @@ public class BigqueryConnection implements AutoCloseable {
|
||||
|
||||
public Builder setPollInterval(Duration pollInterval) {
|
||||
checkArgument(
|
||||
!pollInterval.isShorterThan(MIN_POLL_INTERVAL),
|
||||
pollInterval.compareTo(MIN_POLL_INTERVAL) >= 0,
|
||||
"poll interval must be at least %s ms",
|
||||
MIN_POLL_INTERVAL.getMillis());
|
||||
MIN_POLL_INTERVAL.toMillis());
|
||||
instance.pollInterval = pollInterval;
|
||||
return this;
|
||||
}
|
||||
@@ -225,7 +225,7 @@ public class BigqueryConnection implements AutoCloseable {
|
||||
}
|
||||
|
||||
public Builder timeToLive(Duration duration) {
|
||||
this.table.setExpirationTime(clock.nowUtc().plus(duration).getMillis());
|
||||
this.table.setExpirationTime(clock.now().plus(duration).toEpochMilli());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,16 @@
|
||||
|
||||
package google.registry.bigquery;
|
||||
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
import static java.time.temporal.ChronoUnit.MICROS;
|
||||
|
||||
import com.google.api.services.bigquery.model.JobReference;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.SignStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.joda.time.format.DateTimeFormatterBuilder;
|
||||
import org.joda.time.format.DateTimeParser;
|
||||
import org.joda.time.format.ISODateTimeFormat;
|
||||
|
||||
/** Utilities related to Bigquery. */
|
||||
public class BigqueryUtils {
|
||||
@@ -67,47 +70,56 @@ public class BigqueryUtils {
|
||||
*
|
||||
* <p>The general format definition is "YYYY-MM-DD HH:MM:SS.SSS[ ZZ]", where the fractional
|
||||
* seconds portion can have 0-6 decimal places (although we restrict it to 0-3 here since Joda
|
||||
* DateTime only supports up to millisecond precision) and the zone if not specified defaults to
|
||||
* Instant only supports up to millisecond precision) and the zone if not specified defaults to
|
||||
* UTC.
|
||||
*
|
||||
* <p>Although we expect a zone specification of "UTC" when parsing, we don't emit it when
|
||||
* printing because in some cases BigQuery does not allow any time zone specification (instead it
|
||||
* assumes UTC for whatever input you provide) for input timestamp strings (see b/16380363).
|
||||
*
|
||||
* @see <a href="https://cloud.google.com/bigquery/data-types#timestamp-type">
|
||||
* BigQuery Data Types - TIMESTAMP</a>
|
||||
* @see <a href="https://cloud.google.com/bigquery/data-types#timestamp-type">BigQuery Data Types
|
||||
* - TIMESTAMP</a>
|
||||
*/
|
||||
public static final DateTimeFormatter BIGQUERY_TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
|
||||
.append(ISODateTimeFormat.date())
|
||||
.appendLiteral(' ')
|
||||
.append(
|
||||
// For printing, always print out the milliseconds.
|
||||
ISODateTimeFormat.hourMinuteSecondMillis().getPrinter(),
|
||||
// For parsing, we need a series of parsers to correctly handle the milliseconds.
|
||||
new DateTimeParser[] {
|
||||
// Try to parse the time with milliseconds first, which requires at least one
|
||||
// fractional second digit, and if that fails try to parse without milliseconds.
|
||||
ISODateTimeFormat.hourMinuteSecondMillis().getParser(),
|
||||
ISODateTimeFormat.hourMinuteSecond().getParser()})
|
||||
// Print UTC as the empty string since BigQuery's TIMESTAMP() function does not accept any
|
||||
// time zone specification, but require "UTC" on parsing. Since we force this formatter to
|
||||
// always use UTC below, the other arguments do not matter. If b/16380363 ever gets resolved
|
||||
// this could be simplified to appendLiteral(" UTC").
|
||||
.appendTimeZoneOffset("", " UTC", false, 1, 1)
|
||||
.toFormatter()
|
||||
.withZoneUTC();
|
||||
private static final DateTimeFormatter BIGQUERY_TIMESTAMP_PARSER =
|
||||
new DateTimeFormatterBuilder()
|
||||
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
|
||||
.appendLiteral('-')
|
||||
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
|
||||
.appendLiteral('-')
|
||||
.appendValue(ChronoField.DAY_OF_MONTH, 2)
|
||||
.appendLiteral(' ')
|
||||
.appendPattern("HH:mm:ss")
|
||||
.optionalStart()
|
||||
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
|
||||
.optionalEnd()
|
||||
.appendLiteral(" UTC")
|
||||
.toFormatter()
|
||||
.withZone(UTC);
|
||||
|
||||
private static final DateTimeFormatter BIGQUERY_TIMESTAMP_PRINTER =
|
||||
new DateTimeFormatterBuilder()
|
||||
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
|
||||
.appendLiteral('-')
|
||||
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
|
||||
.appendLiteral('-')
|
||||
.appendValue(ChronoField.DAY_OF_MONTH, 2)
|
||||
.appendLiteral(' ')
|
||||
.appendPattern("HH:mm:ss")
|
||||
.appendFraction(ChronoField.MILLI_OF_SECOND, 3, 3, true)
|
||||
.toFormatter()
|
||||
.withZone(UTC);
|
||||
|
||||
/**
|
||||
* Returns the human-readable string version of the given DateTime, suitable for conversion
|
||||
* within BigQuery from a string literal into a BigQuery timestamp type.
|
||||
* Returns the human-readable string version of the given Instant, suitable for conversion within
|
||||
* BigQuery from a string literal into a BigQuery timestamp type.
|
||||
*/
|
||||
public static String toBigqueryTimestampString(DateTime dateTime) {
|
||||
return BIGQUERY_TIMESTAMP_FORMAT.print(dateTime);
|
||||
public static String toBigqueryTimestampString(Instant dateTime) {
|
||||
return BIGQUERY_TIMESTAMP_PRINTER.format(dateTime);
|
||||
}
|
||||
|
||||
/** Returns the DateTime for a given human-readable string-formatted BigQuery timestamp. */
|
||||
public static DateTime fromBigqueryTimestampString(String timestampString) {
|
||||
return BIGQUERY_TIMESTAMP_FORMAT.parseDateTime(timestampString);
|
||||
/** Returns the Instant for a given human-readable string-formatted BigQuery timestamp. */
|
||||
public static Instant fromBigqueryTimestampString(String timestampString) {
|
||||
return BIGQUERY_TIMESTAMP_PARSER.parse(timestampString, Instant::from);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,15 +135,16 @@ public class BigqueryUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link DateTime} into a numeric string that BigQuery understands as a timestamp:
|
||||
* the decimal number of seconds since the epoch, precise up to microseconds.
|
||||
* Converts a time into a numeric string that BigQuery understands as a timestamp: the decimal
|
||||
* number of seconds since the epoch, precise up to microseconds.
|
||||
*
|
||||
* <p>Note that since {@code DateTime} only stores milliseconds, the last 3 digits will be zero.
|
||||
* <p>Note that while {@code Instant} supports nanosecond precision, BigQuery only supports
|
||||
* microsecond precision, so the sub-microsecond precision is truncated.
|
||||
*
|
||||
* @see <a href="https://developers.google.com/bigquery/timestamp">Data Types</a>
|
||||
*/
|
||||
public static String toBigqueryTimestamp(DateTime dateTime) {
|
||||
return toBigqueryTimestamp(dateTime.getMillis(), TimeUnit.MILLISECONDS);
|
||||
public static String toBigqueryTimestamp(Instant dateTime) {
|
||||
return toBigqueryTimestamp(MICROS.between(Instant.EPOCH, dateTime), TimeUnit.MICROSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,7 +116,7 @@ public class BsaDownloadAction implements Runnable {
|
||||
|
||||
Void runWithinLock() {
|
||||
// Cannot enroll new TLDs after download starts. This may change if b/309175410 is fixed.
|
||||
if (!Tlds.hasActiveBsaEnrollment(clock.nowUtc())) {
|
||||
if (!Tlds.hasActiveBsaEnrollment(clock.now())) {
|
||||
logger.atInfo().log("No TLDs enrolled with BSA. Quitting.");
|
||||
return null;
|
||||
}
|
||||
@@ -179,9 +179,7 @@ public class BsaDownloadAction implements Runnable {
|
||||
gcsClient.writeUnblockableDomains(
|
||||
schedule.jobName(),
|
||||
batches
|
||||
.map(
|
||||
batch ->
|
||||
applyLabelDiff(batch, lazyIdnChecker.get(), schedule, clock.nowUtc()))
|
||||
.map(batch -> applyLabelDiff(batch, lazyIdnChecker.get(), schedule, clock.now()))
|
||||
.flatMap(ImmutableList::stream));
|
||||
}
|
||||
schedule.updateJobStage(DownloadStage.REPORT_START_OF_ORDER_PROCESSING);
|
||||
|
||||
@@ -17,8 +17,8 @@ package google.registry.bsa;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Helper for guarding all BSA related work with a common lock. */
|
||||
public class BsaLock {
|
||||
|
||||
@@ -67,7 +67,7 @@ public class BsaRefreshAction implements Runnable {
|
||||
GcsClient gcsClient,
|
||||
BsaReportSender bsaReportSender,
|
||||
@Config("bsaTxnBatchSize") int transactionBatchSize,
|
||||
@Config("domainCreateTxnCommitTimeLag") org.joda.time.Duration domainCreateTxnCommitTimeLag,
|
||||
@Config("domainCreateTxnCommitTimeLag") Duration domainCreateTxnCommitTimeLag,
|
||||
BsaEmailSender emailSender,
|
||||
BsaLock bsaLock,
|
||||
Clock clock,
|
||||
@@ -76,7 +76,7 @@ public class BsaRefreshAction implements Runnable {
|
||||
this.gcsClient = gcsClient;
|
||||
this.bsaReportSender = bsaReportSender;
|
||||
this.transactionBatchSize = transactionBatchSize;
|
||||
this.domainCreateTxnCommitTimeLag = Duration.ofMillis(domainCreateTxnCommitTimeLag.getMillis());
|
||||
this.domainCreateTxnCommitTimeLag = domainCreateTxnCommitTimeLag;
|
||||
this.emailSender = emailSender;
|
||||
this.bsaLock = bsaLock;
|
||||
this.clock = clock;
|
||||
|
||||
@@ -88,14 +88,14 @@ public class BsaValidateAction implements Runnable {
|
||||
IdnChecker idnChecker,
|
||||
BsaEmailSender emailSender,
|
||||
@Config("bsaTxnBatchSize") int transactionBatchSize,
|
||||
@Config("bsaValidationMaxStaleness") org.joda.time.Duration maxStaleness,
|
||||
@Config("bsaValidationMaxStaleness") Duration maxStaleness,
|
||||
Clock clock,
|
||||
Response response) {
|
||||
this.gcsClient = gcsClient;
|
||||
this.idnChecker = idnChecker;
|
||||
this.emailSender = emailSender;
|
||||
this.transactionBatchSize = transactionBatchSize;
|
||||
this.maxStaleness = Duration.ofMillis(maxStaleness.getMillis());
|
||||
this.maxStaleness = maxStaleness;
|
||||
this.clock = clock;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import google.registry.tldconfig.idn.IdnLabelValidator;
|
||||
import google.registry.tldconfig.idn.IdnTableEnum;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Checks labels' validity wrt Idns in TLDs enrolled with BSA.
|
||||
@@ -45,7 +45,7 @@ public class IdnChecker {
|
||||
|
||||
@Inject
|
||||
IdnChecker(Clock clock) {
|
||||
this.idnToTlds = getIdnToTldMap(clock.nowUtc());
|
||||
this.idnToTlds = getIdnToTldMap(clock.now());
|
||||
allTlds = idnToTlds.values().stream().flatMap(ImmutableSet::stream).collect(toImmutableSet());
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class IdnChecker {
|
||||
return Sets.difference(allTlds, getSupportingTlds(idnTables)).immutableCopy();
|
||||
}
|
||||
|
||||
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(DateTime now) {
|
||||
private static ImmutableMap<IdnTableEnum, ImmutableSet<Tld>> getIdnToTldMap(Instant now) {
|
||||
var idnToTldMap = new ImmutableMultimap.Builder<IdnTableEnum, Tld>();
|
||||
Tlds.getTldEntitiesOfType(TldType.REAL).stream()
|
||||
.filter(tld -> isEnrolledWithBsa(tld, now))
|
||||
|
||||
@@ -20,7 +20,6 @@ import static google.registry.bsa.BsaStringUtils.DOMAIN_JOINER;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.isReserved;
|
||||
import static google.registry.model.tld.Tlds.findTldForName;
|
||||
import static google.registry.model.tld.label.ReservedList.loadReservedLists;
|
||||
import static google.registry.util.DateTimeUtils.toInstant;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
@@ -35,7 +34,6 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Utility for looking up reserved domain names.
|
||||
@@ -47,15 +45,6 @@ public final class ReservedDomainsUtils {
|
||||
|
||||
private ReservedDomainsUtils() {}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getAllReservedNames(Instant)}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("InlineMeSuggester")
|
||||
public static Stream<String> getAllReservedNames(DateTime now) {
|
||||
return getAllReservedNames(toInstant(now));
|
||||
}
|
||||
|
||||
public static Stream<String> getAllReservedNames(Instant now) {
|
||||
return Tlds.getTldEntitiesOfType(TldType.REAL).stream()
|
||||
.filter(tld -> Tld.isEnrolledWithBsa(tld, now))
|
||||
@@ -74,15 +63,6 @@ public final class ReservedDomainsUtils {
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getAllReservedDomainsInTld(Tld, Instant)}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("InlineMeSuggester")
|
||||
static ImmutableSet<String> getAllReservedDomainsInTld(Tld tld, DateTime now) {
|
||||
return getAllReservedDomainsInTld(tld, toInstant(now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code domain} is a reserved name that can be registered right now (e.g.,
|
||||
* during sunrise or with allocation token), therefore unblockable.
|
||||
@@ -95,13 +75,4 @@ public final class ReservedDomainsUtils {
|
||||
InternetDomainName.from(domain),
|
||||
Objects.equals(tld.getTldState(now), TldState.START_DATE_SUNRISE));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #isReservedDomain(String, Instant)}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("InlineMeSuggester")
|
||||
public static boolean isReservedDomain(String domain, DateTime now) {
|
||||
return isReservedDomain(domain, toInstant(now));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@ import jakarta.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import org.joda.time.Duration;
|
||||
import org.joda.time.Instant;
|
||||
|
||||
/**
|
||||
* A credential for accessing the BSA API.
|
||||
@@ -104,7 +104,7 @@ public class BsaCredential {
|
||||
}
|
||||
|
||||
private void ensureAuthTokenValid() throws IOException, GeneralSecurityException {
|
||||
Instant now = Instant.ofEpochMilli(clock.nowUtc().getMillis());
|
||||
Instant now = clock.now();
|
||||
if (authToken != null && lastRefreshTime.plus(authTokenExpiry).isAfter(now)) {
|
||||
logger.atInfo().log("AuthToken still valid, reusing.");
|
||||
return;
|
||||
|
||||
@@ -20,7 +20,6 @@ import static google.registry.bsa.DownloadStage.DONE;
|
||||
import static google.registry.bsa.DownloadStage.NOP;
|
||||
import static google.registry.bsa.persistence.RefreshScheduler.fetchMostRecentRefresh;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static org.joda.time.Duration.standardSeconds;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -28,9 +27,9 @@ import google.registry.bsa.persistence.DownloadSchedule.CompletedJob;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Assigns work for each cron invocation of the BSA Download job.
|
||||
@@ -57,7 +56,7 @@ import org.joda.time.Duration;
|
||||
public final class DownloadScheduler {
|
||||
|
||||
/** Allows a new download to proceed if the cron job fires a little early due to NTP drift. */
|
||||
private static final Duration CRON_JITTER = standardSeconds(5);
|
||||
private static final Duration CRON_JITTER = Duration.ofSeconds(5);
|
||||
|
||||
private final Duration downloadInterval;
|
||||
private final Duration maxNopInterval;
|
||||
@@ -115,11 +114,7 @@ public final class DownloadScheduler {
|
||||
}
|
||||
|
||||
private boolean isTimeAgain(BsaDownload mostRecent, Duration interval) {
|
||||
return mostRecent
|
||||
.getCreationTime()
|
||||
.plusMillis(interval.getMillis())
|
||||
.minusMillis(CRON_JITTER.getMillis())
|
||||
.isBefore(clock.now());
|
||||
return mostRecent.getCreationTime().plus(interval).minus(CRON_JITTER).isBefore(clock.now());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,9 +37,9 @@ import google.registry.bsa.api.UnblockableDomain.Reason;
|
||||
import google.registry.model.ForeignKeyUtils;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.tld.Tld;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Applies the BSA label diffs from the latest BSA download. */
|
||||
public final class LabelDiffUpdates {
|
||||
@@ -60,7 +60,7 @@ public final class LabelDiffUpdates {
|
||||
ImmutableList<BlockLabel> labels,
|
||||
IdnChecker idnChecker,
|
||||
DownloadSchedule schedule,
|
||||
DateTime now) {
|
||||
Instant now) {
|
||||
ImmutableList.Builder<UnblockableDomain> nonBlockedDomains = new ImmutableList.Builder<>();
|
||||
ImmutableMap<LabelType, ImmutableList<BlockLabel>> labelsByType =
|
||||
ImmutableMap.copyOf(
|
||||
@@ -134,7 +134,7 @@ public final class LabelDiffUpdates {
|
||||
}
|
||||
|
||||
static ImmutableList<UnblockableDomain> tallyUnblockableDomainsForNewLabels(
|
||||
ImmutableList<BlockLabel> labels, IdnChecker idnChecker, DateTime now) {
|
||||
ImmutableList<BlockLabel> labels, IdnChecker idnChecker, Instant now) {
|
||||
ImmutableList.Builder<UnblockableDomain> nonBlockedDomains = new ImmutableList.Builder<>();
|
||||
|
||||
for (BlockLabel label : labels) {
|
||||
|
||||
51
core/src/main/java/google/registry/cache/CacheMetrics.java
vendored
Normal file
51
core/src/main/java/google/registry/cache/CacheMetrics.java
vendored
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -85,25 +85,30 @@ public final class CacheModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public static DomainCache provideDomainCache(Optional<UnifiedJedis> jedis, Clock clock) {
|
||||
if (jedis.isEmpty()) {
|
||||
return domainName ->
|
||||
ForeignKeyUtils.loadResourceByCache(Domain.class, domainName, clock.now());
|
||||
}
|
||||
SimplifiedJedisClient<Domain> jedisClient =
|
||||
SimplifiedJedisClient.create(Domain.class, jedis.get());
|
||||
return new MultilayerDomainCache(jedisClient, clock);
|
||||
public static Optional<SimplifiedJedisClient> provideJedisClient(Optional<UnifiedJedis> jedis) {
|
||||
return jedis.map(SimplifiedJedisClient::new);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public static HostCache provideHostCache(Optional<UnifiedJedis> jedis) {
|
||||
if (jedis.isEmpty()) {
|
||||
public static DomainCache provideDomainCache(
|
||||
Optional<SimplifiedJedisClient> jedisClient, Clock clock, CacheMetrics cacheMetrics) {
|
||||
if (jedisClient.isEmpty()) {
|
||||
return domainName ->
|
||||
ForeignKeyUtils.loadResourceByCache(Domain.class, domainName, clock.now());
|
||||
}
|
||||
return new MultilayerDomainCache(jedisClient.get(), clock, cacheMetrics);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public static HostCache provideHostCache(
|
||||
Optional<SimplifiedJedisClient> jedisClient, CacheMetrics cacheMetrics) {
|
||||
if (jedisClient.isEmpty()) {
|
||||
return repoId ->
|
||||
Optional.ofNullable(EppResource.loadByCache(VKey.create(Host.class, repoId)));
|
||||
}
|
||||
SimplifiedJedisClient<Host> jedisClient = SimplifiedJedisClient.create(Host.class, jedis.get());
|
||||
return new MultilayerHostCache(jedisClient);
|
||||
return new MultilayerHostCache(jedisClient.get(), cacheMetrics);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +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;
|
||||
@@ -38,54 +43,61 @@ 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)) {
|
||||
AbstractPipeline pipeline = jedis.pipelined();
|
||||
batch.forEach(
|
||||
resource ->
|
||||
pipeline.set(
|
||||
resource.key.getBytes(StandardCharsets.UTF_8),
|
||||
serialize(resource.value),
|
||||
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli())));
|
||||
pipeline.sync();
|
||||
try (AbstractPipeline pipeline = jedis.pipelined()) {
|
||||
batch.forEach(
|
||||
resource ->
|
||||
pipeline.set(
|
||||
convertKey(resource.value.getClass(), resource.key),
|
||||
serialize(resource.value),
|
||||
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli())));
|
||||
pipeline.sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,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);
|
||||
@@ -121,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
@@ -271,7 +271,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("brdaDayOfWeek")
|
||||
public static int provideBrdaDayOfWeek() {
|
||||
return DateTimeConstants.TUESDAY;
|
||||
return DayOfWeek.TUESDAY.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,7 +282,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("brdaInterval")
|
||||
public static Duration provideBrdaInterval() {
|
||||
return Duration.standardDays(7);
|
||||
return Duration.ofDays(7);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -316,7 +316,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("publishDnsUpdatesLockDuration")
|
||||
public static Duration providePublishDnsUpdatesLockDuration() {
|
||||
return Duration.standardMinutes(3);
|
||||
return Duration.ofMinutes(3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,7 +344,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("readDnsRefreshRequestsActionRuntime")
|
||||
public static Duration provideReadDnsRefreshRequestsRuntime() {
|
||||
return Duration.standardSeconds(45);
|
||||
return Duration.ofSeconds(45);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,7 +355,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("dnsDefaultATtl")
|
||||
public static Duration provideDnsDefaultATtl() {
|
||||
return Duration.standardHours(1);
|
||||
return Duration.ofHours(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,7 +366,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("dnsDefaultNsTtl")
|
||||
public static Duration provideDnsDefaultNsTtl() {
|
||||
return Duration.standardHours(3);
|
||||
return Duration.ofHours(3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +377,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("dnsDefaultDsTtl")
|
||||
public static Duration provideDnsDefaultDsTtl() {
|
||||
return Duration.standardHours(1);
|
||||
return Duration.ofHours(1);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -758,7 +758,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("rdeInterval")
|
||||
public static Duration provideRdeInterval() {
|
||||
return Duration.standardDays(1);
|
||||
return Duration.ofDays(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -769,7 +769,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("rdeReportLockTimeout")
|
||||
public static Duration provideRdeReportLockTimeout() {
|
||||
return Duration.standardMinutes(1);
|
||||
return Duration.ofMinutes(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -793,7 +793,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("rdeUploadLockTimeout")
|
||||
public static Duration provideRdeUploadLockTimeout() {
|
||||
return Duration.standardMinutes(30);
|
||||
return Duration.ofMinutes(30);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -806,7 +806,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("rdeUploadSftpCooldown")
|
||||
public static Duration provideRdeUploadSftpCooldown() {
|
||||
return Duration.standardHours(2);
|
||||
return Duration.ofHours(2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -842,7 +842,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("sheetLockTimeout")
|
||||
public static Duration provideSheetLockTimeout() {
|
||||
return Duration.standardHours(1);
|
||||
return Duration.ofHours(1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -866,7 +866,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("emailThrottleDuration")
|
||||
public static Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.misc.emailThrottleSeconds);
|
||||
return Duration.ofSeconds(config.misc.emailThrottleSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -947,7 +947,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("sshTimeout")
|
||||
public static Duration provideSshTimeout() {
|
||||
return Duration.standardSeconds(30);
|
||||
return Duration.ofSeconds(30);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -958,7 +958,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("transactionCooldown")
|
||||
public static Duration provideTransactionCooldown() {
|
||||
return Duration.standardMinutes(5);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1328,14 +1328,14 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("bsaLockLeaseExpiry")
|
||||
public static Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
|
||||
return Duration.standardMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
|
||||
return Duration.ofMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
|
||||
}
|
||||
|
||||
/** Returns the desired interval between successive BSA downloads. */
|
||||
@Provides
|
||||
@Config("bsaDownloadInterval")
|
||||
public static Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
|
||||
return Duration.standardMinutes(config.bsa.bsaDownloadIntervalMinutes);
|
||||
return Duration.ofMinutes(config.bsa.bsaDownloadIntervalMinutes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1345,7 +1345,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("bsaMaxNopInterval")
|
||||
public static Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
|
||||
return Duration.standardHours(config.bsa.bsaMaxNopIntervalHours);
|
||||
return Duration.ofHours(config.bsa.bsaMaxNopIntervalHours);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -1357,13 +1357,13 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("domainCreateTxnCommitTimeLag")
|
||||
public static Duration provideDomainCreateTxnCommitTimeLag(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
|
||||
return Duration.ofSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("bsaValidationMaxStaleness")
|
||||
public static Duration provideBsaValidationMaxStaleness(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
|
||||
return Duration.ofSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -1375,7 +1375,7 @@ public final class RegistryConfig {
|
||||
@Provides
|
||||
@Config("bsaAuthTokenExpiry")
|
||||
public static Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
|
||||
return Duration.standardSeconds(config.bsa.authTokenExpirySeconds);
|
||||
return Duration.ofSeconds(config.bsa.authTokenExpirySeconds);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -1489,7 +1489,7 @@ public final class RegistryConfig {
|
||||
* @see google.registry.tools.server.GenerateZoneFilesAction
|
||||
*/
|
||||
public static Duration getDatabaseRetention() {
|
||||
return Duration.standardDays(30);
|
||||
return Duration.ofDays(30);
|
||||
}
|
||||
|
||||
public static boolean areServersLocal() {
|
||||
@@ -1505,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1515,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1543,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. */
|
||||
@@ -1553,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. */
|
||||
@@ -1637,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
<max-backoff>180s</max-backoff>
|
||||
</queue>
|
||||
|
||||
|
||||
<!-- Queue for tasks that communicate with TMCH MarksDB webserver. -->
|
||||
<queue>
|
||||
<name>marksdb</name>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.google.monitoring.metrics.LabelDescriptor;
|
||||
import com.google.monitoring.metrics.MetricRegistryImpl;
|
||||
import google.registry.util.RegistryEnvironment;
|
||||
import jakarta.inject.Inject;
|
||||
import org.joda.time.Duration;
|
||||
import java.time.Duration;
|
||||
|
||||
/** DNS instrumentation. */
|
||||
// TODO(b/67947699):Once load testing is done, revisit these to rename them and delete the ones that
|
||||
@@ -239,15 +239,15 @@ public class DnsMetrics {
|
||||
int batchSize = numberOfDomains + numberOfHosts;
|
||||
|
||||
processingTimePerCommitDist.record(
|
||||
processingDuration.getMillis(), tld, status.name(), dnsWriter);
|
||||
processingDuration.toMillis(), tld, status.name(), dnsWriter);
|
||||
processingTimePerItemDist.record(
|
||||
processingDuration.getMillis(), batchSize, tld, status.name(), dnsWriter);
|
||||
processingDuration.toMillis(), batchSize, tld, status.name(), dnsWriter);
|
||||
|
||||
if (batchSize > 0) {
|
||||
normalizedProcessingTimePerCommitDist.record(
|
||||
processingDuration.getMillis() / (double) batchSize, tld, status.name(), dnsWriter);
|
||||
processingDuration.toMillis() / (double) batchSize, tld, status.name(), dnsWriter);
|
||||
normalizedProcessingTimePerItemDist.record(
|
||||
processingDuration.getMillis() / (double) batchSize,
|
||||
processingDuration.toMillis() / (double) batchSize,
|
||||
batchSize,
|
||||
tld,
|
||||
status.name(),
|
||||
@@ -267,7 +267,7 @@ public class DnsMetrics {
|
||||
Duration timeSinceUpdateRequest,
|
||||
Duration timeSinceActionEnqueued) {
|
||||
updateRequestLatency.record(
|
||||
timeSinceUpdateRequest.getMillis(), numberOfItems, tld, status.name(), dnsWriter);
|
||||
publishQueueDelay.record(timeSinceActionEnqueued.getMillis(), tld, status.name(), dnsWriter);
|
||||
timeSinceUpdateRequest.toMillis(), numberOfItems, tld, status.name(), dnsWriter);
|
||||
publishQueueDelay.record(timeSinceActionEnqueued.toMillis(), tld, status.name(), dnsWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import google.registry.dns.writer.DnsWriterZone;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.RequestParameters;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Dagger module for the dns package. */
|
||||
@Module
|
||||
@@ -68,15 +68,15 @@ public abstract class DnsModule {
|
||||
|
||||
@Provides
|
||||
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED)
|
||||
static DateTime provideCreateTime(HttpServletRequest req) {
|
||||
return DateTime.parse(extractRequiredParameter(req, PARAM_PUBLISH_TASK_ENQUEUED));
|
||||
static Instant provideCreateTime(HttpServletRequest req) {
|
||||
return Instant.parse(extractRequiredParameter(req, PARAM_PUBLISH_TASK_ENQUEUED));
|
||||
}
|
||||
|
||||
// TODO: Retire the old header after DNS pull queue migration.
|
||||
@Provides
|
||||
@Parameter(PARAM_REFRESH_REQUEST_TIME)
|
||||
static DateTime provideItemsCreateTime(HttpServletRequest req) {
|
||||
return DateTime.parse(
|
||||
static Instant provideItemsCreateTime(HttpServletRequest req) {
|
||||
return Instant.parse(
|
||||
extractOptionalParameter(req, "itemsCreated")
|
||||
.orElse(extractRequiredParameter(req, PARAM_REFRESH_REQUEST_TIME)));
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ import com.google.common.net.InternetDomainName;
|
||||
import google.registry.model.common.DnsRefreshRequest;
|
||||
import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tlds;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Utility class to handle DNS refresh requests. */
|
||||
public final class DnsUtils {
|
||||
@@ -42,13 +42,13 @@ public final class DnsUtils {
|
||||
// Throws an IllegalArgumentException if the name is not under a managed TLD -- we only update
|
||||
// DNS for names that are under our management.
|
||||
String tld = Tlds.findTldForNameOrThrow(InternetDomainName.from(name)).toString();
|
||||
tm().insert(new DnsRefreshRequest(type, name, tld, tm().getTransactionTime().plus(delay)));
|
||||
tm().insert(new DnsRefreshRequest(type, name, tld, tm().getTxTime().plus(delay)));
|
||||
}
|
||||
|
||||
private static void requestDnsRefresh(
|
||||
ImmutableCollection<String> names, TargetType type, Duration delay) {
|
||||
tm().assertInTransaction();
|
||||
DateTime requestTime = tm().getTransactionTime().plus(delay);
|
||||
Instant requestTime = tm().getTxTime().plus(delay);
|
||||
tm().insertAll(
|
||||
names.stream()
|
||||
.map(
|
||||
@@ -103,7 +103,7 @@ public final class DnsUtils {
|
||||
return tm().transact(
|
||||
TRANSACTION_REPEATABLE_READ,
|
||||
() -> {
|
||||
DateTime transactionTime = tm().getTransactionTime();
|
||||
Instant transactionTime = tm().getTxTime();
|
||||
ImmutableList<DnsRefreshRequest> requests =
|
||||
tm().query(
|
||||
"FROM DnsRefreshRequest WHERE tld = :tld "
|
||||
@@ -153,7 +153,7 @@ public final class DnsUtils {
|
||||
dnsAPlusAaaaTtl = tld.getDnsAPlusAaaaTtl().get();
|
||||
}
|
||||
}
|
||||
return dnsAPlusAaaaTtl.getStandardSeconds();
|
||||
return dnsAPlusAaaaTtl.toSeconds();
|
||||
}
|
||||
|
||||
/** The possible values of the {@code DNS_TARGET_TYPE_PARAM} parameter. */
|
||||
|
||||
@@ -63,11 +63,11 @@ import google.registry.util.DomainNameUtils;
|
||||
import google.registry.util.EmailMessage;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.mail.internet.InternetAddress;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Task that sends domain and host updates to the DNS server. */
|
||||
@Action(
|
||||
@@ -100,8 +100,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
*/
|
||||
private final String dnsWriter;
|
||||
|
||||
private final DateTime enqueuedTime;
|
||||
private final DateTime itemsCreateTime;
|
||||
private final Instant enqueuedTime;
|
||||
private final Instant itemsCreateTime;
|
||||
private final int lockIndex;
|
||||
private final int numPublishLocks;
|
||||
private final Set<String> domains;
|
||||
@@ -121,8 +121,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
@Inject
|
||||
public PublishDnsUpdatesAction(
|
||||
@Parameter(PARAM_DNS_WRITER) String dnsWriter,
|
||||
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED) DateTime enqueuedTime,
|
||||
@Parameter(PARAM_REFRESH_REQUEST_TIME) DateTime itemsCreateTime,
|
||||
@Parameter(PARAM_PUBLISH_TASK_ENQUEUED) Instant enqueuedTime,
|
||||
@Parameter(PARAM_REFRESH_REQUEST_TIME) Instant itemsCreateTime,
|
||||
@Parameter(PARAM_LOCK_INDEX) int lockIndex,
|
||||
@Parameter(PARAM_NUM_PUBLISH_LOCKS) int numPublishLocks,
|
||||
@Parameter(PARAM_DOMAINS) Set<String> domains,
|
||||
@@ -167,15 +167,15 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
}
|
||||
|
||||
private void recordActionResult(ActionStatus status) {
|
||||
DateTime now = clock.nowUtc();
|
||||
Instant now = clock.now();
|
||||
|
||||
dnsMetrics.recordActionResult(
|
||||
tld,
|
||||
dnsWriter,
|
||||
status,
|
||||
nullToEmpty(domains).size() + nullToEmpty(hosts).size(),
|
||||
new Duration(itemsCreateTime, now),
|
||||
new Duration(enqueuedTime, now));
|
||||
Duration.between(itemsCreateTime, now),
|
||||
Duration.between(enqueuedTime, now));
|
||||
logger.atInfo().log(
|
||||
"publishDnsWriter latency statistics: TLD: %s, dnsWriter: %s, actionStatus: %s, "
|
||||
+ "numItems: %d, timeSinceCreation: %s, timeInQueue: %s.",
|
||||
@@ -183,8 +183,8 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
dnsWriter,
|
||||
status,
|
||||
nullToEmpty(domains).size() + nullToEmpty(hosts).size(),
|
||||
new Duration(itemsCreateTime, now),
|
||||
new Duration(enqueuedTime, now));
|
||||
Duration.between(itemsCreateTime, now),
|
||||
Duration.between(enqueuedTime, now));
|
||||
}
|
||||
|
||||
/** Runs the task. */
|
||||
@@ -237,7 +237,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
.ifPresent(
|
||||
dn -> {
|
||||
Optional<Domain> domain =
|
||||
ForeignKeyUtils.loadResource(Domain.class, dn, clock.nowUtc());
|
||||
ForeignKeyUtils.loadResource(Domain.class, dn, clock.now());
|
||||
if (domain.isPresent()) {
|
||||
notifyWithEmailAboutDnsUpdateFailure(
|
||||
domain.get().getCurrentSponsorRegistrarId(), dn, false);
|
||||
@@ -250,8 +250,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
hn -> {
|
||||
Optional<Host> host =
|
||||
ForeignKeyUtils.loadResource(Host.class, hn, clock.nowUtc());
|
||||
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hn, clock.now());
|
||||
if (host.isPresent()) {
|
||||
notifyWithEmailAboutDnsUpdateFailure(
|
||||
host.get().getPersistedCurrentSponsorRegistrarId(), hn, true);
|
||||
@@ -336,7 +335,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
.put(PARAM_DNS_WRITER, dnsWriter)
|
||||
.put(PARAM_LOCK_INDEX, Integer.toString(lockIndex))
|
||||
.put(PARAM_NUM_PUBLISH_LOCKS, Integer.toString(numPublishLocks))
|
||||
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.nowUtc().toString())
|
||||
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.now().toString())
|
||||
.put(PARAM_REFRESH_REQUEST_TIME, itemsCreateTime.toString())
|
||||
.put(PARAM_DOMAINS, Joiner.on(",").join(domains))
|
||||
.put(PARAM_HOSTS, Joiner.on(",").join(hosts))
|
||||
@@ -374,7 +373,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
|
||||
/** Steps through the domain and host refreshes contained in the parameters and processes them. */
|
||||
private void processBatch() {
|
||||
DateTime timeAtStart = clock.nowUtc();
|
||||
Instant timeAtStart = clock.now();
|
||||
|
||||
DnsWriter writer = dnsWriterProxy.getByClassNameForTld(dnsWriter, tld);
|
||||
|
||||
@@ -426,7 +425,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
|
||||
actionStatus = ActionStatus.SUCCESS;
|
||||
} finally {
|
||||
recordActionResult(actionStatus);
|
||||
Duration duration = new Duration(timeAtStart, clock.nowUtc());
|
||||
Duration duration = Duration.between(timeAtStart, clock.now());
|
||||
dnsMetrics.recordCommit(
|
||||
tld, dnsWriter, commitStatus, duration, domainsPublished, hostsPublished);
|
||||
logger.atInfo().log(
|
||||
|
||||
@@ -28,7 +28,7 @@ import static google.registry.dns.DnsUtils.deleteRequests;
|
||||
import static google.registry.dns.DnsUtils.readAndUpdateRequestsWithLatestProcessTime;
|
||||
import static google.registry.request.Action.Method.POST;
|
||||
import static google.registry.request.RequestParameters.PARAM_TLD;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.END_INSTANT;
|
||||
import static google.registry.util.DomainNameUtils.getSecondLevelDomain;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@@ -49,10 +49,10 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Action for fanning out DNS refresh tasks by TLD, using data taken from {@link DnsRefreshRequest}
|
||||
@@ -104,11 +104,11 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
|
||||
logger.atInfo().log("The queue updated is paused for TLD: %s.", tld);
|
||||
return;
|
||||
}
|
||||
DateTime requestedEndTime = clock.nowUtc().plus(requestedMaximumDuration);
|
||||
Instant requestedEndTime = clock.now().plus(requestedMaximumDuration);
|
||||
// See getLockIndex(), requests are evenly distributed to [1, numDnsPublishLocks], so each
|
||||
// bucket would be roughly the size of tldUpdateBatchSize.
|
||||
int processBatchSize = tldUpdateBatchSize * Tld.get(tld).getNumDnsPublishLocks();
|
||||
while (requestedEndTime.isAfter(clock.nowUtc())) {
|
||||
while (requestedEndTime.isAfter(clock.now())) {
|
||||
ImmutableList<DnsRefreshRequest> requests =
|
||||
readAndUpdateRequestsWithLatestProcessTime(
|
||||
tld, requestedMaximumDuration, processBatchSize);
|
||||
@@ -165,7 +165,7 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
|
||||
void enqueueUpdates(int lockIndex, int numPublishLocks, Collection<DnsRefreshRequest> requests) {
|
||||
ImmutableList.Builder<String> domainsBuilder = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<String> hostsBuilder = new ImmutableList.Builder<>();
|
||||
DateTime earliestRequestTime = END_OF_TIME;
|
||||
Instant earliestRequestTime = END_INSTANT;
|
||||
for (DnsRefreshRequest request : requests) {
|
||||
if (request.getRequestTime().isBefore(earliestRequestTime)) {
|
||||
earliestRequestTime = request.getRequestTime();
|
||||
@@ -189,7 +189,7 @@ public final class ReadDnsRefreshRequestsAction implements Runnable {
|
||||
.put(PARAM_DNS_WRITER, dnsWriter)
|
||||
.put(PARAM_LOCK_INDEX, Integer.toString(lockIndex))
|
||||
.put(PARAM_NUM_PUBLISH_LOCKS, Integer.toString(numPublishLocks))
|
||||
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.nowUtc().toString())
|
||||
.put(PARAM_PUBLISH_TASK_ENQUEUED, clock.now().toString())
|
||||
.put(PARAM_REFRESH_REQUEST_TIME, earliestRequestTime.toString())
|
||||
.put(PARAM_DOMAINS, Joiner.on(',').join(domains))
|
||||
.put(PARAM_HOSTS, Joiner.on(',').join(hosts))
|
||||
|
||||
@@ -78,7 +78,7 @@ public final class RefreshDnsAction implements Runnable {
|
||||
|
||||
private <T extends EppResource & ForeignKeyedEppResource>
|
||||
T loadAndVerifyExistence(Class<T> clazz, String foreignKey) {
|
||||
return ForeignKeyUtils.loadResource(clazz, foreignKey, clock.nowUtc())
|
||||
return ForeignKeyUtils.loadResource(clazz, foreignKey, clock.now())
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new NotFoundException(
|
||||
|
||||
@@ -30,7 +30,7 @@ import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import jakarta.inject.Inject;
|
||||
import org.joda.time.DateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
@@ -56,7 +56,7 @@ public class RefreshDnsOnHostRenameAction implements Runnable {
|
||||
public void run() {
|
||||
tm().transact(
|
||||
() -> {
|
||||
DateTime now = tm().getTransactionTime();
|
||||
Instant now = tm().getTxTime();
|
||||
Host host = tm().loadByKeyIfPresent(hostKey).orElse(null);
|
||||
boolean hostValid = true;
|
||||
String failureMessage = null;
|
||||
|
||||
@@ -51,6 +51,7 @@ import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -59,7 +60,6 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* {@link DnsWriter} implementation that talks to Google Cloud DNS.
|
||||
@@ -123,8 +123,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
|
||||
String absoluteDomainName = getAbsoluteHostName(domainName);
|
||||
|
||||
// Load the target domain. Note that it can be absent if this domain was just deleted.
|
||||
Optional<Domain> domain =
|
||||
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.nowUtc());
|
||||
Optional<Domain> domain = ForeignKeyUtils.loadResource(Domain.class, domainName, clock.now());
|
||||
|
||||
// Return early if no DNS records should be published.
|
||||
// desiredRecordsBuilder is populated with an empty set to indicate that all existing records
|
||||
@@ -148,7 +147,11 @@ public class CloudDnsWriter extends BaseDnsWriter {
|
||||
domainRecords.add(
|
||||
new ResourceRecordSet()
|
||||
.setName(absoluteDomainName)
|
||||
.setTtl((int) tld.getDnsDsTtl().orElse(defaultDsTtl).getStandardSeconds())
|
||||
.setTtl(
|
||||
(int)
|
||||
tld.getDnsDsTtl()
|
||||
.orElse(defaultDsTtl)
|
||||
.toSeconds())
|
||||
.setType("DS")
|
||||
.setKind("dns#resourceRecordSet")
|
||||
.setRrdatas(ImmutableList.copyOf(dsRrData)));
|
||||
@@ -171,7 +174,11 @@ public class CloudDnsWriter extends BaseDnsWriter {
|
||||
domainRecords.add(
|
||||
new ResourceRecordSet()
|
||||
.setName(absoluteDomainName)
|
||||
.setTtl((int) tld.getDnsNsTtl().orElse(defaultNsTtl).getStandardSeconds())
|
||||
.setTtl(
|
||||
(int)
|
||||
tld.getDnsNsTtl()
|
||||
.orElse(defaultNsTtl)
|
||||
.toSeconds())
|
||||
.setType("NS")
|
||||
.setKind("dns#resourceRecordSet")
|
||||
.setRrdatas(ImmutableList.copyOf(nsRrData)));
|
||||
@@ -190,7 +197,7 @@ public class CloudDnsWriter extends BaseDnsWriter {
|
||||
// Load the target host. Note that it can be absent if this host was just deleted.
|
||||
// desiredRecords is populated with an empty set to indicate that all existing records
|
||||
// should be deleted.
|
||||
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.nowUtc());
|
||||
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.now());
|
||||
|
||||
// Return early if the host is deleted.
|
||||
if (host.isEmpty()) {
|
||||
|
||||
@@ -28,8 +28,8 @@ import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Duration;
|
||||
import javax.net.SocketFactory;
|
||||
import org.joda.time.Duration;
|
||||
import org.xbill.DNS.Message;
|
||||
import org.xbill.DNS.Opcode;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class DnsMessageTransport {
|
||||
@Config("dnsUpdateTimeout") Duration updateTimeout) {
|
||||
this.factory = factory;
|
||||
this.updateHost = updateHost;
|
||||
this.updateTimeout = Ints.checkedCast(updateTimeout.getMillis());
|
||||
this.updateTimeout = Ints.checkedCast(updateTimeout.toMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ package google.registry.dns.writer.dnsupdate;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import org.joda.time.Duration;
|
||||
import java.time.Duration;
|
||||
|
||||
/** Dagger module that provides DNS configuration settings. */
|
||||
@Module
|
||||
@@ -39,6 +39,6 @@ public class DnsUpdateConfigModule {
|
||||
@Provides
|
||||
@Config("dnsUpdateTimeout")
|
||||
public static Duration provideDnsUpdateTimeout() {
|
||||
return Duration.standardSeconds(30);
|
||||
return Duration.ofSeconds(30);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.Duration;
|
||||
import org.xbill.DNS.AAAARecord;
|
||||
import org.xbill.DNS.ARecord;
|
||||
import org.xbill.DNS.DClass;
|
||||
@@ -130,7 +130,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
|
||||
*/
|
||||
private void publishDomain(String domainName, String requestingHostName) {
|
||||
Optional<Domain> domainOptional =
|
||||
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.nowUtc());
|
||||
ForeignKeyUtils.loadResource(Domain.class, domainName, clock.now());
|
||||
update.delete(toAbsoluteName(domainName), Type.ANY);
|
||||
// If the domain is now deleted, then don't update DNS for it.
|
||||
if (domainOptional.isPresent()) {
|
||||
@@ -194,7 +194,9 @@ public class DnsUpdateWriter extends BaseDnsWriter {
|
||||
new DSRecord(
|
||||
toAbsoluteName(domain.getDomainName()),
|
||||
DClass.IN,
|
||||
tld.getDnsDsTtl().orElse(dnsDefaultDsTtl).getStandardSeconds(),
|
||||
tld.getDnsDsTtl()
|
||||
.orElse(dnsDefaultDsTtl)
|
||||
.toSeconds(),
|
||||
signerData.getKeyTag(),
|
||||
signerData.getAlgorithm(),
|
||||
signerData.getDigestType(),
|
||||
@@ -219,7 +221,7 @@ public class DnsUpdateWriter extends BaseDnsWriter {
|
||||
private void addInBailiwickNameServerSet(Domain domain, Update update) {
|
||||
for (String hostName :
|
||||
intersection(domain.loadNameserverHostNames(), domain.getSubordinateHosts())) {
|
||||
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.nowUtc());
|
||||
Optional<Host> host = ForeignKeyUtils.loadResource(Host.class, hostName, clock.now());
|
||||
checkState(host.isPresent(), "Host %s cannot be loaded", hostName);
|
||||
update.add(makeAddressSet(host.get()));
|
||||
update.add(makeV6AddressSet(host.get()));
|
||||
@@ -234,7 +236,9 @@ public class DnsUpdateWriter extends BaseDnsWriter {
|
||||
new NSRecord(
|
||||
toAbsoluteName(domain.getDomainName()),
|
||||
DClass.IN,
|
||||
tld.getDnsNsTtl().orElse(dnsDefaultNsTtl).getStandardSeconds(),
|
||||
tld.getDnsNsTtl()
|
||||
.orElse(dnsDefaultNsTtl)
|
||||
.toSeconds(),
|
||||
toAbsoluteName(hostName));
|
||||
nameServerSet.addRR(record);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@ import java.time.Instant;
|
||||
import java.util.List;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.query.TupleTransformer;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
/**
|
||||
* An action that exports the list of active domains on all real TLDs to Google Drive and GCS.
|
||||
@@ -175,8 +173,7 @@ public class ExportDomainListsAction implements Runnable {
|
||||
@Override
|
||||
public String transformTuple(Object[] domainResult, String[] strings) {
|
||||
String domainName = (String) domainResult[0];
|
||||
Instant deletionInstant = (Instant) domainResult[1];
|
||||
DateTime deletionTime = new DateTime(deletionInstant.toEpochMilli(), DateTimeZone.UTC);
|
||||
Instant deletionTime = (Instant) domainResult[1];
|
||||
String[] domainStatuses = (String[]) domainResult[2];
|
||||
String gracePeriodType = (String) domainResult[3];
|
||||
boolean inPendingDelete =
|
||||
|
||||
@@ -26,6 +26,7 @@ import static google.registry.model.registrar.RegistrarPoc.Type.TECH;
|
||||
import static google.registry.model.registrar.RegistrarPoc.Type.WHOIS;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.START_INSTANT;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -37,7 +38,6 @@ import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registrar.RegistrarPoc;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.DateTimeUtils;
|
||||
import jakarta.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
@@ -63,9 +63,9 @@ class SyncRegistrarsSheet {
|
||||
boolean wereRegistrarsModified() {
|
||||
Optional<Cursor> cursor =
|
||||
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createGlobalVKey(SYNC_REGISTRAR_SHEET)));
|
||||
Instant lastUpdateTime = cursor.isEmpty() ? START_INSTANT : cursor.get().getCursorTimeInstant();
|
||||
Instant lastUpdateTime = cursor.isEmpty() ? START_INSTANT : cursor.get().getCursorTime();
|
||||
for (Registrar registrar : Registrar.loadAllCached()) {
|
||||
if (DateTimeUtils.isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
|
||||
if (isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import jakarta.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.annotation.Nullable;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Action for synchronizing the registrars spreadsheet.
|
||||
|
||||
@@ -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(""),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -49,4 +49,3 @@ public class EppTlsAction implements Runnable {
|
||||
inputXmlBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,4 @@ public class StatelessRequestSessionMetadata extends SessionMetadata {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +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 google.registry.util.DateTimeUtils.minusYears;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -100,15 +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.time.ZoneOffset;
|
||||
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,15 +184,13 @@ 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(),
|
||||
toDateTime(now),
|
||||
ImmutableSortedSet.of(toDateTime(redemptionTime), toDateTime(deletionTime)));
|
||||
existingDomain.createVKey(), now, ImmutableSortedSet.of(redemptionTime, deletionTime));
|
||||
builder
|
||||
.setDeletionTime(deletionTime)
|
||||
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE))
|
||||
@@ -219,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(
|
||||
@@ -235,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));
|
||||
@@ -252,15 +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(ZoneOffset.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(ZoneOffset.UTC).minusYears(1).toInstant();
|
||||
newExpirationTime = minusYears(newExpirationTime, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,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,
|
||||
@@ -425,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();
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import static google.registry.util.DateTimeUtils.END_INSTANT;
|
||||
import static google.registry.util.DateTimeUtils.isAtOrAfter;
|
||||
import static google.registry.util.DateTimeUtils.minusDays;
|
||||
import static google.registry.util.DomainNameUtils.ACE_PREFIX;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
@@ -123,8 +124,8 @@ 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.time.ZoneOffset;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
@@ -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. */
|
||||
@@ -848,10 +848,7 @@ public class DomainFlowUtils {
|
||||
*/
|
||||
public static void validateRegistrationPeriod(Instant now, Instant newExpirationTime)
|
||||
throws EppException {
|
||||
if (now.atZone(ZoneOffset.UTC)
|
||||
.plusYears(MAX_REGISTRATION_YEARS)
|
||||
.toInstant()
|
||||
.isBefore(newExpirationTime)) {
|
||||
if (now.atZone(UTC).plusYears(MAX_REGISTRATION_YEARS).toInstant().isBefore(newExpirationTime)) {
|
||||
throw new ExceedsMaxRegistrationYearsException();
|
||||
}
|
||||
}
|
||||
@@ -1117,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();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ 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;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -86,11 +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.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* An EPP flow that renews a domain.
|
||||
@@ -194,7 +194,7 @@ public final class DomainRenewFlow implements MutatingFlow {
|
||||
Instant newExpirationTime =
|
||||
existingDomain
|
||||
.getRegistrationExpirationTime()
|
||||
.atZone(ZoneOffset.UTC)
|
||||
.atZone(UTC)
|
||||
.plusYears(years)
|
||||
.toInstant(); // Uncapped
|
||||
validateRegistrationPeriod(now, newExpirationTime);
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActi
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_RESTORE;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_INSTANT;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -70,7 +71,6 @@ import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||
import google.registry.model.tld.Tld;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
import org.joda.money.Money;
|
||||
|
||||
@@ -152,7 +152,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
|
||||
Instant newExpirationTime =
|
||||
existingDomain
|
||||
.getRegistrationExpirationTime()
|
||||
.atZone(ZoneOffset.UTC)
|
||||
.atZone(UTC)
|
||||
.plusYears(isExpired ? 1 : 0)
|
||||
.toInstant();
|
||||
// Restore the expiration time on the deleted domain, except if that's already passed, then add
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -35,7 +35,7 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer
|
||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.toDateTime;
|
||||
import static java.time.temporal.ChronoUnit.DAYS;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@@ -82,7 +82,6 @@ import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||
import google.registry.model.transfer.TransferStatus;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -220,9 +219,8 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
|
||||
.map(
|
||||
domainTransferRequestSuperuserExtension ->
|
||||
now.plus(
|
||||
domainTransferRequestSuperuserExtension.getAutomaticTransferLength(),
|
||||
ChronoUnit.DAYS))
|
||||
.orElseGet(() -> now.plusMillis(tld.getAutomaticTransferLength().getMillis()));
|
||||
domainTransferRequestSuperuserExtension.getAutomaticTransferLength(), DAYS))
|
||||
.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
|
||||
@@ -284,9 +282,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
|
||||
DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now, period);
|
||||
|
||||
asyncTaskEnqueuer.enqueueAsyncResave(
|
||||
newDomain.createVKey(),
|
||||
toDateTime(now),
|
||||
ImmutableSortedSet.of(toDateTime(automaticTransferTime)));
|
||||
newDomain.createVKey(), now, ImmutableSortedSet.of(automaticTransferTime));
|
||||
tm().put(newDomain);
|
||||
tm().putAll(serverApproveEntities);
|
||||
tm().insertAll(domainHistory, requestPollMessage);
|
||||
@@ -372,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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public final class PollAckFlow implements MutatingFlow {
|
||||
throw new InvalidMessageIdException(messageId);
|
||||
}
|
||||
|
||||
final Instant now = tm().getTxTime();
|
||||
Instant now = tm().getTxTime();
|
||||
|
||||
// Load the message to be acked. If a message is queued to be delivered in the future, we treat
|
||||
// it as if it doesn't exist yet. Same for if the message ID year isn't the same as the actual
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBu
|
||||
*/
|
||||
public final class KeySerializer {
|
||||
|
||||
|
||||
private KeySerializer() {}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user