1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

...

14 Commits

Author SHA1 Message Date
gbrodman b78d12e73f Add a DelegatingReplicaJpaTransactionManager to handle multiple replicas (#3005)
This will allow us to spread the load across multiple Postgres replica
instances which should help with latency and stability.
2026-04-10 20:46:06 +00:00
Weimin Yu 4a1d0609f3 Support Fee-1.0 XML parser in all environments (#3007)
Add the Fee-1.0 schema in production, allowing the requests with this
extension to be parsed. This allows us to test this extension before hand.

The announcement of this extension in greeting is controlled by a
feature flag in ProtocolDefinition.java. As long as it is not announced,
we do not expect real customers to use this extension.
2026-04-09 20:45:36 +00:00
gbrodman 61b121f464 Fix Gradle issues when running devTool (#3006)
I think this may have been introduced as part of Gradle 9? Not sure why
it's not showing up in the remote builds but without this, I can't run
any "devTool" commands.

Note: the fixes were suggested by gemini-cli
2026-04-09 20:11:44 +00:00
Weimin Yu 074f78cfb3 Fix docker client api version on CloudBuild (#3004)
The docker engine provided by CloudBuild only supports up to 1.41.

Explicitly set API version for downloaded client for now.
2026-04-08 18:13:26 +00:00
Weimin Yu 7be5fe4c01 Fix Flyway script (#3003)
Removing the obsolete command line argument `community`.
2026-04-07 20:40:04 +00:00
Weimin Yu 1876e2c3e8 Fix Kyeth for Java 25 (#3002) 2026-04-06 21:42:11 +00:00
Ben McIlwain 49f14b5e1b Set clock precision to milliseconds for Datetime->Instant migration (#2999)
Our existing precision is milliseconds so we want to stick with that for
Instants. If we want to increase the precision globally after that we can do so
all in one go post-migration, but for now, it would be a bad thing to have mixed
precision going on just depending on whether a class happens to be migrated yet
or not.

This PR also migrates all existing DateTime.nowUtc() calls to use the Clock
interface, so that when they are migrated they will get the benefit of this
precision-setting as well.

BUG= http://b/496985355
2026-04-03 20:38:26 +00:00
Weimin Yu d2881b47dc Upgrade to Java 25 (#3000)
Error-prone introduced many more checks in Java 25. We fixed a few
and suppressed most. A follow-up bug is opened to clean this up.
An ai agent should be able to clean up most of it.

This PR is created with gemini-cli. Summary of experience:

* The good: AI caught most compatibility issues, and with permission,
  suppressed them through compiler flags and errorprone options.
  It also caught many versio references in scripts.

* Where it didn't shine:
  - It did not find and update the target version spec in the custome
    VKey annotation processor source file.
  - It did not flag eclipse-temurin:21 docker image for upgrade.
  - When running into failure, its first instinct is to disable checks
    e.g., -Werror instead of fixing them.
2026-04-02 21:23:00 +00:00
gbrodman 9f3dfec118 Default to skipping optional domain RDAP events (#2995)
We don't need these, so there's no point in adding database load (but we
leave the option to include them in the future). Note that these are,
and were, only ever included for domains so we don't need to worry about
hosts.
2026-04-02 19:12:17 +00:00
Ben McIlwain 60e84e72d7 Begin migration of joda DateTime to java.time.Instant (#2992)
java.time has been around since Java 8 and was based on joda DateTime, so this
is an overdue migration.  We're migrating specifically to Instant in most places
rather than ZonedDateTime because we were always using DateTimes in UTC to
reference a specific instant, which is exactly what Instants are
for. ZonedDateTime set to UTC may still be useful in some places that are heavy
on date math (especially in tests).

There is a lot more work to be done after this, but I wanted to put together a
manual PR showing my overall approach for how to do the migration that I can
then hopefully follow along with AI to continue making these changes throughout
the codebase. The basic approach is to migrate a small number of methods at a
time, marking the old methods as @Deprecated when possible (not always possible
because of @InlineMe restrictions). This PR doesn't yet migrate any DateTime
fields in the model classes, so that's the one remaining type of refactor to
figure out after this. We won't be changing how any of the data is actually
stored in the database.

BUG= http://b/496985355
2026-03-31 20:30:29 +00:00
gbrodman aedfdd47f1 Use caching for host loads in RDAP domain queries (#2996) 2026-03-31 15:57:56 +00:00
gbrodman 9ca75b2294 Install graphviz package in Cloud Build machines (#2997)
The bumped dependency uses the system utility rather than the Java
package, so we need to make sure that it's installed.
2026-03-30 22:03:04 +00:00
Weimin Yu 03b3f9f5a0 Upgrade to Gradle 9 (#2993) 2026-03-30 17:15:55 +00:00
Pavlo Tkach 193ccb5ad3 Increase GKE resources for servicing pubapi (#2994) 2026-03-30 16:50:28 +00:00
190 changed files with 2895 additions and 1286 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
java-version: '25'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+52
View File
@@ -0,0 +1,52 @@
# Engineering Standards for Gemini CLI
This document outlines foundational mandates, architectural patterns, and project-specific conventions to ensure high-quality, idiomatic, and consistent code from the first iteration.
## Core Mandates
### 1. Rigorous Import Management
- **Addition:** When adding new symbols, ensure the corresponding import is added.
- **Removal:** When removing the last usage of a class or symbol from a file (e.g., removing a `@Inject Clock clock;` field), **immediately remove the associated import**. Do not wait for a build failure to identify unused imports.
- **Checkstyle:** Proactively fix common checkstyle errors (line length > 100, formatting, unused imports) during the initial code write. Do not wait for CI/build failures to address these, as iterative fixes are inefficient.
- **Verification:** Before finalizing any change, scan the imports section for redundancy.
### 2. Time and Precision Handling (java.time Migration)
- **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()`.
- Inject `google.registry.util.Clock` (production) or `google.registry.testing.FakeClock` (tests).
- Use `clock.nowDate()` to get a `ZonedDateTime` in UTC.
- **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.
- **Command-Line Tools:**
- Use `@Inject Clock clock;` in `Command` implementations.
- The `clock` field should be **package-private** (no access modifier) to allow manual initialization in corresponding test classes.
- In test classes (e.g., `UpdateDomainCommandTest`), manually set `command.clock = fakeClock;` in the `@BeforeEach` method.
- Base test classes like `EppToolCommandTestCase` should handle this assignment for their generic command types where applicable.
### 3. Dependency Injection (Dagger)
- **Concrete Types:** Dagger `inject` methods must use explicit concrete types. Generic `inject(Command)` methods will not work.
- **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.
### 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).
### 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`.
## Performance and Efficiency
- **Turn Minimization:** Aim for "perfect" code in the first iteration. Iterative fixes for checkstyle or compilation errors consume significant context and time.
- **Context Management:** Use sub-agents for batch refactoring or high-volume output tasks to keep the main session history lean and efficient.
+43 -13
View File
@@ -11,7 +11,6 @@
// 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.
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
@@ -28,8 +27,9 @@ buildscript {
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.1'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:3.1.0'
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.5.0'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:5.1.0'
classpath 'com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.4.0'
classpath 'org.sonatype.aether:aether-api:1.13.1'
classpath 'org.sonatype.aether:aether-impl:1.13.1'
}
@@ -40,15 +40,15 @@ plugins {
// Re-enable when compatible with Gradle 8
// id 'nebula.lint' version '16.0.2'
id 'net.ltgt.errorprone' version '3.1.0'
id 'net.ltgt.errorprone' version '5.1.0'
id 'checkstyle'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'com.gradleup.shadow' version '9.4.0' apply false
// NodeJs plugin
id "com.github.node-gradle.node" version "3.0.1"
id "com.github.node-gradle.node" version "7.1.0"
id 'idea'
id 'com.diffplug.spotless' version '6.20.0'
id 'com.diffplug.spotless' version '8.4.0'
id 'jacoco'
id 'com.dorongold.task-tree' version '2.1.0'
@@ -73,7 +73,15 @@ apply from: 'dependency_lic.gradle'
apply from: 'utils.gradle'
tasks.build.dependsOn(tasks.checkLicense)
// The license-report plugin must run with --no-parallel due to
// complex cross-subject references. The `mutex` pattern does not
// help because a mutex does not enforce task execution order.
// For now we separate checkLicense from build so that the latter may
// still take advantage of parallelism, which cuts down the build time
// by about 20%. The presubmit and release procedures that want to check
// licenses must invoke checkLicense explicitly with the `--no-parallel`
// flag.
// tasks.build.dependsOn(tasks.checkLicense)
// Provide defaults for all of the project properties.
@@ -192,6 +200,7 @@ allprojects {
"--add-exports",
"jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED"]
options.forkOptions.jvmArgs = ["-J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
@@ -255,6 +264,14 @@ subprojects {
// Skip no-op project
if (project.name == 'services') return
apply plugin: 'com.gradleup.shadow'
tasks.configureEach {
if (it.class.name.contains('ShadowJar')) {
it.zip64 = true
}
}
ext.createUberJar = {
taskName,
binaryName,
@@ -263,7 +280,8 @@ subprojects {
List<SourceSetOutput> srcOutput = [project.sourceSets.main.output],
List<String> excludes = [] ->
project.tasks.create(
taskName, com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
taskName, project.tasks.shadowJar.class) {
zip64 = true
mergeServiceFiles()
archiveBaseName = binaryName
if (mainClass != '') {
@@ -321,9 +339,8 @@ subprojects {
// To selectively activate dependency locking without hardcoding them
// in the 'configurations' block, the following code must run after
// project evaluation, when all configurations have been created.
configurations.each {
if (!it.name.contains('detachedConfiguration')
&& it.name != 'integration') {
configurations.all {
if (!it.name.contains('detachedConfiguration')) {
it.resolutionStrategy.activateDependencyLocking()
}
}
@@ -343,6 +360,8 @@ subprojects {
// There are at least two instances, one in core/build.gradle, one in
// release/stage_beam_pipeline.sh
java {
// TODO(b/457758757): change to V_25 once Java in all environments are
// upgraded.
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
@@ -517,7 +536,10 @@ task javadoc(type: Javadoc) {
// In a lot of places we don't write @return so suppress warnings about that.
// We don't report HTML lint errors because XJB-generated POJO files have
// incorrect tags (like dangling </p> without the corresponding open tag.
options.addBooleanOption('Xdoclint:all,-missing,-html', true)
// Starting in Java 25, references to primitives and arrays are forbidden.
// The JAXB-generated classes have array references, and we suppress the
// error with '-reference'.
options.addBooleanOption('Xdoclint:all,-missing,-html,-reference', true)
options.addBooleanOption("-allow-script-in-comments",true)
options.tags = ["type:a:Generic Type",
"error:a:Expected Error",
@@ -537,6 +559,14 @@ task coreDev {
dependsOn 'checkLicense'
dependsOn ':core:check'
dependsOn 'assemble'
if (gradle.startParameter.parallelProjectExecutionEnabled
&& gradle.startParameter.taskNames.contains("coreDev")) {
throw new GradleException(
"ERROR: 'coreDev' cannot run with --parallel due to checkLicense constraints.\n"
+ "Please run: ./gradlew coreDev --no-parallel"
)
}
}
javadocDependentTasks.each { tasks.javadoc.dependsOn(it) }
+48 -39
View File
@@ -4,59 +4,68 @@
com.diffplug.durian:durian-collect:1.2.0=classpath
com.diffplug.durian:durian-core:1.2.0=classpath
com.diffplug.durian:durian-io:1.2.0=classpath
com.diffplug.durian:durian-swt.os:4.2.0=classpath
com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:6.20.0=classpath
com.diffplug.spotless:spotless-lib-extra:2.40.0=classpath
com.diffplug.spotless:spotless-lib:2.40.0=classpath
com.diffplug.spotless:spotless-plugin-gradle:6.20.0=classpath
com.diffplug.durian:durian-swt.os:4.3.0=classpath
com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:8.4.0=classpath
com.diffplug.spotless:spotless-lib-extra:4.5.0=classpath
com.diffplug.spotless:spotless-lib:4.5.0=classpath
com.diffplug.spotless:spotless-plugin-gradle:8.4.0=classpath
com.dorongold.plugins:task-tree:2.1.0=classpath
com.dorongold.task-tree:com.dorongold.task-tree.gradle.plugin:2.1.0=classpath
com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:8.1.1=classpath
com.github.johnrengelman:shadow:8.1.1=classpath
com.github.node-gradle.node:com.github.node-gradle.node.gradle.plugin:3.0.1=classpath
com.github.node-gradle:gradle-node-plugin:3.0.1=classpath
com.google.cloud.tools:appengine-gradle-plugin:2.4.1=classpath
com.google.cloud.tools:appengine-plugins-core:0.9.1=classpath
com.fasterxml.jackson.core:jackson-annotations:2.14.2=classpath
com.fasterxml.jackson.core:jackson-core:2.14.2=classpath
com.fasterxml.jackson.core:jackson-databind:2.14.2=classpath
com.fasterxml.jackson:jackson-bom:2.14.2=classpath
com.fasterxml.woodstox:woodstox-core:7.1.1=classpath
com.github.node-gradle.node:com.github.node-gradle.node.gradle.plugin:7.1.0=classpath
com.github.node-gradle:gradle-node-plugin:7.1.0=classpath
com.google.cloud.tools:appengine-gradle-plugin:2.5.0=classpath
com.google.cloud.tools:appengine-plugins-core:0.10.0=classpath
com.google.code.findbugs:jsr305:3.0.2=classpath
com.google.code.gson:gson:2.8.6=classpath
com.google.errorprone:error_prone_annotations:2.3.4=classpath
com.google.code.gson:gson:2.10.1=classpath
com.google.errorprone:error_prone_annotations:2.18.0=classpath
com.google.guava:failureaccess:1.0.1=classpath
com.google.guava:guava:28.2-jre=classpath
com.google.guava:guava-parent:32.1.2-jre=classpath
com.google.guava:guava:32.1.2-jre=classpath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=classpath
com.google.j2objc:j2objc-annotations:1.3=classpath
com.googlecode.concurrent-trees:concurrent-trees:2.6.1=classpath
com.googlecode.javaewah:JavaEWAH:1.2.3=classpath
com.squareup.okhttp3:okhttp:4.10.0=classpath
com.squareup.okio:okio-jvm:3.0.0=classpath
com.squareup.okio:okio:3.0.0=classpath
commons-io:commons-io:2.11.0=classpath
dev.equo.ide:solstice:1.3.1=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:3.1.0=classpath
net.ltgt.gradle:gradle-errorprone-plugin:3.1.0=classpath
org.apache.ant:ant-launcher:1.10.13=classpath
org.apache.ant:ant:1.10.13=classpath
org.apache.commons:commons-compress:1.20=classpath
com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.4.0=classpath
com.gradleup.shadow:shadow-gradle-plugin:9.4.0=classpath
com.squareup.okhttp3:okhttp:4.12.0=classpath
com.squareup.okio:okio-jvm:3.6.0=classpath
com.squareup.okio:okio:3.6.0=classpath
commons-codec:commons-codec:1.21.0=classpath
commons-io:commons-io:2.21.0=classpath
dev.equo.ide:solstice:1.8.1=classpath
net.ltgt.errorprone:net.ltgt.errorprone.gradle.plugin:5.1.0=classpath
net.ltgt.gradle:gradle-errorprone-plugin:5.1.0=classpath
org.apache.ant:ant-launcher:1.10.15=classpath
org.apache.ant:ant:1.10.15=classpath
org.apache.commons:commons-compress:1.21=classpath
org.apache.commons:commons-lang3:3.5=classpath
org.checkerframework:checker-qual:2.10.0=classpath
org.codehaus.plexus:plexus-utils:3.5.1=classpath
org.eclipse.jgit:org.eclipse.jgit:6.6.0.202305301015-r=classpath
org.eclipse.platform:org.eclipse.osgi:3.18.300=classpath
org.apache.maven:maven-api-annotations:4.0.0-rc-5=classpath
org.apache.maven:maven-api-xml:4.0.0-rc-5=classpath
org.apache.maven:maven-xml:4.0.0-rc-5=classpath
org.checkerframework:checker-qual:3.33.0=classpath
org.codehaus.plexus:plexus-utils:4.0.2=classpath
org.codehaus.plexus:plexus-xml:4.1.1=classpath
org.codehaus.woodstox:stax2-api:4.2.2=classpath
org.eclipse.jgit:org.eclipse.jgit:7.5.0.202512021534-r=classpath
org.eclipse.platform:org.eclipse.osgi:3.24.100=classpath
org.glassfish:javax.json:1.0.4=classpath
org.jdom:jdom2:2.0.6.1=classpath
org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31=classpath
org.jetbrains.kotlin:kotlin-stdlib:1.6.20=classpath
org.jetbrains.kotlin:kotlin-metadata-jvm:2.3.20-RC3=classpath
org.jetbrains.kotlin:kotlin-stdlib-common:2.3.20-RC3=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10=classpath
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10=classpath
org.jetbrains.kotlin:kotlin-stdlib:2.3.20-RC3=classpath
org.jetbrains:annotations:13.0=classpath
org.ow2.asm:asm-commons:9.4=classpath
org.ow2.asm:asm-tree:9.4=classpath
org.ow2.asm:asm:9.4=classpath
org.slf4j:slf4j-api:1.7.36=classpath
org.slf4j:slf4j-api:2.0.17=classpath
org.sonatype.aether:aether-api:1.13.1=classpath
org.sonatype.aether:aether-impl:1.13.1=classpath
org.sonatype.aether:aether-spi:1.13.1=classpath
org.sonatype.aether:aether-util:1.13.1=classpath
org.tukaani:xz:1.9=classpath
org.vafer:jdependency:2.8.0=classpath
org.yaml:snakeyaml:1.21=classpath
org.vafer:jdependency:2.15=classpath
org.yaml:snakeyaml:2.0=classpath
empty=
+58 -43
View File
@@ -1,60 +1,73 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
aopalliance:aopalliance:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
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.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
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
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
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.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
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
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:failureaccess:1.0.2=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,checkstyle,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:33.4.3-android=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.j2objc:j2objc-annotations:3.0.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:guava:33.4.8-jre=checkstyle
com.google.guava:guava:33.5.0-jre=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
com.google.j2objc:j2objc-annotations:3.0.0=checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
com.google.truth:truth:1.4.5=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
com.puppycrawl.tools:checkstyle:9.3=checkstyle
commons-beanutils:commons-beanutils:1.9.4=checkstyle
com.puppycrawl.tools:checkstyle:10.24.0=checkstyle
commons-beanutils:commons-beanutils:1.10.1=checkstyle
commons-codec:commons-codec:1.15=checkstyle
commons-collections:commons-collections:3.2.2=checkstyle
info.picocli:picocli:4.6.2=checkstyle
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
info.picocli:picocli:4.7.7=checkstyle
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
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,errorprone,testAnnotationProcessor,testingAnnotationProcessor
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:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
net.sf.saxon:Saxon-HE:12.5=checkstyle
org.antlr:antlr4-runtime:4.13.2=checkstyle
org.apache.commons:commons-lang3:3.8.1=checkstyle
org.apache.commons:commons-text:1.3=checkstyle
org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle
org.apache.httpcomponents:httpclient:4.5.13=checkstyle
org.apache.httpcomponents:httpcore:4.4.14=checkstyle
org.apache.maven.doxia:doxia-core:1.12.0=checkstyle
org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle
org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle
org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.checkerframework:checker-qual:3.19.0=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
org.checkerframework:checker-qual:3.43.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.checkerframework:checker-qual:3.49.3=checkstyle
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
org.codehaus.plexus:plexus-utils:3.3.0=checkstyle
org.hamcrest:hamcrest-core:1.3=testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.jacoco:org.jacoco.agent:0.8.13=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.13=jacocoAnt
org.jacoco:org.jacoco.core:0.8.13=jacocoAnt
org.jacoco:org.jacoco.report:0.8.13=jacocoAnt
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.jspecify:jspecify:1.0.0=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.jspecify:jspecify:1.0.0=annotationProcessor,checkstyle,compileClasspath,deploy_jar,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath,testing,testingAnnotationProcessor,testingCompileClasspath
org.junit.jupiter:junit-jupiter-api:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.13.4=testCompileClasspath,testRuntimeClasspath
@@ -62,9 +75,11 @@ org.junit.platform:junit-platform-engine:1.13.4=testCompileClasspath,testRuntime
org.junit.platform:junit-platform-launcher:1.13.4=testCompileClasspath,testRuntimeClasspath
org.junit:junit-bom:5.13.4=testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.8=jacocoAnt
org.ow2.asm:asm-tree:9.8=jacocoAnt
org.ow2.asm:asm:9.8=compileClasspath,deploy_jar,jacocoAnt,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor,testingAnnotationProcessor
org.ow2.asm:asm-commons:9.9=jacocoAnt
org.ow2.asm:asm-tree:9.9=jacocoAnt
org.ow2.asm:asm:9.8=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath,testing,testingCompileClasspath
org.ow2.asm:asm:9.9=jacocoAnt
org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor,testingAnnotationProcessor
org.reflections:reflections:0.10.2=checkstyle
empty=testingCompile,testingRuntime,testingRuntimeClasspath
org.xmlresolver:xmlresolver:5.2.2=checkstyle
empty=shadow,testingCompile,testingRuntime,testingRuntimeClasspath
@@ -15,6 +15,9 @@
package google.registry.util;
import java.io.Serializable;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
@@ -30,5 +33,14 @@ import org.joda.time.DateTime;
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);
}
}
@@ -20,6 +20,9 @@ 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.ZoneOffset;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
@@ -28,7 +31,10 @@ import org.joda.time.LocalDate;
public abstract class DateTimeUtils {
/** The start of the epoch, in a convenient constant. */
public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC);
@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.
@@ -37,19 +43,40 @@ public abstract class DateTimeUtils {
* but Java uses milliseconds, so this is the largest representable date that will survive a
* round-trip through the database.
*/
@Deprecated
public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, DateTimeZone.UTC);
/**
* An instant 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.
*/
public static final Instant END_INSTANT = Instant.ofEpochMilli(Long.MAX_VALUE / 1000);
/** 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 earliestOf(Iterable<DateTime> dates) {
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. */
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 latestOf(Lists.asList(first, rest));
@@ -66,29 +93,63 @@ public abstract class DateTimeUtils {
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);
}
/**
* 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.
*/
@Deprecated
public static DateTime leapSafeAddYears(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.
*/
public static Instant leapSafeAddYears(Instant now, long years) {
checkArgument(years >= 0);
return (years == 0)
? now
: now.atZone(ZoneOffset.UTC).plusYears(1).plusYears(years - 1).toInstant();
}
/**
* 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.
*/
@Deprecated
public static DateTime leapSafeSubtractYears(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.
*/
public static Instant leapSafeSubtractYears(Instant now, int years) {
checkArgument(years >= 0);
return (years == 0)
? now
: now.atZone(ZoneOffset.UTC).minusYears(1).minusYears(years - 1).toInstant();
}
public static Date toSqlDate(LocalDate localDate) {
return new Date(localDate.toDateTimeAtStartOfDay().getMillis());
}
@@ -96,4 +157,34 @@ public abstract class DateTimeUtils {
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());
}
public static Instant plusYears(Instant instant, int years) {
return instant.atZone(ZoneOffset.UTC).plusYears(years).toInstant();
}
public static Instant plusDays(Instant instant, int days) {
return instant.atZone(ZoneOffset.UTC).plusDays(days).toInstant();
}
public static Instant minusDays(Instant instant, int days) {
return instant.atZone(ZoneOffset.UTC).minusDays(days).toInstant();
}
}
@@ -17,6 +17,7 @@ package google.registry.util;
import static org.joda.time.DateTimeZone.UTC;
import jakarta.inject.Inject;
import java.time.Instant;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
@@ -34,4 +35,13 @@ public class SystemClock implements Clock {
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(java.time.temporal.ChronoUnit.MILLIS);
}
}
@@ -19,6 +19,7 @@ import static org.joda.time.DateTimeZone.UTC;
import static org.joda.time.Duration.millis;
import google.registry.util.Clock;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
@@ -54,6 +55,11 @@ public final class FakeClock implements Clock {
return new DateTime(currentTimeMillis.addAndGet(autoIncrementStepMs), UTC);
}
@Override
public Instant now() {
return Instant.ofEpochMilli(currentTimeMillis.addAndGet(autoIncrementStepMs));
}
/**
* Sets the increment applied to the clock whenever it is queried. The increment is zero by
* default: the clock is left unchanged when queried.
@@ -244,6 +244,12 @@
{
"moduleLicense": "The JSON License"
},
{
"moduleLicense": "LGPL-2.1-or-later"
},
{
"moduleLicense": "Apache License version 2.0"
},
{
"moduleLicense": "LGPL-2.1+"
},
+57 -41
View File
@@ -1,47 +1,63 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
aopalliance:aopalliance:1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,testAnnotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,testAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.guava:failureaccess:1.0.1=annotationProcessor,checkstyle,errorprone,testAnnotationProcessor
com.google.guava:guava-parent:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=annotationProcessor,errorprone,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,testAnnotationProcessor
com.puppycrawl.tools:checkstyle:9.3=checkstyle
commons-beanutils:commons-beanutils:1.9.4=checkstyle
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor
com.google.code.findbugs:jsr305:3.0.2=checkstyle
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.36.0=checkstyle
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,checkstyle,testAnnotationProcessor
com.google.guava:guava:33.4.8-jre=checkstyle
com.google.guava:guava:33.5.0-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:3.0.0=checkstyle
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,testAnnotationProcessor
com.puppycrawl.tools:checkstyle:10.24.0=checkstyle
commons-beanutils:commons-beanutils:1.10.1=checkstyle
commons-codec:commons-codec:1.15=checkstyle
commons-collections:commons-collections:3.2.2=checkstyle
info.picocli:picocli:4.6.2=checkstyle
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
javax.inject:javax.inject:1=annotationProcessor,errorprone,testAnnotationProcessor
net.sf.saxon:Saxon-HE:10.6=checkstyle
org.antlr:antlr4-runtime:4.9.3=checkstyle
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=annotationProcessor,errorprone,testAnnotationProcessor
org.jacoco:org.jacoco.agent:0.8.13=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.13=jacocoAnt
org.jacoco:org.jacoco.core:0.8.13=jacocoAnt
org.jacoco:org.jacoco.report:0.8.13=jacocoAnt
info.picocli:picocli:4.7.7=checkstyle
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,testAnnotationProcessor
javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:12.5=checkstyle
org.antlr:antlr4-runtime:4.13.2=checkstyle
org.apache.commons:commons-lang3:3.8.1=checkstyle
org.apache.commons:commons-text:1.3=checkstyle
org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle
org.apache.httpcomponents:httpclient:4.5.13=checkstyle
org.apache.httpcomponents:httpcore:4.4.14=checkstyle
org.apache.maven.doxia:doxia-core:1.12.0=checkstyle
org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle
org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle
org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.checkerframework:checker-qual:3.19.0=annotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.49.3=checkstyle
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
org.codehaus.plexus:plexus-utils:3.3.0=checkstyle
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.ow2.asm:asm-commons:9.8=jacocoAnt
org.ow2.asm:asm-tree:9.8=jacocoAnt
org.ow2.asm:asm:9.8=jacocoAnt
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,testAnnotationProcessor
org.jspecify:jspecify:1.0.0=annotationProcessor,checkstyle,testAnnotationProcessor
org.ow2.asm:asm-commons:9.9=jacocoAnt
org.ow2.asm:asm-tree:9.9=jacocoAnt
org.ow2.asm:asm:9.9=jacocoAnt
org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor
org.reflections:reflections:0.10.2=checkstyle
empty=compileClasspath,deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.xmlresolver:xmlresolver:5.2.2=checkstyle
empty=compileClasspath,deploy_jar,runtimeClasspath,shadow,testCompileClasspath,testRuntimeClasspath
+1 -1
View File
@@ -1,3 +1,3 @@
FROM eclipse-temurin:21
FROM eclipse-temurin:25
ADD build/libs/nomulus.jar /nomulus.jar
ENTRYPOINT ["java", "-jar", "/nomulus.jar"]
+5 -10
View File
@@ -17,7 +17,7 @@ import java.util.Optional
plugins {
id 'java-library'
id "org.flywaydb.flyway" version "11.0.1"
id "org.flywaydb.flyway" version "12.2.0"
id 'maven-publish'
}
@@ -74,11 +74,7 @@ sourceSets {
nonprod {
java {
compileClasspath += main.output
// Add the DB runtime classpath to nonprod so we can load the flyway
// scripts.
runtimeClasspath += main.output +
rootProject.project(":db").sourceSets.main.runtimeClasspath
runtimeClasspath += main.output
}
}
test {
@@ -102,6 +98,7 @@ configurations {
devtool
nonprodImplementation.extendsFrom implementation
nonprodRuntimeOnly.extendsFrom runtimeOnly
testImplementation.extendsFrom nonprodImplementation
@@ -259,6 +256,7 @@ dependencies {
implementation project(':util')
// Import NomulusPostreSql from ':db' for implementation but exclude dependencies.
implementation project(path: ':db', configuration: 'implementationApi')
nonprodRuntimeOnly project(':db')
testRuntimeOnly project(':db')
annotationProcessor deps['com.google.auto.service:auto-service']
@@ -301,9 +299,6 @@ dependencies {
// Dependency needed for soy to java compilation.
soy deps['com.google.template:soy']
// Tool dependencies. used for doc generation.
implementation files("${System.properties['java.home']}/../lib/tools.jar")
// Flyway classes needed to generate the golden file.
implementation deps['org.flywaydb:flyway-core']
implementation deps['org.flywaydb:flyway-database-postgresql']
@@ -596,7 +591,7 @@ if (environment == 'alpha') {
gs://${gcpProject}-deploy/live/beam/${metaDataBaseName} \
--image-gcr-path ${imageName}:live \
--sdk-language JAVA \
--flex-template-base-image gcr.io/dataflow-templates-base/java21-template-launcher-base:latest \
--flex-template-base-image gcr.io/dataflow-templates-base/java25-template-launcher-base:latest \
--metadata-file ${projectDir}/src/main/resources/${metaData} \
--jar ${uberJarName} \
--env FLEX_TEMPLATE_JAVA_MAIN_CLASS=${mainClass} \
+7 -9
View File
@@ -1,13 +1,11 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.fasterxml.jackson.core:jackson-annotations:2.15.2=classpath
com.fasterxml.jackson.core:jackson-core:2.15.2=classpath
com.fasterxml.jackson.core:jackson-databind:2.15.2=classpath
com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.15.2=classpath
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2=classpath
com.fasterxml.jackson:jackson-bom:2.15.2=classpath
gradle.plugin.org.flywaydb:gradle-plugin-publishing:11.0.1=classpath
org.flywaydb.flyway:org.flywaydb.flyway.gradle.plugin:11.0.1=classpath
org.flywaydb:flyway-core:11.0.1=classpath
com.fasterxml.jackson.core:jackson-annotations:2.21=classpath
gradle.plugin.org.flywaydb:gradle-plugin-publishing:12.2.0=classpath
org.flywaydb.flyway:org.flywaydb.flyway.gradle.plugin:12.2.0=classpath
org.flywaydb:flyway-core:12.2.0=classpath
tools.jackson.core:jackson-core:3.1.0=classpath
tools.jackson.core:jackson-databind:3.1.0=classpath
tools.jackson:jackson-bom:3.1.0=classpath
empty=
+80 -61
View File
@@ -1,7 +1,7 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
aopalliance:aopalliance:1.0=annotationProcessor,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
aopalliance:aopalliance:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
args4j:args4j:2.33=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.charleskorn.kaml:kaml:0.20.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.fasterxml.jackson.core:jackson-annotations:2.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -12,7 +12,7 @@ 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:classmate:1.7.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
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.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
@@ -25,7 +25,7 @@ com.github.jnr:jnr-ffi:2.2.18=compileClasspath,deploy_jar,nonprodCompileClasspat
com.github.jnr:jnr-posix:3.1.21=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-unixsocket:0.38.24=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-x86asm:1.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api-client:google-api-client-jackson2:2.0.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api-client:google-api-client-jackson2:2.7.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -100,8 +100,10 @@ com.google.apis:google-api-services-admin-directory:directory_v1-rev20260227-2.0
com.google.apis:google-api-services-bigquery:v2-rev20240815-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20240310-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20260213-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260219-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260322-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260219-2.0.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260402-2.0.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260322-2.0.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260405-2.0.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260112-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
@@ -115,14 +117,14 @@ com.google.apis:google-api-services-storage:v1-rev20250312-2.0.0=compileClasspat
com.google.apis:google-api-services-storage:v1-rev20251118-2.0.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
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
com.google.auto.value:auto-value-annotations:1.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value:1.11.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.value:auto-value:1.11.1=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.cloud.bigdataoss:gcsio:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigdataoss:util:2.2.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigtable:bigtable-client-core-config:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -132,7 +134,7 @@ com.google.cloud.opentelemetry:detector-resources-support:0.33.0=deploy_jar,nonp
com.google.cloud.opentelemetry:exporter-metrics:0.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:shared-resourcemapping:0.33.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.28.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.28.2=deploy_jar,runtimeClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.28.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-bigquerystorage:3.9.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.43.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
@@ -158,7 +160,7 @@ com.google.cloud:grpc-gcp:1.6.1=compileClasspath,deploy_jar,nonprodCompileClassp
com.google.cloud:libraries-bom:26.48.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.25.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:proto-google-cloud-firestore-bundle-v1:3.26.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.code.gson:gson:2.10.1=soy
com.google.code.gson:gson:2.12.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.common.html.types:types:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
@@ -166,15 +168,12 @@ com.google.dagger:dagger-compiler:2.59.2=annotationProcessor,testAnnotationProce
com.google.dagger:dagger-spi:2.59.2=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger:2.59.2=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.devtools.ksp:symbol-processing-api:2.2.20-2.0.3=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.20.0=soy
com.google.errorprone:error_prone_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_annotations:2.7.1=checkstyle
com.google.errorprone:error_prone_check_api:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_type_annotations:2.23.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:javac:9+181-r4173-1=errorproneJavac
com.google.errorprone:error_prone_annotations:2.36.0=checkstyle
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.escapevelocity:escapevelocity:1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flatbuffers:flatbuffers-java:23.5.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=soy
@@ -183,18 +182,16 @@ com.google.flogger:flogger:0.7.4=soy
com.google.flogger:flogger:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.4=soy
com.google.flogger:google-extensions:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.googlejavaformat:google-java-format:1.33.0=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=checkstyle,errorprone,nonprodAnnotationProcessor,soy
com.google.guava:failureaccess:1.0.2=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.1=soy
com.google.guava:failureaccess:1.0.3=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava-parent:32.1.1-jre=soy
com.google.guava:guava-testlib:33.3.0-jre=testRuntimeClasspath
com.google.guava:guava-testlib:33.5.0-jre=testCompileClasspath
com.google.guava:guava:31.0.1-jre=checkstyle
com.google.guava:guava:32.1.1-jre=errorprone,nonprodAnnotationProcessor,soy
com.google.guava:guava:33.0.0-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.5.0-jre=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:guava:32.1.1-jre=soy
com.google.guava:guava:33.4.8-jre=checkstyle
com.google.guava:guava:33.5.0-jre=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.gwt:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-apache-v2:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-appengine:1.46.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -203,10 +200,9 @@ com.google.http-client:google-http-client-jackson2:1.46.3=compileClasspath,deplo
com.google.http-client:google-http-client-protobuf:1.44.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.http-client:google-http-client-protobuf:1.45.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:5.1.0=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.inject:guice:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:1.3=checkstyle
com.google.j2objc:j2objc-annotations:3.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:3.0.0=checkstyle
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
com.google.jsinterop:jsinterop-annotations:1.0.1=soy
com.google.jsinterop:jsinterop-annotations:2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.monitoring-client:contrib:1.0.7=testCompileClasspath,testRuntimeClasspath
@@ -221,8 +217,8 @@ com.google.oauth-client:google-oauth-client-servlet:1.39.0=compileClasspath,nonp
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.34.1=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.19.6=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
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.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2024-02-26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
@@ -231,7 +227,7 @@ com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprod
com.ibm.icu:icu4j:73.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.jcraft:jsch:0.1.55=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.lmax:disruptor:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.puppycrawl.tools:checkstyle:9.3=checkstyle
com.puppycrawl.tools:checkstyle:10.24.0=checkstyle
com.squareup.okhttp3:okhttp:4.12.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.squareup.okio:okio-bom:3.0.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.squareup.okio:okio-fakefilesystem-jvm:3.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -258,7 +254,8 @@ com.sun.xml.bind.external:relaxng-datatype:4.0.7=jaxb
com.sun.xml.bind.external:rngom:4.0.7=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.9.4=checkstyle
commons-beanutils:commons-beanutils:1.10.1=checkstyle
commons-codec:commons-codec:1.15=checkstyle
commons-codec:commons-codec:1.19.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-collections:commons-collections:3.2.2=checkstyle
commons-io:commons-io:2.20.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -271,11 +268,11 @@ guru.nidi.com.eclipsesource.j2v8:j2v8_win32_x86_64:4.6.0=testRuntimeClasspath
guru.nidi.com.kitfox:svgSalamander:1.1.3=testRuntimeClasspath
guru.nidi:graphviz-java-all-j2v8:0.18.1=testRuntimeClasspath
guru.nidi:graphviz-java:0.18.1=testRuntimeClasspath
info.picocli:picocli:4.6.2=checkstyle
info.picocli:picocli:4.7.7=checkstyle
io.apicurio:apicurio-registry-protobuf-schema-utilities:3.0.0.M2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.github.eisop:dataflow-errorprone:3.34.0-eisop1=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.16=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.70.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
@@ -377,7 +374,7 @@ jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=deploy_jar,nonprodRuntimeClasspath,r
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=compileClasspath,jaxb,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,errorprone,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
javax.jdo:jdo2-api:2.3-20090302111651=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.validation:validation-api:1.0.0.GA=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
joda-time:joda-time:2.12.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -389,12 +386,11 @@ net.bytebuddy:byte-buddy:1.17.8=deploy_jar,nonprodRuntimeClasspath,runtimeClassp
net.bytebuddy:byte-buddy:1.18.5=testCompileClasspath,testRuntimeClasspath
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:10.6=checkstyle
net.sf.saxon:Saxon-HE:12.5=checkstyle
org.abego.treelayout:org.abego.treelayout.core:1.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.antlr:ST4:4.3.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.antlr:antlr-runtime:3.5.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.antlr:antlr4-runtime:4.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.antlr:antlr4-runtime:4.9.3=checkstyle
org.antlr:antlr4-runtime:4.13.2=checkstyle,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.antlr:antlr4:4.13.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-format:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-memory-core:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -425,17 +421,29 @@ org.apache.commons:commons-csv:1.14.1=compileClasspath,deploy_jar,nonprodCompile
org.apache.commons:commons-exec:1.3=testRuntimeClasspath
org.apache.commons:commons-lang3:3.18.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.apache.commons:commons-lang3:3.20.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-lang3:3.8.1=checkstyle
org.apache.commons:commons-text:1.15.0=testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-text:1.3=checkstyle
org.apache.ftpserver:ftplet-api:1.2.1=testCompileClasspath,testRuntimeClasspath
org.apache.ftpserver:ftpserver-core:1.2.1=testCompileClasspath,testRuntimeClasspath
org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle
org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle
org.apache.httpcomponents:httpclient:4.5.13=checkstyle
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.httpcomponents:httpcore:4.4.14=checkstyle
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.maven.doxia:doxia-core:1.12.0=checkstyle
org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle
org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle
org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle
org.apache.mina:mina-core:2.2.4=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-common:3.0.0-M2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:3.0.0-M2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:3.0.0-M2=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:3.0.0-M2=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.20=testCompileClasspath,testRuntimeClasspath
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.83=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.bouncycastle:bcpkix-jdk18on:1.83=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -443,12 +451,16 @@ org.bouncycastle:bcprov-jdk18on:1.83=compileClasspath,deploy_jar,nonprodCompileC
org.bouncycastle:bcutil-jdk18on:1.83=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-compat-qual:2.5.3=annotationProcessor,compileClasspath,nonprodCompileClasspath,soy,testAnnotationProcessor,testCompileClasspath
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.12.0=checkstyle
org.checkerframework:checker-qual:3.33.0=errorprone,nonprodAnnotationProcessor,soy
org.checkerframework:checker-qual:3.41.0=annotationProcessor,testAnnotationProcessor
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.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,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
org.codehaus.plexus:plexus-utils:3.3.0=checkstyle
org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.angus:angus-activation:2.0.3=jaxb
org.eclipse.angus:angus-activation:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -465,8 +477,8 @@ org.eclipse.jetty:jetty-server:12.1.7=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.7=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.7=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.7=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.3.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.3.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.7=jaxb
org.glassfish.jaxb:jaxb-core:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.7=jaxb
@@ -486,10 +498,10 @@ org.hibernate.models:hibernate-models:1.0.1=deploy_jar,nonprodRuntimeClasspath,r
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.jacoco:org.jacoco.agent:0.8.13=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.13=jacocoAnt
org.jacoco:org.jacoco.core:0.8.13=jacocoAnt
org.jacoco:org.jacoco.report:0.8.13=jacocoAnt
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.jcommander:jcommander:2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -517,7 +529,7 @@ org.joda:joda-money:2.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,no
org.json:json:20230618=soy
org.json:json:20240303=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.22.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.jspecify:jspecify:1.0.0=annotationProcessor,checkstyle,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.junit-pioneer:junit-pioneer:2.3.0=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.13.4=testCompileClasspath,testRuntimeClasspath
@@ -539,16 +551,17 @@ org.ow2.asm:asm-analysis:9.5=soy
org.ow2.asm:asm-analysis:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.5=soy
org.ow2.asm:asm-commons:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-commons:9.8=jacocoAnt
org.ow2.asm:asm-commons:9.9=jacocoAnt
org.ow2.asm:asm-tree:9.5=soy
org.ow2.asm:asm-tree:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm-tree:9.8=jacocoAnt
org.ow2.asm:asm-tree:9.9=jacocoAnt
org.ow2.asm:asm-util:9.5=soy
org.ow2.asm:asm-util:9.7.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.5=soy
org.ow2.asm:asm:9.7.1=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm:9.8=deploy_jar,jacocoAnt,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.pcollections:pcollections:3.1.4=annotationProcessor,errorprone,nonprodAnnotationProcessor,testAnnotationProcessor
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.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -584,17 +597,23 @@ org.threeten:threetenbp:1.7.0=compileClasspath,deploy_jar,nonprodCompileClasspat
org.w3c.css:sac:1.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.webjars.npm:viz.js-graphviz-java:2.1.3=testRuntimeClasspath
org.xerial.snappy:snappy-java:1.1.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.xmlresolver:xmlresolver:5.2.2=checkstyle
org.yaml:snakeyaml:2.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-core:3.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-databind:3.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson:jackson-bom:3.1.0=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.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.10.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.9.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.10.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
us.fatehi:schemacrawler-operations:17.9.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.10.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.9.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.10.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
us.fatehi:schemacrawler-text:17.9.0=deploy_jar,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.8.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.10.0=compileClasspath,nonprodCompileClasspath,nonprodRuntimeClasspath
us.fatehi:schemacrawler:17.9.0=deploy_jar,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool
empty=devtool,shadow
@@ -17,6 +17,7 @@ package google.registry.batch;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static google.registry.flows.FlowUtils.marshalWithLenientRetry;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_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;
@@ -39,7 +40,6 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import google.registry.util.DateTimeUtils;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.util.Optional;
@@ -212,7 +212,7 @@ public class BulkDomainTransferAction implements Runnable {
private boolean shouldSkipDomain(String domainName) {
Optional<Domain> maybeDomain =
ForeignKeyUtils.loadResource(Domain.class, domainName, tm().getTransactionTime());
ForeignKeyUtils.loadResource(Domain.class, domainName, tm().getTxTime());
if (maybeDomain.isEmpty()) {
logger.atWarning().log("Domain '%s' was already deleted", domainName);
missingDomains++;
@@ -232,7 +232,7 @@ public class BulkDomainTransferAction implements Runnable {
return true;
}
if (domain.getStatusValues().contains(StatusValue.PENDING_DELETE)
|| !domain.getDeletionTime().equals(DateTimeUtils.END_OF_TIME)) {
|| !domain.getDeletionTime().equals(END_INSTANT)) {
logger.atWarning().log("Domain '%s' is in PENDING_DELETE", domainName);
pendingDelete++;
return true;
@@ -18,6 +18,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static google.registry.flows.FlowUtils.marshalWithLenientRetry;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
@@ -177,7 +178,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
"Failed to delete domain %s because of its autorenew end time: %s.",
transDomain.getDomainName(), transDomain.getAutorenewEndTime());
return Optional.empty();
} else if (domain.getDeletionTime().isBefore(END_OF_TIME)) {
} else if (domain.getDeletionTime().isBefore(END_INSTANT)) {
logger.atSevere().log(
"Failed to delete domain %s because it was already deleted on %s.",
transDomain.getDomainName(), transDomain.getDeletionTime());
@@ -28,7 +28,6 @@ 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.RegistryEnvironment.PRODUCTION;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
@@ -44,6 +43,7 @@ import google.registry.model.tld.Tld.TldType;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import jakarta.persistence.TypedQuery;
@@ -111,16 +111,20 @@ public class DeleteProberDataAction implements Runnable {
String registryAdminRegistrarId;
private final Clock clock;
@Inject
DeleteProberDataAction(
@Parameter(PARAM_DRY_RUN) boolean isDryRun,
@Parameter(PARAM_TLDS) ImmutableSet<String> tlds,
@Parameter(PARAM_BATCH_SIZE) Optional<Integer> batchSize,
@Config("registryAdminClientId") String registryAdminRegistrarId) {
@Config("registryAdminClientId") String registryAdminRegistrarId,
Clock clock) {
this.isDryRun = isDryRun;
this.tlds = tlds;
this.batchSize = batchSize.orElse(DEFAULT_BATCH_SIZE);
this.registryAdminRegistrarId = registryAdminRegistrarId;
this.clock = clock;
}
@Override
@@ -145,7 +149,7 @@ public class DeleteProberDataAction implements Runnable {
AtomicInteger softDeletedDomains = new AtomicInteger();
AtomicInteger hardDeletedDomains = new AtomicInteger();
AtomicReference<ImmutableList<Domain>> domainsBatch = new AtomicReference<>();
DateTime startTime = DateTime.now(UTC);
DateTime startTime = clock.nowUtc();
do {
tm().transact(
TRANSACTION_REPEATABLE_READ,
@@ -164,7 +168,7 @@ public class DeleteProberDataAction implements Runnable {
hardDeletedDomains.get(), batchSize);
// Automatically kill the job if it is running for over 20 hours
} while (DateTime.now(UTC).isBefore(startTime.plusHours(20))
} while (clock.nowUtc().isBefore(startTime.plusHours(20))
&& domainsBatch.get().size() == batchSize);
logger.atInfo().log(
"%s %d domains.",
@@ -188,7 +188,7 @@ public class RelockDomainAction implements Runnable {
"Domain %s has a pending delete.",
domainName);
checkArgument(
!DateTimeUtils.isAtOrAfter(tm().getTransactionTime(), domain.getDeletionTime()),
!DateTimeUtils.isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
"Domain %s has been deleted.",
domainName);
checkArgument(
@@ -19,7 +19,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_OK;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -37,6 +36,7 @@ import google.registry.model.registrar.RegistrarPoc.Type;
import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.AddressException;
@@ -73,6 +73,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
private final GmailClient gmailClient;
private final String expirationWarningEmailSubjectText;
private final Response response;
private final Clock clock;
@Inject
public SendExpiringCertificateNotificationEmailAction(
@@ -80,12 +81,14 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@Config("expirationWarningEmailSubjectText") String expirationWarningEmailSubjectText,
GmailClient gmailClient,
CertificateChecker certificateChecker,
Response response) {
Response response,
Clock clock) {
this.certificateChecker = certificateChecker;
this.expirationWarningEmailSubjectText = expirationWarningEmailSubjectText;
this.gmailClient = gmailClient;
this.expirationWarningEmailBodyText = expirationWarningEmailBodyText;
this.response = response;
this.clock = clock;
}
@Override
@@ -186,7 +189,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
*/
updateLastNotificationSentDate(
registrar,
DateTime.now(UTC).minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
clock.nowUtc().minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
certificateType);
return true;
} catch (Exception e) {
@@ -24,6 +24,7 @@ import static google.registry.util.CollectionUtils.union;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.earliestOf;
import static google.registry.util.DateTimeUtils.latestOf;
import static google.registry.util.DateTimeUtils.toInstant;
import static org.apache.beam.sdk.values.TypeDescriptors.voids;
import com.google.common.collect.ImmutableMap;
@@ -372,7 +373,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
// during ARGP).
//
// See: DomainFlowUtils#createCancellingRecords
domain.getDeletionTime().isBefore(billingTime)
domain.getDeletionTime().isBefore(toInstant(billingTime))
? ImmutableSet.of()
: ImmutableSet.of(
DomainTransactionRecord.create(
@@ -21,6 +21,8 @@ import com.google.common.annotations.VisibleForTesting;
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;
@@ -40,7 +42,6 @@ import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.joda.time.Instant;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -74,6 +75,8 @@ public class SafeBrowsingTransforms {
/** Provides the SafeBrowsing API key at runtime. */
private final String apiKey;
private final Clock clock;
/**
* Maps a domain name's {@code domainName} to its corresponding {@link DomainNameInfo} to
* facilitate batching SafeBrowsing API requests.
@@ -101,9 +104,10 @@ public class SafeBrowsingTransforms {
* HttpClients#createDefault()}.
*/
@SuppressWarnings("unchecked")
EvaluateSafeBrowsingFn(String apiKey, Retrier retrier) {
EvaluateSafeBrowsingFn(String apiKey, Retrier retrier, Clock clock) {
this.apiKey = apiKey;
this.retrier = retrier;
this.clock = clock;
closeableHttpClientSupplier = (Supplier & Serializable) HttpClients::createDefault;
}
@@ -115,9 +119,10 @@ public class SafeBrowsingTransforms {
*/
@VisibleForTesting
EvaluateSafeBrowsingFn(
String apiKey, Retrier retrier, Supplier<CloseableHttpClient> clientSupplier) {
String apiKey, Retrier retrier, Clock clock, Supplier<CloseableHttpClient> clientSupplier) {
this.apiKey = apiKey;
this.retrier = retrier;
this.clock = clock;
closeableHttpClientSupplier = clientSupplier;
}
@@ -126,7 +131,10 @@ public class SafeBrowsingTransforms {
public void finishBundle(FinishBundleContext context) {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach((kv) -> context.output(kv, Instant.now(), GlobalWindow.INSTANCE));
results.forEach(
(kv) ->
context.output(
kv, DateTimeUtils.toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
}
}
@@ -30,6 +30,7 @@ import google.registry.model.reporting.Spec11ThreatMatch;
import google.registry.model.reporting.Spec11ThreatMatch.ThreatType;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
import google.registry.util.Clock;
import google.registry.util.Retrier;
import google.registry.util.UtilsModule;
import jakarta.inject.Singleton;
@@ -263,8 +264,9 @@ public class Spec11Pipeline implements Serializable {
}
@Provides
EvaluateSafeBrowsingFn provideSafeBrowsingFn(Spec11PipelineOptions options, Retrier retrier) {
return new EvaluateSafeBrowsingFn(options.getSafeBrowsingApiKey(), retrier);
EvaluateSafeBrowsingFn provideSafeBrowsingFn(
Spec11PipelineOptions options, Retrier retrier, Clock clock) {
return new EvaluateSafeBrowsingFn(options.getSafeBrowsingApiKey(), retrier, clock);
}
@Provides
@@ -24,7 +24,6 @@ import static com.google.common.util.concurrent.Futures.transformAsync;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static google.registry.bigquery.BigqueryUtils.toJobReferenceString;
import static google.registry.config.RegistryConfig.getProjectId;
import static org.joda.time.DateTimeZone.UTC;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.AbstractInputStreamContent;
@@ -58,6 +57,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import google.registry.bigquery.BigqueryUtils.DestinationFormat;
import google.registry.bigquery.BigqueryUtils.TableType;
import google.registry.bigquery.BigqueryUtils.WriteDisposition;
import google.registry.util.Clock;
import google.registry.util.NonFinalForTesting;
import google.registry.util.Sleeper;
import google.registry.util.SqlTemplate;
@@ -69,7 +69,6 @@ import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.Duration;
/** Class encapsulating parameters and state for accessing the Bigquery API. */
@@ -94,6 +93,9 @@ public class BigqueryConnection implements AutoCloseable {
/** Bigquery client instance wrapped by this class. */
private final Bigquery bigquery;
/** Clock instance for this connection. */
private final Clock clock;
/** Executor service for bigquery jobs. */
private ListeningExecutorService service;
@@ -109,8 +111,9 @@ public class BigqueryConnection implements AutoCloseable {
/** Duration to wait between polls for job status. */
private Duration pollInterval = Duration.millis(1000);
BigqueryConnection(Bigquery bigquery) {
BigqueryConnection(Bigquery bigquery, Clock clock) {
this.bigquery = bigquery;
this.clock = clock;
}
/** Builder for a {@link BigqueryConnection}, since the latter is immutable once created. */
@@ -118,8 +121,8 @@ public class BigqueryConnection implements AutoCloseable {
private BigqueryConnection instance;
@Inject
Builder(Bigquery bigquery) {
instance = new BigqueryConnection(bigquery);
Builder(Bigquery bigquery, Clock clock) {
instance = new BigqueryConnection(bigquery, clock);
}
/**
@@ -195,6 +198,11 @@ public class BigqueryConnection implements AutoCloseable {
private final TableReference tableRef = new TableReference();
private TableType type = TableType.TABLE;
private WriteDisposition writeDisposition = WriteDisposition.WRITE_EMPTY;
private final Clock clock;
public Builder(Clock clock) {
this.clock = clock;
}
public Builder datasetId(String datasetId) {
tableRef.setDatasetId(datasetId);
@@ -217,7 +225,7 @@ public class BigqueryConnection implements AutoCloseable {
}
public Builder timeToLive(Duration duration) {
this.table.setExpirationTime(DateTime.now(UTC).plus(duration).getMillis());
this.table.setExpirationTime(clock.nowUtc().plus(duration).getMillis());
return this;
}
@@ -302,7 +310,7 @@ public class BigqueryConnection implements AutoCloseable {
/** Returns a partially built DestinationTable with the default dataset and overwrite behavior. */
public DestinationTable.Builder buildDestinationTable(String tableName) {
return new DestinationTable.Builder()
return new DestinationTable.Builder(clock)
.datasetId(datasetId)
.type(TableType.TABLE)
.name(tableName)
@@ -314,7 +322,7 @@ public class BigqueryConnection implements AutoCloseable {
* temporary table dataset, with the default TTL and overwrite behavior.
*/
public DestinationTable.Builder buildTemporaryTable() {
return new DestinationTable.Builder()
return new DestinationTable.Builder(clock)
.datasetId(TEMP_DATASET_NAME)
.type(TableType.TABLE)
.name(getRandomTableName())
@@ -988,6 +988,19 @@ public final class RegistryConfig {
return 100;
}
/**
* Whether to include optional RDAP history results in domain responses.
*
* <p>The RDAP Response Profile (Feb 2024) section 2.3 specifies that while registration and
* expiration events are required, other types are optional. In an effort to reduce database
* load, we (by default) omit the optional events.
*/
@Provides
@Config("rdapIncludeOptionalHistoryResults")
public static boolean provideRdapIncludeOptionalHistoryResults() {
return false;
}
/**
* Maximum QPS for the Google Cloud Monitoring V3 (aka Stackdriver) API. The QPS limit can be
* adjusted by contacting Cloud Support.
@@ -16,6 +16,7 @@ package google.registry.flows;
import static com.google.common.collect.Sets.intersection;
import static google.registry.model.EppResourceUtils.isLinked;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -44,6 +45,7 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.Host;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import java.time.Instant;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -89,6 +91,11 @@ public final class ResourceFlowUtils {
public static <R extends EppResource & ForeignKeyedEppResource> R loadAndVerifyExistence(
Class<R> clazz, String targetId, DateTime now) throws ResourceDoesNotExistException {
return loadAndVerifyExistence(clazz, targetId, toInstant(now));
}
public static <R extends EppResource & ForeignKeyedEppResource> R loadAndVerifyExistence(
Class<R> clazz, String targetId, Instant now) throws ResourceDoesNotExistException {
return verifyExistence(clazz, targetId, ForeignKeyUtils.loadResource(clazz, targetId, now));
}
@@ -197,8 +204,8 @@ public final class ResourceFlowUtils {
*
* @param domain is the domain already projected at approvalTime
*/
public static DateTime computeExDateForApprovalTime(
DomainBase domain, DateTime approvalTime, Period period) {
public static Instant computeExDateForApprovalTime(
DomainBase domain, Instant approvalTime, Period period) {
boolean inAutoRenew = domain.getGracePeriodStatuses().contains(GracePeriodStatus.AUTO_RENEW);
// inAutoRenew is set to false if the period is zero because a zero-period transfer should not
// subsume an autorenew.
@@ -236,7 +236,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
}
// Cancel any grace periods that were still active, and set the expiration time accordingly.
DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime();
DateTime newExpirationTime = existingDomain.getRegistrationExpirationDateTime();
for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) {
// No cancellation is written if the grace period was not for a billable event.
if (gracePeriod.hasBillingEvent()) {
@@ -289,7 +289,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging
flowCustomLogic.beforeResponse(
BeforeResponseParameters.newBuilder()
.setResultCode(
newDomain.getDeletionTime().isAfter(now)
newDomain.getDeletionDateTime().isAfter(now)
? SUCCESS_WITH_ACTION_PENDING
: SUCCESS)
.setResponseExtensions(
@@ -503,7 +503,7 @@ public class DomainFlowUtils {
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId(domain.getDomainName())
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
.setEventTime(domain.getRegistrationExpirationTime());
.setEventTime(domain.getRegistrationExpirationDateTime());
}
/**
@@ -514,7 +514,7 @@ public class DomainFlowUtils {
return new Autorenew.Builder()
.setTargetId(domain.getDomainName())
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setMsg("Domain was auto-renewed.");
}
@@ -658,7 +658,7 @@ public class DomainFlowUtils {
// process, don't count as expired for the purposes of requiring an added year of renewal on
// restore because they can't be restored in the first place.
boolean isExpired =
domain.isPresent() && domain.get().getRegistrationExpirationTime().isBefore(now);
domain.isPresent() && domain.get().getRegistrationExpirationDateTime().isBefore(now);
fees = pricingLogic.getRestorePrice(tld, domainNameString, now, isExpired).getFees();
}
case TRANSFER -> {
@@ -122,8 +122,8 @@ public final class DomainInfoFlow implements MutatingFlow {
.setNameservers(
hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
.setCreationTime(domain.getCreationTime())
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
.setLastEppUpdateTime(domain.getLastEppUpdateDateTime())
.setRegistrationExpirationTime(domain.getRegistrationExpirationDateTime())
.setLastTransferTime(domain.getLastTransferTime());
// If authInfo is non-null, then the caller is authorized to see the full information since we
@@ -191,7 +191,7 @@ public final class DomainRenewFlow implements MutatingFlow {
existingDomain = maybeApplyBulkPricingRemovalToken(existingDomain, allocationToken);
DateTime newExpirationTime =
leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped
leapSafeAddYears(existingDomain.getRegistrationExpirationDateTime(), years); // Uncapped
validateRegistrationPeriod(now, newExpirationTime);
Optional<FeeRenewCommandExtension> feeRenew =
eppInput.getSingleExtension(FeeRenewCommandExtension.class);
@@ -328,8 +328,9 @@ public final class DomainRenewFlow implements MutatingFlow {
// We only allow __REMOVE_BULK_PRICING__ token on bulk pricing domains for now
verifyBulkTokenAllowedOnDomain(existingDomain, allocationToken);
// If the date they specify doesn't match the expiration, fail. (This is an idempotence check).
if (!command.getCurrentExpirationDate().equals(
existingDomain.getRegistrationExpirationTime().toLocalDate())) {
if (!command
.getCurrentExpirationDate()
.equals(existingDomain.getRegistrationExpirationDateTime().toLocalDate())) {
throw new IncorrectCurrentExpirationDateException();
}
}
@@ -138,7 +138,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
Update command = (Update) resourceCommand;
DateTime now = tm().getTransactionTime();
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
boolean isExpired = existingDomain.getRegistrationExpirationTime().isBefore(now);
boolean isExpired = existingDomain.getRegistrationExpirationDateTime().isBefore(now);
FeesAndCredits feesAndCredits =
pricingLogic.getRestorePrice(Tld.get(existingDomain.getTld()), targetId, now, isExpired);
Optional<FeeUpdateCommandExtension> feeUpdate =
@@ -149,7 +149,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow {
ImmutableSet.Builder<ImmutableObject> entitiesToInsert = new ImmutableSet.Builder<>();
DateTime newExpirationTime =
existingDomain.getRegistrationExpirationTime().plusYears(isExpired ? 1 : 0);
existingDomain.getRegistrationExpirationDateTime().plusYears(isExpired ? 1 : 0);
// Restore the expiration time on the deleted domain, except if that's already passed, then add
// a year and bill for it immediately, with no grace period.
if (isExpired) {
@@ -33,6 +33,8 @@ 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_OF_TIME;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -193,7 +195,9 @@ public final class DomainTransferApproveFlow implements MutatingFlow {
updateAutorenewRecurrenceEndTime(
existingDomain, existingBillingRecurrence, now, domainHistoryId);
DateTime newExpirationTime =
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
toDateTime(
computeExDateForApprovalTime(
existingDomain, toInstant(now), transferData.getTransferPeriod()));
// Create a new autorenew event starting at the expiration time.
BillingRecurrence autorenewEvent =
new BillingRecurrence.Builder()
@@ -268,8 +272,11 @@ public final class DomainTransferApproveFlow implements MutatingFlow {
// been implicitly server approved.
tm().delete(existingDomain.getTransferData().getServerApproveEntities());
return responseBuilder
.setResData(createTransferResponse(
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))
.setResData(
createTransferResponse(
targetId,
newDomain.getTransferData(),
newDomain.getRegistrationExpirationDateTime()))
.build();
}
@@ -15,15 +15,17 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.FlowModule.RegistrarId;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.ResourceFlowUtils;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec;
import google.registry.flows.exceptions.NoTransferHistoryToQueryException;
@@ -88,11 +90,12 @@ public final class DomainTransferQueryFlow implements TransactionalFlow {
}
DateTime newExpirationTime = null;
if (transferData.getTransferStatus().isApproved()) {
newExpirationTime = transferData.getTransferredRegistrationExpirationTime();
newExpirationTime = transferData.getTransferredRegistrationExpirationDateTime();
} else if (transferData.getTransferStatus().equals(TransferStatus.PENDING)) {
newExpirationTime =
ResourceFlowUtils.computeExDateForApprovalTime(
domain, now, domain.getTransferData().getTransferPeriod());
toDateTime(
computeExDateForApprovalTime(
domain, toInstant(now), domain.getTransferData().getTransferPeriod()));
}
return responseBuilder
.setResData(createTransferResponse(targetId, transferData, newExpirationTime))
@@ -32,6 +32,7 @@ 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_OF_TIME;
import static google.registry.util.DateTimeUtils.toDateTime;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.EppException;
@@ -53,6 +54,7 @@ import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.tld.Tld;
import google.registry.model.transfer.TransferStatus;
import jakarta.inject.Inject;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -92,7 +94,7 @@ public final class DomainTransferRejectFlow implements MutatingFlow {
extensionManager.register(MetadataExtension.class);
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now);
Tld tld = Tld.get(existingDomain.getTld());
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
@@ -107,13 +109,14 @@ public final class DomainTransferRejectFlow implements MutatingFlow {
checkAllowedAccessToTld(registrarId, existingDomain.getTld());
}
Domain newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, registrarId);
DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now);
denyPendingTransfer(
existingDomain, TransferStatus.CLIENT_REJECTED, toDateTime(now), registrarId);
DomainHistory domainHistory = buildDomainHistory(newDomain, tld, toDateTime(now));
tm().update(newDomain);
tm().insertAll(
domainHistory,
createGainingTransferPollMessage(
targetId, newDomain.getTransferData(), null, now, domainHistoryId));
targetId, newDomain.getTransferData(), null, toDateTime(now), domainHistoryId));
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may end up recreating the poll message if it was deleted upon the transfer request.
BillingRecurrence existingBillingRecurrence =
@@ -35,6 +35,8 @@ 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 google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -80,6 +82,7 @@ import google.registry.model.transfer.DomainTransferData.TransferServerApproveEn
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus;
import jakarta.inject.Inject;
import java.time.Instant;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -230,7 +233,9 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
Domain domainAtTransferTime = existingDomain.cloneProjectedAtTime(automaticTransferTime);
// The new expiration time if there is a server approval.
DateTime serverApproveNewExpirationTime =
computeExDateForApprovalTime(domainAtTransferTime, automaticTransferTime, period);
toDateTime(
computeExDateForApprovalTime(
domainAtTransferTime, toInstant(automaticTransferTime), period));
// Create speculative entities in anticipation of an automatic server approval.
ImmutableSet<TransferServerApproveEntity> serverApproveEntities =
createTransferServerApproveEntities(
@@ -287,7 +292,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
tm().insertAll(domainHistory, requestPollMessage);
return responseBuilder
.setResultFromCode(SUCCESS_WITH_ACTION_PENDING)
.setResData(createResponse(period, existingDomain, newDomain, now))
.setResData(createResponse(period, existingDomain, newDomain, toInstant(now)))
.setExtensions(createResponseExtensions(feesAndCredits, feeTransfer))
.build();
}
@@ -375,14 +380,14 @@ public final class DomainTransferRequestFlow implements MutatingFlow {
}
private DomainTransferResponse createResponse(
Period period, Domain existingDomain, Domain newDomain, DateTime now) {
Period period, Domain existingDomain, Domain newDomain, Instant now) {
// If the registration were approved this instant, this is what the new expiration would be,
// because we cap at 10 years from the moment of approval. This is different from the server
// approval new expiration time, which is capped at 10 years from the server approve time.
DateTime approveNowExtendedRegistrationTime =
Instant approveNowExtendedRegistrationTime =
computeExDateForApprovalTime(existingDomain, now, period);
return createTransferResponse(
targetId, newDomain.getTransferData(), approveNowExtendedRegistrationTime);
targetId, newDomain.getTransferData(), toDateTime(approveNowExtendedRegistrationTime));
}
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
@@ -184,7 +184,7 @@ public final class DomainTransferUtils {
HistoryEntryId domainHistoryId) {
return new PollMessage.OneTime.Builder()
.setRegistrarId(transferData.getGainingRegistrarId())
.setEventTime(transferData.getPendingTransferExpirationTime())
.setEventTime(transferData.getPendingTransferExpirationDateTime())
.setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(
ImmutableList.of(
@@ -206,7 +206,7 @@ public final class DomainTransferUtils {
HistoryEntryId domainHistoryId) {
return new PollMessage.OneTime.Builder()
.setRegistrarId(transferData.getLosingRegistrarId())
.setEventTime(transferData.getPendingTransferExpirationTime())
.setEventTime(transferData.getPendingTransferExpirationDateTime())
.setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(
ImmutableList.of(
@@ -224,7 +224,7 @@ public final class DomainTransferUtils {
.setDomainName(targetId)
.setGainingRegistrarId(transferData.getGainingRegistrarId())
.setLosingRegistrarId(transferData.getLosingRegistrarId())
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationDateTime())
.setTransferRequestTime(transferData.getTransferRequestTime())
.setTransferStatus(transferData.getTransferStatus())
.setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime)
@@ -281,7 +281,7 @@ public final class DomainUpdateFlow implements MutatingFlow {
if (superuserExt.get().getAutorenews().isPresent()) {
boolean autorenews = superuserExt.get().getAutorenews().get();
domainBuilder.setAutorenewEndTime(
Optional.ofNullable(autorenews ? null : domain.getRegistrationExpirationTime()));
Optional.ofNullable(autorenews ? null : domain.getRegistrationExpirationDateTime()));
}
}
return domainBuilder.build();
@@ -99,7 +99,7 @@ public final class HostInfoFlow implements TransactionalFlow {
.setCreationRegistrarId(host.getCreationRegistrarId())
.setCreationTime(host.getCreationTime())
.setLastEppUpdateRegistrarId(host.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(host.getLastEppUpdateTime())
.setLastEppUpdateTime(host.getLastEppUpdateDateTime())
.build())
.build();
}
@@ -14,6 +14,7 @@
package google.registry.keyring;
import com.google.common.collect.ImmutableList;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -21,7 +22,6 @@ import google.registry.config.RegistryConfig.Config;
import google.registry.keyring.api.Keyring;
import google.registry.keyring.secretmanager.SecretManagerKeyring;
import jakarta.inject.Singleton;
import java.util.Optional;
/** Dagger module for {@link Keyring} */
@Module
@@ -38,9 +38,10 @@ public abstract class KeyringModule {
}
@Provides
@Config("cloudSqlReplicaInstanceConnectionName")
public static Optional<String> provideCloudSqlReplicaInstanceConnectionName(Keyring keyring) {
return Optional.ofNullable(keyring.getSqlReplicaConnectionName());
@Config("cloudSqlReplicaInstanceConnectionNames")
public static ImmutableList<String> provideCloudSqlReplicaInstanceConnectionNames(
Keyring keyring) {
return ImmutableList.copyOf(keyring.getSqlReplicaConnectionNames());
}
@Provides
@@ -14,6 +14,7 @@
package google.registry.keyring.api;
import com.google.common.collect.ImmutableList;
import javax.annotation.concurrent.ThreadSafe;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPrivateKey;
@@ -151,9 +152,17 @@ public interface Keyring extends AutoCloseable {
/** Returns the Cloud SQL connection name of the primary database instance. */
String getSqlPrimaryConnectionName();
/** Returns the Cloud SQL connection name of the replica database instance. */
/**
* Returns the Cloud SQL connection name of the replica database instance.
*
* <p>Note: It is likely a better idea to use multiple replicas and {@link
* #getSqlReplicaConnectionNames()} instead.
*/
String getSqlReplicaConnectionName();
/** Returns the Cloud SQL connection names of the replica database instances. */
ImmutableList<String> getSqlReplicaConnectionNames();
// Don't throw so try-with-resources works better.
@Override
void close();
@@ -17,6 +17,8 @@ package google.registry.keyring.secretmanager;
import static com.google.common.base.CaseFormat.LOWER_HYPHEN;
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import google.registry.keyring.api.KeySerializer;
import google.registry.keyring.api.Keyring;
import google.registry.keyring.api.KeyringException;
@@ -66,7 +68,8 @@ public class SecretManagerKeyring implements Keyring {
RDE_SSH_CLIENT_PUBLIC_STRING,
SAFE_BROWSING_API_KEY,
SQL_PRIMARY_CONN_NAME,
SQL_REPLICA_CONN_NAME;
SQL_REPLICA_CONN_NAME,
SQL_REPLICA_CONN_NAMES;
String getLabel() {
return UPPER_UNDERSCORE.to(LOWER_HYPHEN, name());
@@ -157,7 +160,25 @@ public class SecretManagerKeyring implements Keyring {
@Override
public String getSqlReplicaConnectionName() {
return getString(StringKeyLabel.SQL_REPLICA_CONN_NAME);
try {
return getString(StringKeyLabel.SQL_REPLICA_CONN_NAME);
} catch (KeyringException e) {
return null;
}
}
@Override
public ImmutableList<String> getSqlReplicaConnectionNames() {
try {
String names = getString(StringKeyLabel.SQL_REPLICA_CONN_NAMES);
return ImmutableList.copyOf(
Splitter.on('\n').trimResults().omitEmptyStrings().splitToList(names));
} catch (KeyringException e) {
String replicaConnectionName = getSqlReplicaConnectionName();
return replicaConnectionName == null
? ImmutableList.of()
: ImmutableList.of(replicaConnectionName);
}
}
/** No persistent resources are maintained for this Keyring implementation. */
@@ -34,6 +34,7 @@ import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringK
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SAFE_BROWSING_API_KEY;
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SQL_PRIMARY_CONN_NAME;
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SQL_REPLICA_CONN_NAME;
import static google.registry.keyring.secretmanager.SecretManagerKeyring.StringKeyLabel.SQL_REPLICA_CONN_NAMES;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.google.common.flogger.FluentLogger;
@@ -134,6 +135,10 @@ public final class SecretManagerKeyringUpdater {
return setString(name, SQL_REPLICA_CONN_NAME);
}
public SecretManagerKeyringUpdater setSqlReplicaConnectionNames(String names) {
return setString(names, SQL_REPLICA_CONN_NAMES);
}
/**
* Persists the secrets in the Secret Manager.
*
@@ -25,6 +25,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.toInstant;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.LoadingCache;
@@ -45,6 +46,7 @@ import jakarta.persistence.Enumerated;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Transient;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -163,10 +165,15 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
return creationRegistrarId;
}
public DateTime getLastEppUpdateTime() {
@Deprecated
public DateTime getLastEppUpdateDateTime() {
return lastEppUpdateTime;
}
public Instant getLastEppUpdateTime() {
return toInstant(lastEppUpdateTime);
}
public String getLastEppUpdateRegistrarId() {
return lastEppUpdateRegistrarId;
}
@@ -185,13 +192,22 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B
return nullToEmptyImmutableCopy(statuses);
}
public DateTime getDeletionTime() {
@Deprecated
public DateTime getDeletionDateTime() {
return deletionTime;
}
public Instant getDeletionTime() {
return toInstant(deletionTime);
}
/** Return a clone of the resource with timed status values modified using the given time. */
@Deprecated
public abstract EppResource cloneProjectedAtTime(DateTime now);
/** Return a clone of the resource with timed status values modified using the given time. */
public abstract EppResource cloneProjectedAtInstant(Instant now);
/** Get the foreign key string for this resource. */
public abstract String getForeignKey();
@@ -34,6 +34,7 @@ import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import jakarta.persistence.Query;
import java.time.Instant;
import java.util.Comparator;
import java.util.function.Function;
import javax.annotation.Nullable;
@@ -83,7 +84,7 @@ public final class EppResourceUtils {
* exclusive, which happily maps to the behavior of Interval.
*/
private static Interval getLifetime(EppResource resource) {
return new Interval(resource.getCreationTime(), resource.getDeletionTime());
return new Interval(resource.getCreationTime(), resource.getDeletionDateTime());
}
public static boolean isActive(EppResource resource, DateTime time) {
@@ -108,7 +109,7 @@ public final class EppResourceUtils {
builder
.removeStatusValue(StatusValue.PENDING_TRANSFER)
.setTransferData(transferDataBuilder.build())
.setLastTransferTime(transferData.getPendingTransferExpirationTime())
.setLastTransferTime(transferData.getPendingTransferExpirationDateTime())
.setPersistedCurrentSponsorRegistrarId(transferData.getGainingRegistrarId());
}
@@ -120,10 +121,10 @@ public final class EppResourceUtils {
* </ul>
*/
public static void projectResourceOntoBuilderAtTime(
DomainBase domain, DomainBase.Builder<?, ?> builder, DateTime now) {
DomainBase domain, DomainBase.Builder<?, ?> builder, Instant now) {
DomainTransferData transferData = domain.getTransferData();
// If there's a pending transfer that has expired, process it.
DateTime expirationTime = transferData.getPendingTransferExpirationTime();
Instant expirationTime = transferData.getPendingTransferExpirationTime();
if (TransferStatus.PENDING.equals(transferData.getTransferStatus())
&& isBeforeOrAt(expirationTime, now)) {
setAutomaticTransferSuccessProperties(builder, transferData);
@@ -35,6 +35,7 @@ import google.registry.persistence.VKey;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.util.NonFinalForTesting;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
@@ -81,6 +82,7 @@ public final class ForeignKeyUtils {
* <p>Returns null if no resource with this foreign key was ever created or if the most recently
* created resource was deleted before time "now".
*/
@Deprecated
public static <E extends EppResource> Optional<E> loadResource(
Class<E> clazz, String foreignKey, DateTime now) {
// Note: no need to project to "now" because loadResources already does
@@ -88,6 +90,19 @@ public final class ForeignKeyUtils {
loadResources(clazz, ImmutableList.of(foreignKey), now).get(foreignKey));
}
/**
* Loads an {@link EppResource} from the database by foreign key.
*
* <p>Returns null if no resource with this foreign key was ever created or if the most recently
* created resource was deleted before time "now".
*/
public static <E extends EppResource> Optional<E> loadResource(
Class<E> clazz, String foreignKey, Instant now) {
// Note: no need to project to "now" because loadResources already does
return Optional.ofNullable(
loadResources(clazz, ImmutableList.of(foreignKey), now).get(foreignKey));
}
/**
* Load a map of {@link String} foreign keys to {@link VKey}s to {@link EppResource} that are
* active at or after the specified moment in time.
@@ -110,13 +125,29 @@ public final class ForeignKeyUtils {
* or has been soft-deleted.
*/
@SuppressWarnings("unchecked")
@Deprecated
public static <E extends EppResource> ImmutableMap<String, E> loadResources(
Class<E> clazz, Collection<String> foreignKeys, DateTime now) {
return loadMostRecentResourceObjects(clazz, foreignKeys, false).entrySet().stream()
.filter(e -> now.isBefore(e.getValue().getDeletionTime()))
.filter(e -> now.isBefore(e.getValue().getDeletionDateTime()))
.collect(toImmutableMap(Entry::getKey, e -> (E) e.getValue().cloneProjectedAtTime(now)));
}
/**
* Load a map of {@link String} foreign keys to the {@link EppResource} that are active at or
* after the specified moment in time.
*
* <p>The returned map will omit any foreign keys for which the {@link EppResource} doesn't exist
* or has been soft-deleted.
*/
@SuppressWarnings("unchecked")
public static <E extends EppResource> ImmutableMap<String, E> loadResources(
Class<E> clazz, Collection<String> foreignKeys, Instant now) {
return loadMostRecentResourceObjects(clazz, foreignKeys, false).entrySet().stream()
.filter(e -> now.isBefore(e.getValue().getDeletionTime()))
.collect(toImmutableMap(Entry::getKey, e -> (E) e.getValue().cloneProjectedAtInstant(now)));
}
/**
* Helper method to load {@link VKey}s to all the most recent {@link EppResource}s for the given
* foreign keys, regardless of whether they have been soft-deleted.
@@ -397,7 +428,7 @@ public final class ForeignKeyUtils {
return (Optional<E>)
foreignKeyToResourceCache
.get(VKey.create(clazz, foreignKey))
.filter(e -> now.isBefore(e.getDeletionTime()))
.filter(e -> now.isBefore(e.getDeletionDateTime()))
.map(e -> e.cloneProjectedAtTime(now));
}
}
@@ -50,11 +50,11 @@ public final class ResourceTransferUtils {
.setDomainName(domain.getForeignKey())
.setExtendedRegistrationExpirationTime(
ADD_EXDATE_STATUSES.contains(transferData.getTransferStatus())
? transferData.getTransferredRegistrationExpirationTime()
? transferData.getTransferredRegistrationExpirationDateTime()
: null)
.setGainingRegistrarId(transferData.getGainingRegistrarId())
.setLosingRegistrarId(transferData.getLosingRegistrarId())
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationDateTime())
.setTransferRequestTime(transferData.getTransferRequestTime())
.setTransferStatus(transferData.getTransferStatus())
.build();
@@ -104,7 +104,7 @@ public class BillingCancellation extends BillingBase {
.setRegistrarId(gracePeriod.getRegistrarId())
.setEventTime(eventTime)
// The charge being cancelled will take place at the grace period's expiration time.
.setBillingTime(gracePeriod.getExpirationTime())
.setBillingTime(gracePeriod.getExpirationDateTime())
.setDomainHistoryId(domainHistoryId);
// Set the grace period's billing event using the appropriate Cancellation builder method.
if (gracePeriod.getBillingEvent() != null) {
@@ -14,6 +14,8 @@
package google.registry.model.domain;
import static google.registry.util.DateTimeUtils.toInstant;
import google.registry.model.EppResource;
import google.registry.model.EppResource.ForeignKeyedEppResource;
import google.registry.model.annotations.ExternalMessagingName;
@@ -37,6 +39,7 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.time.Instant;
import java.util.Set;
import org.hibernate.Hibernate;
import org.joda.time.DateTime;
@@ -153,6 +156,11 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
@Override
public Domain cloneProjectedAtTime(final DateTime now) {
return cloneDomainProjectedAtTime(this, toInstant(now));
}
@Override
public Domain cloneProjectedAtInstant(final Instant now) {
return cloneDomainProjectedAtTime(this, now);
}
@@ -32,9 +32,14 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.earliestOf;
import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static google.registry.util.DomainNameUtils.getTldFromDomainName;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.time.ZoneOffset.UTC;
import static java.time.temporal.ChronoUnit.YEARS;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
@@ -79,13 +84,13 @@ import jakarta.persistence.Enumerated;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Transient;
import java.time.Instant;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.hibernate.collection.spi.PersistentSet;
import org.joda.time.DateTime;
import org.joda.time.Interval;
/**
* A persistable domain resource including mutable and non-mutable fields.
@@ -285,10 +290,15 @@ public class DomainBase extends EppResource {
return nullToEmptyImmutableCopy(subordinateHosts);
}
public DateTime getRegistrationExpirationTime() {
@Deprecated
public DateTime getRegistrationExpirationDateTime() {
return registrationExpirationTime;
}
public Instant getRegistrationExpirationTime() {
return toInstant(registrationExpirationTime);
}
public VKey<OneTime> getDeletePollMessage() {
return deletePollMessage;
}
@@ -436,6 +446,11 @@ public class DomainBase extends EppResource {
@Override
public DomainBase cloneProjectedAtTime(final DateTime now) {
return cloneDomainProjectedAtTime(this, toInstant(now));
}
@Override
public DomainBase cloneProjectedAtInstant(final Instant now) {
return cloneDomainProjectedAtTime(this, now);
}
@@ -444,9 +459,9 @@ public class DomainBase extends EppResource {
* parallels the logic in {@code DomainTransferApproveFlow} which handles explicit client
* approvals.
*/
static <T extends DomainBase> T cloneDomainProjectedAtTime(T domain, DateTime now) {
static <T extends DomainBase> T cloneDomainProjectedAtTime(T domain, Instant now) {
DomainTransferData transferData = domain.getTransferData();
DateTime transferExpirationTime = transferData.getPendingTransferExpirationTime();
Instant transferExpirationTime = transferData.getPendingTransferExpirationTime();
// If there's a pending transfer that has expired, handle it.
if (TransferStatus.PENDING.equals(transferData.getTransferStatus())
@@ -459,7 +474,7 @@ public class DomainBase extends EppResource {
T domainAtTransferTime =
cloneDomainProjectedAtTime(domain, transferExpirationTime.minusMillis(1));
DateTime expirationDate = transferData.getTransferredRegistrationExpirationTime();
Instant expirationDate = transferData.getTransferredRegistrationExpirationTime();
if (expirationDate == null) {
// Extend the registration by the correct number of years from the expiration time
// that was current on the domain right before the transfer, capped at 10 years from
@@ -478,7 +493,7 @@ public class DomainBase extends EppResource {
Builder builder =
domainAtTransferTime
.asBuilder()
.setRegistrationExpirationTime(expirationDate)
.setRegistrationExpirationTime(toDateTime(expirationDate))
// Set the speculatively-written new autorenew events as the domain's autorenew
// events.
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent())
@@ -492,8 +507,8 @@ public class DomainBase extends EppResource {
GracePeriod.create(
GracePeriodStatus.TRANSFER,
domain.getRepoId(),
transferExpirationTime.plus(
Tld.get(domain.getTld()).getTransferGracePeriodLength()),
toDateTime(transferExpirationTime)
.plus(Tld.get(domain.getTld()).getTransferGracePeriodLength()),
transferData.getGainingRegistrarId(),
transferData.getServerApproveBillingEvent())));
} else {
@@ -503,32 +518,33 @@ public class DomainBase extends EppResource {
// Set all remaining transfer properties.
setAutomaticTransferSuccessProperties(builder, transferData);
builder
.setLastEppUpdateTime(transferExpirationTime)
.setLastEppUpdateTime(toDateTime(transferExpirationTime))
.setLastEppUpdateRegistrarId(transferData.getGainingRegistrarId());
// Finish projecting to now.
return (T) builder.build().cloneProjectedAtTime(now);
return (T) builder.build().cloneProjectedAtInstant(now);
}
Optional<DateTime> newLastEppUpdateTime = Optional.empty();
Optional<Instant> newLastEppUpdateTime = Optional.empty();
// There is no transfer. Do any necessary autorenews for active domains.
Builder builder = domain.asBuilder();
if (isBeforeOrAt(domain.getRegistrationExpirationTime(), now)
&& END_OF_TIME.equals(domain.getDeletionTime())) {
&& END_OF_TIME.equals(domain.getDeletionDateTime())) {
// Autorenew by the number of years between the old expiration time and now.
DateTime lastAutorenewTime =
Instant lastAutorenewTime =
leapSafeAddYears(
domain.getRegistrationExpirationTime(),
new Interval(domain.getRegistrationExpirationTime(), now).toPeriod().getYears());
DateTime newExpirationTime = lastAutorenewTime.plusYears(1);
YEARS.between(domain.getRegistrationExpirationTime().atZone(UTC), now.atZone(UTC)));
Instant newExpirationTime = plusYears(lastAutorenewTime, 1);
builder
.setRegistrationExpirationTime(newExpirationTime)
.setRegistrationExpirationTime(toDateTime(newExpirationTime))
.addGracePeriod(
GracePeriod.createForRecurrence(
GracePeriodStatus.AUTO_RENEW,
domain.getRepoId(),
lastAutorenewTime.plus(Tld.get(domain.getTld()).getAutoRenewGracePeriodLength()),
toDateTime(lastAutorenewTime)
.plus(Tld.get(domain.getTld()).getAutoRenewGracePeriodLength()),
domain.getCurrentSponsorRegistrarId(),
domain.getAutorenewBillingEvent()));
newLastEppUpdateTime = Optional.of(lastAutorenewTime);
@@ -551,10 +567,10 @@ public class DomainBase extends EppResource {
// id, so we have to do the comparison instead of having one variable just storing the most
// recent time.
if (newLastEppUpdateTime.isPresent()) {
if (domain.getLastEppUpdateTime() == null
if (domain.getLastEppUpdateDateTime() == null
|| newLastEppUpdateTime.get().isAfter(domain.getLastEppUpdateTime())) {
builder
.setLastEppUpdateTime(newLastEppUpdateTime.get())
.setLastEppUpdateTime(toDateTime(newLastEppUpdateTime.get()))
.setLastEppUpdateRegistrarId(domain.getCurrentSponsorRegistrarId());
}
}
@@ -567,8 +583,8 @@ public class DomainBase extends EppResource {
}
/** Return what the expiration time would be if the given number of years were added to it. */
public static DateTime extendRegistrationWithCap(
DateTime now, DateTime currentExpirationTime, @Nullable Integer extendedRegistrationYears) {
public static Instant extendRegistrationWithCap(
Instant now, Instant currentExpirationTime, @Nullable Integer extendedRegistrationYears) {
// We must cap registration at the max years (aka 10), even if that truncates the last year.
return earliestOf(
leapSafeAddYears(
@@ -826,16 +842,16 @@ public class DomainBase extends EppResource {
.setDomainName(domainBase.getDomainName())
.setDeletePollMessage(domainBase.getDeletePollMessage())
.setDsData(domainBase.getDsData())
.setDeletionTime(domainBase.getDeletionTime())
.setDeletionTime(domainBase.getDeletionDateTime())
.setGracePeriods(domainBase.getGracePeriods())
.setIdnTableName(domainBase.getIdnTableName())
.setLastTransferTime(domainBase.getLastTransferTime())
.setLaunchNotice(domainBase.getLaunchNotice())
.setLastEppUpdateRegistrarId(domainBase.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(domainBase.getLastEppUpdateTime())
.setLastEppUpdateTime(domainBase.getLastEppUpdateDateTime())
.setNameservers(domainBase.getNameservers())
.setPersistedCurrentSponsorRegistrarId(domainBase.getPersistedCurrentSponsorRegistrarId())
.setRegistrationExpirationTime(domainBase.getRegistrationExpirationTime())
.setRegistrationExpirationTime(domainBase.getRegistrationExpirationDateTime())
.setRepoId(domainBase.getRepoId())
.setSmdId(domainBase.getSmdId())
.setSubordinateHosts(domainBase.getSubordinateHosts())
@@ -14,6 +14,8 @@
package google.registry.model.domain;
import static google.registry.util.DateTimeUtils.toInstant;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
import google.registry.model.billing.BillingEvent;
@@ -30,6 +32,7 @@ import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Transient;
import java.time.Instant;
import org.joda.time.DateTime;
/** Base class containing common fields and methods for {@link GracePeriod}. */
@@ -90,10 +93,15 @@ public class GracePeriodBase extends ImmutableObject implements UnsafeSerializab
return domainRepoId;
}
public DateTime getExpirationTime() {
@Deprecated
public DateTime getExpirationDateTime() {
return expirationTime;
}
public Instant getExpirationTime() {
return toInstant(expirationTime);
}
public String getRegistrarId() {
return clientId;
}
@@ -14,7 +14,6 @@
package google.registry.model.eppcommon;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.annotations.VisibleForTesting;
@@ -28,7 +27,6 @@ import google.registry.model.domain.fee06.FeeInfoResponseExtensionV06;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppoutput.EppOutput;
import google.registry.model.eppoutput.EppResponse;
import google.registry.util.RegistryEnvironment;
import google.registry.xml.ValidationMode;
import google.registry.xml.XmlException;
import google.registry.xml.XmlTransformer;
@@ -71,13 +69,9 @@ public class EppXmlTransformer {
private static final XmlTransformer OUTPUT_TRANSFORMER =
new XmlTransformer(getSchemas(), EppOutput.class);
// TODO(b/159033801): remove method and inline ALL_SCHEMA.
@VisibleForTesting
public static ImmutableList<String> getSchemas() {
if (RegistryEnvironment.get().equals(RegistryEnvironment.PRODUCTION)) {
return ALL_SCHEMAS.stream()
.filter(s -> !NON_PROD_SCHEMAS.contains(s))
.collect(toImmutableList());
}
return ALL_SCHEMAS;
}
@@ -33,6 +33,7 @@ import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.MappedSuperclass;
import java.net.InetAddress;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
@@ -132,6 +133,11 @@ public class HostBase extends EppResource {
return this;
}
@Override
public EppResource cloneProjectedAtInstant(Instant now) {
return this;
}
@Override
public Builder<? extends HostBase, ?> asBuilder() {
return new Builder<>(clone(this));
@@ -232,13 +238,13 @@ public class HostBase extends EppResource {
public B copyFrom(HostBase hostBase) {
return setCreationRegistrarId(hostBase.getCreationRegistrarId())
.setCreationTime(hostBase.getCreationTime())
.setDeletionTime(hostBase.getDeletionTime())
.setDeletionTime(hostBase.getDeletionDateTime())
.setHostName(hostBase.getHostName())
.setInetAddresses(hostBase.getInetAddresses())
.setLastTransferTime(hostBase.getLastTransferTime())
.setLastSuperordinateChange(hostBase.getLastSuperordinateChange())
.setLastEppUpdateRegistrarId(hostBase.getLastEppUpdateRegistrarId())
.setLastEppUpdateTime(hostBase.getLastEppUpdateTime())
.setLastEppUpdateTime(hostBase.getLastEppUpdateDateTime())
.setPersistedCurrentSponsorRegistrarId(hostBase.getPersistedCurrentSponsorRegistrarId())
.setRepoId(hostBase.getRepoId())
.setSuperordinateDomain(hostBase.getSuperordinateDomain())
@@ -437,7 +437,7 @@ public abstract class PollMessage extends ImmutableObject
.setTransferStatus(transferResponse.getTransferStatus())
.setTransferRequestTime(transferResponse.getTransferRequestTime())
.setPendingTransferExpirationTime(
transferResponse.getPendingTransferExpirationTime())
transferResponse.getPendingTransferExpirationDateTime())
.setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime)
.build();
}
@@ -129,34 +129,31 @@ public final class PremiumListDao {
public static PremiumList save(String name, CurrencyUnit currencyUnit, List<String> inputData) {
checkArgument(!inputData.isEmpty(), "New premium list data cannot be empty");
return save(PremiumListUtils.parseToPremiumList(name, currencyUnit, inputData));
tm().assertInTransaction();
return save(
PremiumListUtils.parseToPremiumList(
name, currencyUnit, inputData, tm().getTransactionTime()));
}
/** Saves the given premium list (and its premium list entries) to Cloud SQL. */
public static PremiumList save(PremiumList premiumListToPersist) {
PremiumList persisted =
tm().transact(
() -> {
// Make a new copy in each attempt to insert. See javadoc of the insert method for
// more information.
PremiumList premiumList = premiumListToPersist.asBuilder().build();
tm().insert(premiumList);
tm().getEntityManager().flush(); // This populates the revisionId.
long revisionId = premiumList.getRevisionId();
tm().assertInTransaction();
// Make a new copy in each attempt to insert. See javadoc of the insert method for
// more information.
PremiumList premiumList = premiumListToPersist.asBuilder().build();
tm().insert(premiumList);
tm().getEntityManager().flush(); // This populates the revisionId.
long revisionId = premiumList.getRevisionId();
if (!isNullOrEmpty(premiumList.getLabelsToPrices())) {
ImmutableSet.Builder<PremiumEntry> entries = new ImmutableSet.Builder<>();
premiumList
.getLabelsToPrices()
.forEach(
(key, value) ->
entries.add(PremiumEntry.create(revisionId, value, key)));
tm().insertAll(entries.build());
}
return premiumList;
});
premiumListCache.invalidate(persisted.getName());
return persisted;
if (!isNullOrEmpty(premiumList.getLabelsToPrices())) {
ImmutableSet.Builder<PremiumEntry> entries = new ImmutableSet.Builder<>();
premiumList
.getLabelsToPrices()
.forEach((key, value) -> entries.add(PremiumEntry.create(revisionId, value, key)));
tm().insertAll(entries.build());
}
premiumListCache.invalidate(premiumList.getName());
return premiumList;
}
public static void delete(PremiumList premiumList) {
@@ -14,8 +14,6 @@
package google.registry.model.tld.label;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import google.registry.model.tld.label.PremiumList.PremiumEntry;
@@ -29,12 +27,12 @@ import org.joda.time.DateTime;
public class PremiumListUtils {
public static PremiumList parseToPremiumList(
String name, CurrencyUnit currencyUnit, List<String> inputData) {
String name, CurrencyUnit currencyUnit, List<String> inputData, DateTime creationTime) {
PremiumList partialPremiumList =
new PremiumList.Builder()
.setName(name)
.setCurrency(currencyUnit)
.setCreationTimestamp(DateTime.now(UTC))
.setCreationTimestamp(creationTime)
.build();
ImmutableMap<String, PremiumEntry> prices = partialPremiumList.parse(inputData);
Map<String, BigDecimal> priceAmounts = Maps.transformValues(prices, PremiumEntry::getValue);
@@ -24,10 +24,10 @@ import static google.registry.model.tld.label.ReservationType.FULLY_BLOCKED;
import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static org.joda.time.DateTimeZone.UTC;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.UncheckedExecutionException;
@@ -47,7 +47,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/**
* A list of reserved domain labels that are blocked from being registered for various reasons.
@@ -234,7 +233,7 @@ public final class ReservedList
*/
private static ImmutableSet<ReservedListEntry> getReservedListEntries(
String label, String tldStr) {
DateTime startTime = DateTime.now(UTC);
Stopwatch stopwatch = Stopwatch.createStarted();
Tld tld = Tld.get(checkNotNull(tldStr, "tld must not be null"));
ImmutableSet.Builder<ReservedListEntry> entriesBuilder = new ImmutableSet.Builder<>();
ImmutableSet.Builder<MetricsReservedListMatch> metricMatchesBuilder =
@@ -251,9 +250,7 @@ public final class ReservedList
}
ImmutableSet<ReservedListEntry> entries = entriesBuilder.build();
DomainLabelMetrics.recordReservedListCheckOutcome(
tldStr,
metricMatchesBuilder.build(),
DateTime.now(UTC).getMillis() - startTime.getMillis());
tldStr, metricMatchesBuilder.build(), stopwatch.elapsed().toMillis());
return entries;
}
@@ -14,6 +14,8 @@
package google.registry.model.transfer;
import static google.registry.util.DateTimeUtils.toInstant;
import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject;
import google.registry.model.UnsafeSerializable;
@@ -23,6 +25,7 @@ import jakarta.persistence.Enumerated;
import jakarta.persistence.MappedSuperclass;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlTransient;
import java.time.Instant;
import org.joda.time.DateTime;
/** Fields common to {@link DomainTransferData} and {@link TransferResponse}. */
@@ -73,10 +76,15 @@ public abstract class BaseTransferObject extends ImmutableObject implements Unsa
return losingClientId;
}
public DateTime getPendingTransferExpirationTime() {
@Deprecated
public DateTime getPendingTransferExpirationDateTime() {
return pendingTransferExpirationTime;
}
public Instant getPendingTransferExpirationTime() {
return toInstant(pendingTransferExpirationTime);
}
/** Base class for builders of {@link BaseTransferObject} subclasses. */
public abstract static class Builder<T extends BaseTransferObject, B extends Builder<?, ?>>
extends GenericBuilder<T, B> {
@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.DateTimeUtils.toInstant;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -41,6 +42,7 @@ import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import java.time.Instant;
import java.util.Set;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
@@ -168,10 +170,16 @@ public class DomainTransferData extends BaseTransferObject implements Buildable
}
@Nullable
public DateTime getTransferredRegistrationExpirationTime() {
@Deprecated
public DateTime getTransferredRegistrationExpirationDateTime() {
return transferredRegistrationExpirationTime;
}
@Nullable
public Instant getTransferredRegistrationExpirationTime() {
return toInstant(transferredRegistrationExpirationTime);
}
@Nullable
public VKey<BillingEvent> getServerApproveBillingEvent() {
return serverApproveBillingEvent;
@@ -15,6 +15,7 @@
package google.registry.persistence;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.config.RegistryConfig.getHibernateConnectionIsolation;
import static google.registry.config.RegistryConfig.getHibernateHikariConnectionTimeout;
import static google.registry.config.RegistryConfig.getHibernateHikariIdleTimeout;
@@ -28,6 +29,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import dagger.BindsOptionalOf;
@@ -36,6 +38,7 @@ import dagger.Module;
import dagger.Provides;
import google.registry.config.RegistryConfig.Config;
import google.registry.persistence.transaction.CloudSqlCredentialSupplier;
import google.registry.persistence.transaction.DelegatingReplicaJpaTransactionManager;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.persistence.transaction.JpaTransactionManagerImpl;
import google.registry.persistence.transaction.TransactionManager;
@@ -59,6 +62,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Random;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.hibernate.cfg.Environment;
@@ -264,16 +268,13 @@ public abstract class PersistenceModule {
static JpaTransactionManager provideReadOnlyReplicaJpaTm(
SqlCredentialStore credentialStore,
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
@Config("cloudSqlReplicaInstanceConnectionName")
Optional<String> replicaInstanceConnectionName,
Clock clock) {
@Config("cloudSqlReplicaInstanceConnectionNames")
ImmutableList<String> replicaInstanceConnectionNames,
Clock clock,
Random random) {
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
setSqlCredential(credentialStore, new RobotUser(RobotId.NOMULUS), overrides);
replicaInstanceConnectionName.ifPresent(
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
overrides.put(
Environment.ISOLATION, TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ.name());
return new JpaTransactionManagerImpl(create(overrides), clock, true);
return createReplicaJpaTm(overrides, replicaInstanceConnectionNames, clock, random);
}
@Provides
@@ -281,15 +282,34 @@ public abstract class PersistenceModule {
@BeamReadOnlyReplicaJpaTm
static JpaTransactionManager provideBeamReadOnlyReplicaJpaTm(
@BeamPipelineCloudSqlConfigs ImmutableMap<String, String> beamCloudSqlConfigs,
@Config("cloudSqlReplicaInstanceConnectionName")
Optional<String> replicaInstanceConnectionName,
Clock clock) {
@Config("cloudSqlReplicaInstanceConnectionNames")
ImmutableList<String> replicaInstanceConnectionNames,
Clock clock,
Random random) {
HashMap<String, String> overrides = Maps.newHashMap(beamCloudSqlConfigs);
replicaInstanceConnectionName.ifPresent(
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
overrides.put(
return createReplicaJpaTm(overrides, replicaInstanceConnectionNames, clock, random);
}
private static JpaTransactionManager createReplicaJpaTm(
Map<String, String> baseOverrides,
ImmutableList<String> replicaInstanceConnectionNames,
Clock clock,
Random random) {
baseOverrides.put(
Environment.ISOLATION, TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ.name());
return new JpaTransactionManagerImpl(create(overrides), clock, true);
if (replicaInstanceConnectionNames.isEmpty()) {
return new JpaTransactionManagerImpl(create(baseOverrides), clock, true);
}
ImmutableList<JpaTransactionManager> replicas =
replicaInstanceConnectionNames.stream()
.map(
name -> {
HashMap<String, String> overrides = Maps.newHashMap(baseOverrides);
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name);
return new JpaTransactionManagerImpl(create(overrides), clock, true);
})
.collect(toImmutableList());
return new DelegatingReplicaJpaTransactionManager(replicas, random);
}
/** Constructs the {@link EntityManagerFactory} instance. */
@@ -0,0 +1,361 @@
// 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.persistence.transaction;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import google.registry.model.ImmutableObject;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.metamodel.Metamodel;
import java.time.Instant;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.stream.Stream;
import org.joda.time.DateTime;
/**
* A {@link JpaTransactionManager} that load-balances across multiple read-only replicas.
*
* <p>For each top-level transaction, one replica is chosen and used for the duration of the
* transaction. For non-transactional methods, a replica is chosen for each call.
*/
public class DelegatingReplicaJpaTransactionManager implements JpaTransactionManager {
private final ImmutableList<JpaTransactionManager> replicas;
private final Random random;
private static final AtomicLong nextId = new AtomicLong(1);
private static final ThreadLocal<JpaTransactionManager> activeReplica = new ThreadLocal<>();
public DelegatingReplicaJpaTransactionManager(
ImmutableList<JpaTransactionManager> replicas, Random random) {
checkArgument(!replicas.isEmpty(), "At least one replica must be provided");
this.replicas = replicas;
this.random = random;
}
private JpaTransactionManager getReplica() {
JpaTransactionManager replica = activeReplica.get();
if (replica != null) {
return replica;
}
return getRandomReplica();
}
private <T> T runMaybeAssigningReplica(Function<JpaTransactionManager, T> work) {
JpaTransactionManager existing = activeReplica.get();
if (existing != null) {
return work.apply(existing);
}
JpaTransactionManager replica = getRandomReplica();
activeReplica.set(replica);
try {
return work.apply(replica);
} finally {
activeReplica.remove();
}
}
private JpaTransactionManager getRandomReplica() {
return replicas.get(random.nextInt(replicas.size()));
}
@Override
public boolean inTransaction() {
var replica = activeReplica.get();
return replica != null && replica.inTransaction();
}
@Override
public void assertInTransaction() {
JpaTransactionManager replica = activeReplica.get();
if (replica == null) {
throw new IllegalStateException("Not in a transaction");
}
replica.assertInTransaction();
}
@Override
public long allocateId() {
return nextId.getAndIncrement();
}
@Override
public <T> T transact(Callable<T> work) {
return transact(null, work, false);
}
@Override
public <T> T transact(TransactionIsolationLevel isolationLevel, Callable<T> work) {
return transact(isolationLevel, work, false);
}
@Override
public <T> T transactNoRetry(Callable<T> work) {
return transactNoRetry(null, work, false);
}
@Override
public <T> T transactNoRetry(TransactionIsolationLevel isolationLevel, Callable<T> work) {
return transactNoRetry(isolationLevel, work, false);
}
@Override
public <T> T reTransact(Callable<T> work) {
return runMaybeAssigningReplica(replica -> replica.reTransact(work));
}
@Override
public void transact(ThrowingRunnable work) {
transact(
() -> {
work.run();
return null;
});
}
@Override
public void transact(TransactionIsolationLevel isolationLevel, ThrowingRunnable work) {
transact(
isolationLevel,
() -> {
work.run();
return null;
});
}
@Override
public void reTransact(ThrowingRunnable work) {
reTransact(
() -> {
work.run();
return null;
});
}
@Override
public DateTime getTransactionTime() {
return getReplica().getTransactionTime();
}
@Override
public Instant getTxTime() {
return getReplica().getTxTime();
}
@Override
public void insert(Object entity) {
getReplica().insert(entity);
}
@Override
public void insertAll(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void insertAll(ImmutableObject... entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void put(Object entity) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void putAll(ImmutableObject... entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void putAll(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void update(Object entity) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void updateAll(ImmutableCollection<?> entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void updateAll(ImmutableObject... entities) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public boolean exists(Object entity) {
return getReplica().exists(entity);
}
@Override
public <T> boolean exists(VKey<T> key) {
return getReplica().exists(key);
}
@Override
public <T> Optional<T> loadByKeyIfPresent(VKey<T> key) {
return getReplica().loadByKeyIfPresent(key);
}
@Override
public <T> ImmutableMap<VKey<? extends T>, T> loadByKeysIfPresent(
Iterable<? extends VKey<? extends T>> keys) {
return getReplica().loadByKeysIfPresent(keys);
}
@Override
public <T> ImmutableList<T> loadByEntitiesIfPresent(Iterable<T> entities) {
return getReplica().loadByEntitiesIfPresent(entities);
}
@Override
public <T> T loadByKey(VKey<T> key) {
return getReplica().loadByKey(key);
}
@Override
public <T> ImmutableMap<VKey<? extends T>, T> loadByKeys(
Iterable<? extends VKey<? extends T>> keys) {
return getReplica().loadByKeys(keys);
}
@Override
public <T> T loadByEntity(T entity) {
return getReplica().loadByEntity(entity);
}
@Override
public <T> ImmutableList<T> loadByEntities(Iterable<T> entities) {
return getReplica().loadByEntities(entities);
}
@Override
public <T> ImmutableList<T> loadAllOf(Class<T> clazz) {
return getReplica().loadAllOf(clazz);
}
@Override
public <T> Stream<T> loadAllOfStream(Class<T> clazz) {
return getReplica().loadAllOfStream(clazz);
}
@Override
public <T> Optional<T> loadSingleton(Class<T> clazz) {
return getReplica().loadSingleton(clazz);
}
@Override
public void delete(VKey<?> key) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void delete(Iterable<? extends VKey<?>> keys) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public <T> T delete(T entity) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public <T> QueryComposer<T> createQueryComposer(Class<T> entity) {
return getReplica().createQueryComposer(entity);
}
@Override
public EntityManager getStandaloneEntityManager() {
return getReplica().getStandaloneEntityManager();
}
@Override
public Metamodel getMetaModel() {
return getReplica().getMetaModel();
}
@Override
public EntityManager getEntityManager() {
return getReplica().getEntityManager();
}
@Override
public <T> TypedQuery<T> query(String sqlString, Class<T> resultClass) {
return getReplica().query(sqlString, resultClass);
}
@Override
public <T> TypedQuery<T> criteriaQuery(CriteriaQuery<T> criteriaQuery) {
return getReplica().criteriaQuery(criteriaQuery);
}
@Override
public Query query(String sqlString) {
return getReplica().query(sqlString);
}
@Override
public <T> void assertDelete(VKey<T> key) {
throw new UnsupportedOperationException("This is a replica database");
}
@Override
public void teardown() {
for (JpaTransactionManager replica : replicas) {
replica.teardown();
}
}
@Override
public TransactionIsolationLevel getDefaultTransactionIsolationLevel() {
return replicas.get(0).getDefaultTransactionIsolationLevel();
}
@Override
public TransactionIsolationLevel getCurrentTransactionIsolationLevel() {
return getReplica().getCurrentTransactionIsolationLevel();
}
@Override
public <T> T transact(
TransactionIsolationLevel isolationLevel, Callable<T> work, boolean logSqlStatements) {
return runMaybeAssigningReplica(
replica -> replica.transact(isolationLevel, work, logSqlStatements));
}
@Override
public <T> T transactNoRetry(
TransactionIsolationLevel isolationLevel, Callable<T> work, boolean logSqlStatements) {
return runMaybeAssigningReplica(
replica -> replica.transactNoRetry(isolationLevel, work, logSqlStatements));
}
}
@@ -21,6 +21,7 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.config.RegistryConfig.getHibernateAllowNestedTransactions;
import static google.registry.persistence.transaction.DatabaseException.throwIfSqlException;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.joining;
@@ -61,6 +62,7 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Instant;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
@@ -340,6 +342,11 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
@Override
public DateTime getTransactionTime() {
return toDateTime(getTxTime());
}
@Override
public Instant getTxTime() {
assertInTransaction();
TransactionInfo txnInfo = transactionInfo.get();
if (txnInfo.transactionTime == null) {
@@ -746,7 +753,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
private static class TransactionInfo {
EntityManager entityManager;
boolean inTransaction = false;
DateTime transactionTime;
Instant transactionTime;
Supplier<Long> idProvider;
// The set of entity objects that have been either persisted (via insert()) or merged (via
@@ -759,7 +766,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
private void start(Clock clock, Supplier<Long> idProvider) {
checkArgumentNotNull(clock);
inTransaction = true;
transactionTime = clock.nowUtc();
transactionTime = clock.now();
this.idProvider = idProvider;
}
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
import google.registry.model.ImmutableObject;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
import java.time.Instant;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.Callable;
@@ -49,7 +50,7 @@ public interface TransactionManager {
void assertInTransaction();
/**
* Returns a {@link long} value that can be used as {@code id} by a JPA model entity.
* Returns a {@code long} value that can be used as {@code id} by a JPA model entity.
*
* <p>The returned value must be project-wide unique when transacting on the primary database
* instance, but only needs to be unique within a JVM instance when transacting on the replica
@@ -129,8 +130,12 @@ public interface TransactionManager {
void reTransact(ThrowingRunnable work);
/** Returns the time associated with the start of this particular transaction attempt. */
@Deprecated
DateTime getTransactionTime();
/** Returns the Instant associated with the start of this particular transaction attempt. */
Instant getTxTime();
/** Persists a new entity in the database, throws exception if the entity already exists. */
void insert(Object entity);
@@ -17,6 +17,7 @@ package google.registry.rdap;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static google.registry.request.Actions.getPathForAction;
import static google.registry.util.DateTimeUtils.toInstant;
import static google.registry.util.DomainNameUtils.canonicalizeHostname;
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
@@ -241,7 +242,7 @@ public abstract class RdapActionBase implements Runnable {
* is authorized to do so.
*/
boolean isAuthorized(EppResource eppResource) {
return getRequestTime().isBefore(eppResource.getDeletionTime())
return toInstant(getRequestTime()).isBefore(eppResource.getDeletionTime())
|| (shouldIncludeDeleted()
&& rdapAuthorization.isAuthorizedForRegistrar(
eppResource.getPersistedCurrentSponsorRegistrarId()));
@@ -20,6 +20,8 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.EppResourceUtils.isLinked;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import static google.registry.util.DateTimeUtils.toDateTime;
import static google.registry.util.DateTimeUtils.toInstant;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.annotations.VisibleForTesting;
@@ -47,6 +49,7 @@ import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
import google.registry.persistence.VKey;
import google.registry.rdap.RdapDataStructures.Event;
import google.registry.rdap.RdapDataStructures.EventAction;
import google.registry.rdap.RdapDataStructures.Link;
@@ -113,6 +116,10 @@ public class RdapJsonFormatter {
@Nullable
String rdapTosStaticUrl;
@Inject
@Config("rdapIncludeOptionalHistoryResults")
boolean rdapIncludeOptionalHistoryResults;
@Inject @RequestServerName String serverName;
@Inject RdapAuthorization rdapAuthorization;
@Inject Clock clock;
@@ -317,7 +324,7 @@ public class RdapJsonFormatter {
.build(),
Event.builder()
.setEventAction(EventAction.EXPIRATION)
.setEventDate(domain.getRegistrationExpirationTime())
.setEventDate(domain.getRegistrationExpirationDateTime())
.build(),
// RDAP response profile section 1.5:
// The topmost object in the RDAP response MUST contain an event of "eventAction" type
@@ -327,9 +334,27 @@ public class RdapJsonFormatter {
.setEventAction(EventAction.LAST_UPDATE_OF_RDAP_DATABASE)
.setEventDate(getRequestTime())
.build());
// RDAP Response Profile section 2.3.2.2:
// "The event of eventAction type last changed MUST be omitted if the domain has not been
// updated since it was created." While it is possible for the domain to be changed out of band
// (i.e. without updating lastEppUpdateTime), that can only happen for domains that have already
// been modified in some way. As a result, we can ignore those cases here.
if (domain.getLastEppUpdateTime() != null
&& domain.getLastEppUpdateTime().isAfter(toInstant(domain.getCreationTime()))) {
// Creates an RDAP event object as defined by RFC 9083
builder
.eventsBuilder()
.add(
Event.builder()
.setEventAction(EventAction.LAST_CHANGED)
.setEventDate(toDateTime(domain.getLastEppUpdateTime()))
.build());
}
// RDAP Response Profile section 2.3.2 discusses optional events. We add some of those
// here. We also add a few others we find interesting.
builder.eventsBuilder().addAll(makeOptionalEvents(domain));
if (rdapIncludeOptionalHistoryResults) {
builder.eventsBuilder().addAll(makeOptionalEvents(domain));
}
// RDAP Response Profile section 2.4.1:
// The domain object in the RDAP response MUST contain an entity with the Registrar role.
//
@@ -352,27 +377,36 @@ public class RdapJsonFormatter {
}
// RDAP Response Profile 2.6.1: must have at least one status member
// makeStatusValueList should in theory always contain one of either "active" or "inactive".
// RDAP Response Profile 2.6.3, must have a notice about statuses. That is in {@link
// RdapIcannStandardInformation#domainBoilerplateNotices}, not here.
Set<EppEnum> allStatusValues =
Sets.union(domain.getStatusValues(), domain.getGracePeriodStatuses());
ImmutableSet<RdapStatus> status =
makeStatusValueList(
allStatusValues,
false, // isRedacted
domain.getDeletionTime().isBefore(getRequestTime()));
domain.getDeletionDateTime().isBefore(getRequestTime()));
builder.statusBuilder().addAll(status);
if (status.isEmpty()) {
logger.atWarning().log(
"Domain %s (ROID %s) doesn't have any status.",
domain.getDomainName(), domain.getRepoId());
}
// RDAP Response Profile 2.6.3, must have a notice about statuses. That is in {@link
// RdapIcannStandardInformation#domainBoilerplateNotices}
// We're just trying to load the hosts by cache here, but the generics and casting require
// a lot of boilerplate to make the compiler happy
Iterable<VKey<? extends EppResource>> nameservers =
ImmutableSet.copyOf(domain.getNameservers());
ImmutableSet<Host> loadedHosts =
replicaTm()
.transact(
() ->
ImmutableSet.copyOf(replicaTm().loadByKeys(domain.getNameservers()).values()));
() -> {
ImmutableSet.Builder<Host> hostBuilder = new ImmutableSet.Builder<>();
for (EppResource host : EppResource.loadByCacheIfEnabled(nameservers).values()) {
hostBuilder.add((Host) host);
}
return hostBuilder.build();
});
// Add the nameservers to the data; the load was kicked off above for efficiency.
// RDAP Response Profile 2.8: we MUST have the nameservers
@@ -425,8 +459,7 @@ public class RdapJsonFormatter {
&& replicaTm()
.transact(
() ->
replicaTm()
.loadByKey(host.getSuperordinateDomain())
EppResource.loadByCache(host.getSuperordinateDomain())
.cloneProjectedAtTime(getRequestTime())
.getStatusValues()
.contains(StatusValue.PENDING_TRANSFER))) {
@@ -438,7 +471,7 @@ public class RdapJsonFormatter {
makeStatusValueList(
statuses.build(),
false, // isRedacted
host.getDeletionTime().isBefore(getRequestTime())));
host.getDeletionDateTime().isBefore(getRequestTime())));
}
// For query responses - we MUST have all the ip addresses: RDAP Response Profile 4.2.
@@ -747,12 +780,9 @@ public class RdapJsonFormatter {
* that we don't need to load HistoryEntries for "summary" responses).
*/
private ImmutableList<Event> makeOptionalEvents(EppResource resource) {
ImmutableList.Builder<Event> eventsBuilder = new ImmutableList.Builder<>();
ImmutableMap<EventAction, HistoryTimeAndRegistrar> lastHistoryOfType =
getLastHistoryByType(resource);
ImmutableList.Builder<Event> eventsBuilder = new ImmutableList.Builder<>();
DateTime creationTime = resource.getCreationTime();
DateTime lastChangeTime =
resource.getLastEppUpdateTime() == null ? creationTime : resource.getLastEppUpdateTime();
// The order of the elements is stable - it's the order in which the enum elements are defined
// in EventAction
for (EventAction rdapEventAction : EventAction.values()) {
@@ -761,34 +791,11 @@ public class RdapJsonFormatter {
if (historyTimeAndRegistrar == null) {
continue;
}
DateTime modificationTime = historyTimeAndRegistrar.modificationTime();
// We will ignore all events that happened before the "creation time", since these events are
// from a "previous incarnation of the domain" (for a domain that was owned by someone,
// deleted, and then bought by someone else)
if (modificationTime.isBefore(creationTime)) {
continue;
}
eventsBuilder.add(
Event.builder()
.setEventAction(rdapEventAction)
.setEventActor(historyTimeAndRegistrar.registrarId())
.setEventDate(modificationTime)
.build());
// The last change time might not be the lastEppUpdateTime, since some changes happen without
// any EPP update (for example, by the passage of time).
if (modificationTime.isAfter(lastChangeTime) && modificationTime.isBefore(getRequestTime())) {
lastChangeTime = modificationTime;
}
}
// RDAP Response Profile section 2.3.2.2:
// The event of eventAction type last changed MUST be omitted if the domain name has not been
// updated since it was created
if (lastChangeTime.isAfter(creationTime)) {
// Creates an RDAP event object as defined by RFC 9083
eventsBuilder.add(
Event.builder()
.setEventAction(EventAction.LAST_CHANGED)
.setEventDate(lastChangeTime)
.setEventDate(historyTimeAndRegistrar.modificationTime())
.build());
}
return eventsBuilder.build();
@@ -94,13 +94,13 @@ final class DomainToXjcConverter {
// identifying the end (expiration) of the domain name object's
// registration period. This element MUST be present if the domain
// name has been allocated.
bean.setExDate(model.getRegistrationExpirationTime());
bean.setExDate(model.getRegistrationExpirationDateTime());
// o An OPTIONAL <upDate> element that contains the date and time of
// the most recent domain-name-object modification. This element
// MUST NOT be present if the domain name object has never been
// modified.
bean.setUpDate(model.getLastEppUpdateTime());
bean.setUpDate(model.getLastEppUpdateDateTime());
// o An OPTIONAL <upRr> element that contains the identifier of the
// registrar that last updated the domain name object. This element
@@ -228,8 +228,8 @@ final class DomainToXjcConverter {
bean.setReRr(RdeUtils.makeXjcRdeRrType(model.getGainingRegistrarId()));
bean.setAcRr(RdeUtils.makeXjcRdeRrType(model.getLosingRegistrarId()));
bean.setReDate(model.getTransferRequestTime());
bean.setAcDate(model.getPendingTransferExpirationTime());
bean.setExDate(model.getTransferredRegistrationExpirationTime());
bean.setAcDate(model.getPendingTransferExpirationDateTime());
bean.setExDate(model.getTransferredRegistrationExpirationDateTime());
return bean;
}
@@ -70,7 +70,7 @@ final class HostToXjcConverter {
bean.setName(model.getHostName());
bean.setRoid(model.getRepoId());
bean.setCrDate(model.getCreationTime());
bean.setUpDate(model.getLastEppUpdateTime());
bean.setUpDate(model.getLastEppUpdateDateTime());
bean.setCrRr(RdeAdapter.convertRr(model.getCreationRegistrarId(), null));
bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateRegistrarId(), null));
bean.setCrRr(RdeAdapter.convertRr(model.getCreationRegistrarId(), null));
@@ -19,7 +19,6 @@ import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.model.tld.Tlds.findTldForNameOrThrow;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -30,7 +29,6 @@ import google.registry.util.StringGenerator;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.joda.money.Money;
import org.joda.time.DateTime;
/** A command to create a new anchor tenant domain. */
@Parameters(separators = " =", commandDescription = "Provision a domain for an anchor tenant.")
@@ -86,7 +84,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
Money cost = null;
if (fee) {
cost = getDomainCreateCost(domainName, DateTime.now(UTC), DEFAULT_ANCHOR_TENANT_PERIOD_YEARS);
cost = getDomainCreateCost(domainName, clock.nowUtc(), DEFAULT_ANCHOR_TENANT_PERIOD_YEARS);
}
setSoyTemplate(CreateAnchorTenantSoyInfo.getInstance(),
@@ -17,7 +17,6 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -28,7 +27,6 @@ import google.registry.util.StringGenerator;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.joda.money.Money;
import org.joda.time.DateTime;
/** A command to create a new domain via EPP. */
@Parameters(separators = " =", commandDescription = "Create a new domain via EPP.")
@@ -64,7 +62,7 @@ final class CreateDomainCommand extends CreateOrUpdateDomainCommand {
for (String domain : domains) {
String currency = null;
String cost = null;
DomainPrices prices = getPricesForDomainName(domain, DateTime.now(UTC));
DomainPrices prices = getPricesForDomainName(domain, clock.nowUtc());
// Check if the domain is premium and set the fee on the create command if so.
if (prices.isPremium()) {
@@ -14,10 +14,14 @@
package google.registry.tools;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter;
import com.google.common.flogger.FluentLogger;
import google.registry.model.tld.label.PremiumListDao;
import google.registry.tools.params.PathParameter;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.nio.file.Path;
import java.util.List;
import javax.annotation.Nullable;
@@ -29,6 +33,8 @@ import org.joda.money.CurrencyUnit;
*/
abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand {
@Inject Clock clock;
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected List<String> inputData;
protected CurrencyUnit currency;
@@ -54,7 +60,7 @@ abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand {
String.format("Saved premium list %s with %d entries.", name, inputData.size());
try {
logger.atInfo().log("Saving premium list for TLD %s.", name);
PremiumListDao.save(name, currency, inputData);
tm().transact(() -> PremiumListDao.save(name, currency, inputData));
logger.atInfo().log(message);
} catch (Throwable e) {
message = "Unexpected error saving premium list from nomulus tool command.";
@@ -21,7 +21,6 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.util.RegistrarUtils.normalizeRegistrarName;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter;
import com.google.common.base.Ascii;
@@ -37,6 +36,7 @@ import google.registry.tools.params.OptionalStringParameter;
import google.registry.tools.params.PathParameter.InputFile;
import google.registry.tools.params.StringListParameter;
import google.registry.util.CidrAddressBlock;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -56,6 +56,8 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
@Inject CertificateChecker certificateChecker;
@Inject Clock clock;
@Parameter(description = "Client identifier of the registrar account", required = true)
List<String> mainParameters;
@@ -272,7 +274,7 @@ abstract class CreateOrUpdateRegistrarCommand extends MutatingCommand {
@Override
protected final void init() throws Exception {
initRegistrarCommand();
DateTime now = DateTime.now(UTC);
DateTime now = clock.nowUtc();
for (String clientId : mainParameters) {
Registrar oldRegistrar = getOldRegistrar(clientId);
Registrar.Builder builder =
@@ -19,6 +19,8 @@ import com.google.common.flogger.FluentLogger;
import google.registry.model.tld.label.ReservedList;
import google.registry.model.tld.label.ReservedListDao;
import google.registry.tools.params.PathParameter;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.nio.file.Path;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -29,6 +31,8 @@ import javax.annotation.Nullable;
*/
public abstract class CreateOrUpdateReservedListCommand extends ConfirmingCommand {
@Inject Clock clock;
static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Nullable
@@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.tld.Tlds.assertTldExists;
import static google.registry.util.ListNamingUtils.convertFilePathToName;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -51,7 +50,7 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand
if (!override) {
validateListName(name);
}
DateTime now = DateTime.now(UTC);
DateTime now = clock.nowUtc();
List<String> allLines = Files.readAllLines(input, UTF_8);
reservedList =
new ReservedList.Builder()
@@ -38,6 +38,8 @@ import com.google.template.soy.data.SoyRecord;
import com.google.template.soy.parseinfo.SoyFileInfo;
import com.google.template.soy.parseinfo.SoyTemplateInfo;
import google.registry.model.registrar.Registrar;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
@@ -49,6 +51,8 @@ import java.util.Objects;
/** A command to execute an epp command. */
abstract class EppToolCommand extends ConfirmingCommand implements CommandWithConnection {
@Inject Clock clock;
@Parameter(
names = {"-u", "--superuser"},
description = "Run in superuser mode")
@@ -56,8 +56,7 @@ final class GenerateDnsReportCommand implements Command {
validateWith = PathParameter.OutputFile.class)
private Path output = Paths.get("/dev/stdout");
@Inject
Clock clock;
@Inject Clock clock;
@Override
public void run() throws Exception {
@@ -81,7 +80,7 @@ final class GenerateDnsReportCommand implements Command {
.list());
for (Domain domain : domains) {
// Skip deleted domains and domains that don't get published to DNS.
if (isBeforeOrAt(domain.getDeletionTime(), now) || !domain.shouldPublishToDns()) {
if (isBeforeOrAt(domain.getDeletionDateTime(), now) || !domain.shouldPublishToDns()) {
continue;
}
write(domain);
@@ -90,7 +89,7 @@ final class GenerateDnsReportCommand implements Command {
Iterable<Host> nameservers = tm().transact(() -> tm().loadAllOf(Host.class));
for (Host nameserver : nameservers) {
// Skip deleted hosts and external hosts.
if (isBeforeOrAt(nameserver.getDeletionTime(), now)
if (isBeforeOrAt(nameserver.getDeletionDateTime(), now)
|| nameserver.getInetAddresses().isEmpty()) {
continue;
}
@@ -15,7 +15,6 @@
package google.registry.tools;
import static google.registry.model.tld.Tlds.assertTldsExist;
import static org.joda.time.DateTimeZone.UTC;
import static org.joda.time.Duration.standardMinutes;
import com.beust.jcommander.Parameter;
@@ -23,6 +22,8 @@ import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableMap;
import google.registry.tools.params.DateParameter;
import google.registry.tools.server.GenerateZoneFilesAction;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@@ -40,10 +41,13 @@ final class GenerateZoneFilesCommand implements CommandWithConnection {
// Default to latest midnight that's at least 2 minutes ago.
@Parameter(
names = "--export_date",
description = "The date to generate the file for (defaults to today, or yesterday if run "
+ "before 00:02).",
description =
"The date to generate the file for (defaults to today, or yesterday if run "
+ "before 00:02).",
validateWith = DateParameter.class)
private DateTime exportDate = DateTime.now(UTC).minus(standardMinutes(2)).withTimeAtStartOfDay();
private DateTime exportDate;
@Inject Clock clock;
private ServiceConnection connection;
@@ -54,6 +58,9 @@ final class GenerateZoneFilesCommand implements CommandWithConnection {
@Override
public void run() throws IOException {
if (exportDate == null) {
exportDate = clock.nowUtc().minus(standardMinutes(2)).withTimeAtStartOfDay();
}
assertTldsExist(mainParameters);
ImmutableMap<String, Object> params = ImmutableMap.of(
"tlds", mainParameters,
@@ -17,7 +17,6 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -26,7 +25,9 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
import google.registry.persistence.VKey;
import google.registry.tools.CommandUtilities.ResourceType;
import google.registry.util.Clock;
import google.registry.xml.XmlTransformer;
import jakarta.inject.Inject;
import org.joda.time.DateTime;
/** Command to show history entries. */
@@ -35,6 +36,8 @@ import org.joda.time.DateTime;
commandDescription = "Show history entries that occurred in a given time range")
final class GetHistoryEntriesCommand implements Command {
@Inject Clock clock;
@Parameter(
names = {"-a", "--after"},
description = "Only show history entries that occurred at or after this time")
@@ -58,7 +61,7 @@ final class GetHistoryEntriesCommand implements Command {
checkArgument(
type != null && uniqueId != null,
"If either of 'type' or 'id' are set then both must be");
VKey<? extends EppResource> parentKey = type.getKey(uniqueId, DateTime.now(UTC));
VKey<? extends EppResource> parentKey = type.getKey(uniqueId, clock.nowUtc());
historyEntries = HistoryEntryDao.loadHistoryObjectsForResource(parentKey, after, before);
} else {
historyEntries = HistoryEntryDao.loadAllHistoryObjects(after, before);
@@ -14,6 +14,7 @@
package google.registry.tools;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.keyring.api.KeySerializer;
@@ -95,6 +96,10 @@ final class GetKeyringSecretCommand implements Command {
out.write(KeySerializer.serializeString(keyring.getSqlPrimaryConnectionName()));
case SQL_REPLICA_CONN_NAME ->
out.write(KeySerializer.serializeString(keyring.getSqlReplicaConnectionName()));
case SQL_REPLICA_CONN_NAMES ->
out.write(
KeySerializer.serializeString(
String.join("\n", keyring.getSqlReplicaConnectionNames())));
}
}
}
@@ -26,8 +26,6 @@ import com.google.template.soy.data.SoyMapData;
import google.registry.flows.ResourceFlowUtils;
import google.registry.model.domain.Domain;
import google.registry.tools.soy.DomainRenewSoyInfo;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
@@ -63,9 +61,6 @@ final class RenewDomainCommand extends MutatingEppToolCommand {
arity = 1)
Boolean requestedByRegistrar;
@Inject
Clock clock;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("YYYY-MM-dd");
@Override
@@ -81,7 +76,7 @@ final class RenewDomainCommand extends MutatingEppToolCommand {
SoyMapData soyMapData =
new SoyMapData(
"domainName", domain.getDomainName(),
"expirationDate", domain.getRegistrationExpirationTime().toString(DATE_FORMATTER),
"expirationDate", domain.getRegistrationExpirationDateTime().toString(DATE_FORMATTER),
"period", String.valueOf(period));
if (requestedByRegistrar != null) {
@@ -37,8 +37,6 @@ import google.registry.model.host.Host;
import google.registry.tools.params.NameserversParameter;
import google.registry.tools.soy.DomainRenewSoyInfo;
import google.registry.tools.soy.UniformRapidSuspensionSoyInfo;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import jakarta.xml.bind.annotation.adapters.HexBinaryAdapter;
import java.util.ArrayList;
import java.util.HashSet;
@@ -122,8 +120,6 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
/** Set of status values to remove. */
ImmutableSet<String> removeStatuses;
@Inject Clock clock;
@Override
protected void initMutatingEppToolCommand()
throws ResourceFlowUtils.ResourceDoesNotExistException {
@@ -163,7 +159,7 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand {
domain.getDomainName(),
"expirationDate",
domain
.getRegistrationExpirationTime()
.getRegistrationExpirationDateTime()
.toString(DateTimeFormat.forPattern("YYYY-MM-dd")),
// period is the number of years to renew the registration for
"period",
@@ -99,8 +99,9 @@ class UnrenewDomainCommand extends ConfirmingCommand {
domainsWithDisallowedStatusesBuilder.putAll(
domainName, Sets.intersection(domain.get().getStatusValues(), DISALLOWED_STATUSES));
if (isBeforeOrAt(
leapSafeSubtractYears(domain.get().getRegistrationExpirationTime(), period), now)) {
domainsExpiringTooSoonBuilder.put(domainName, domain.get().getRegistrationExpirationTime());
leapSafeSubtractYears(domain.get().getRegistrationExpirationDateTime(), period), now)) {
domainsExpiringTooSoonBuilder.put(
domainName, domain.get().getRegistrationExpirationDateTime());
}
}
@@ -143,7 +144,7 @@ class UnrenewDomainCommand extends ConfirmingCommand {
DateTime now = clock.nowUtc();
for (String domainName : mainParameters) {
Domain domain = ForeignKeyUtils.loadResource(Domain.class, domainName, now).get();
DateTime previousTime = domain.getRegistrationExpirationTime();
DateTime previousTime = domain.getRegistrationExpirationDateTime();
DateTime newTime = leapSafeSubtractYears(previousTime, period);
resultBuilder.append(
String.format(
@@ -179,12 +180,12 @@ class UnrenewDomainCommand extends ConfirmingCommand {
"Domain %s has prohibited status values",
domainName);
checkState(
leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period).isAfter(now),
leapSafeSubtractYears(domain.getRegistrationExpirationDateTime(), period).isAfter(now),
"Domain %s expires too soon",
domainName);
DateTime newExpirationTime =
leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period);
leapSafeSubtractYears(domain.getRegistrationExpirationDateTime(), period);
DomainHistory domainHistory =
new DomainHistory.Builder()
.setDomain(domain)
@@ -33,8 +33,6 @@ import google.registry.model.domain.GracePeriodBase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.tools.params.NameserversParameter;
import google.registry.tools.soy.DomainUpdateSoyInfo;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -49,8 +47,6 @@ final class UpdateDomainCommand extends CreateOrUpdateDomainCommand {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Inject Clock clock;
@Parameter(names = "--statuses", description = "Comma-separated list of statuses to set.")
private List<String> statuses = new ArrayList<>();
@@ -100,6 +100,8 @@ final class UpdateKeyringSecretCommand implements Command {
secretManagerKeyringUpdater.setSqlPrimaryConnectionName(deserializeString(input));
case SQL_REPLICA_CONN_NAME ->
secretManagerKeyringUpdater.setSqlReplicaConnectionName(deserializeString(input));
case SQL_REPLICA_CONN_NAMES ->
secretManagerKeyringUpdater.setSqlReplicaConnectionNames(deserializeString(input));
}
secretManagerKeyringUpdater.update();
@@ -62,7 +62,8 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand {
inputData = Files.readAllLines(inputFile, UTF_8);
checkArgument(!inputData.isEmpty(), "New premium list data cannot be empty");
currency = existingList.getCurrency();
PremiumList updatedPremiumList = PremiumListUtils.parseToPremiumList(name, currency, inputData);
PremiumList updatedPremiumList =
PremiumListUtils.parseToPremiumList(name, currency, inputData, clock.nowUtc());
if (!existingList
.getLabelsToPrices()
.entrySet()
@@ -16,7 +16,9 @@ package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.toDateTime;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@@ -31,6 +33,7 @@ import google.registry.model.domain.DomainHistory;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
import google.registry.model.transfer.TransferStatus;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
@@ -161,7 +164,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand {
private ImmutableMap<Domain, BillingRecurrence> loadDomainsAndRecurrences() {
ImmutableMap.Builder<Domain, BillingRecurrence> result = new ImmutableMap.Builder<>();
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
for (String domainName : mainParameters) {
Domain domain =
ForeignKeyUtils.loadResource(Domain.class, domainName, now)
@@ -171,7 +174,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand {
String.format(
"Domain %s does not exist or has been deleted", domainName)));
checkArgument(
domain.getDeletionTime().equals(END_OF_TIME),
domain.getDeletionTime().equals(END_INSTANT),
"Domain %s has already had a deletion time set",
domainName);
checkArgument(
@@ -184,7 +187,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand {
domainAutorenewEndTime.ifPresent(
endTime ->
checkArgument(
endTime.isAfter(now),
endTime.isAfter(toDateTime(now)),
"Domain %s autorenew ended prior to now at %s",
domainName,
endTime));
@@ -38,5 +38,6 @@ public enum KeyringKeyName {
RDE_STAGING_PUBLIC_KEY,
SAFE_BROWSING_API_KEY,
SQL_PRIMARY_CONN_NAME,
SQL_REPLICA_CONN_NAME
SQL_REPLICA_CONN_NAME,
SQL_REPLICA_CONN_NAMES
}
@@ -16,7 +16,6 @@ package google.registry.ui.server.console;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.GET;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
@@ -35,7 +34,6 @@ import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.joda.time.DateTime;
@Action(
service = Service.CONSOLE,
@@ -86,7 +84,7 @@ public class ConsoleDumDownloadAction extends ConsoleApiAction {
.setHeader("Cache-Control", "max-age=86400"); // 86400 seconds = 1 day
consoleApiParams
.response()
.setDateHeader("Expires", DateTime.now(UTC).withTimeAtStartOfDay().plusDays(1));
.setDateHeader("Expires", clock.nowUtc().withTimeAtStartOfDay().plusDays(1));
try (var writer = consoleApiParams.response().getWriter()) {
CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT);
@@ -24,6 +24,7 @@ import static google.registry.testing.DatabaseHelper.loadByEntity;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.plusDays;
import com.google.common.collect.ImmutableSet;
import google.registry.flows.DaggerEppTestComponent;
@@ -117,7 +118,7 @@ class DeleteExpiredDomainsActionTest {
assertThat(loadByEntity(notYetExpiredDomain)).isEqualTo(notYetExpiredDomain);
Domain reloadedExpiredDomain = loadByEntity(pendingExpirationDomain);
assertThat(reloadedExpiredDomain.getStatusValues()).contains(PENDING_DELETE);
assertThat(reloadedExpiredDomain.getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35));
assertThat(reloadedExpiredDomain.getDeletionTime()).isEqualTo(plusDays(clock.now(), 35));
}
@Test
@@ -26,7 +26,7 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
import static google.registry.testing.DatabaseHelper.persistDomainAsDeleted;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static org.joda.time.DateTimeZone.UTC;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -45,8 +45,10 @@ import google.registry.model.tld.Tld.TldType;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.SystemPropertyExtension;
import google.registry.util.RegistryEnvironment;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import org.joda.money.Money;
@@ -61,9 +63,11 @@ class DeleteProberDataActionTest {
private static final DateTime DELETION_TIME = DateTime.parse("2010-01-01T00:00:00.000Z");
private final FakeClock clock = new FakeClock(DateTime.now(UTC));
@RegisterExtension
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
@RegisterExtension
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
@@ -93,7 +97,9 @@ class DeleteProberDataActionTest {
}
private void resetAction() {
action = new DeleteProberDataAction(false, ImmutableSet.of(), Optional.empty(), "TheRegistrar");
action =
new DeleteProberDataAction(
false, ImmutableSet.of(), Optional.empty(), "TheRegistrar", clock);
}
@AfterEach
@@ -123,7 +129,7 @@ class DeleteProberDataActionTest {
Set<ImmutableObject> oaEntities = persistLotsOfDomains("oa-canary.test");
// Create action with batch size of 3
DeleteProberDataAction batchedAction =
new DeleteProberDataAction(false, ImmutableSet.of(), Optional.of(3), "TheRegistrar");
new DeleteProberDataAction(false, ImmutableSet.of(), Optional.of(3), "TheRegistrar", clock);
batchedAction.run();
assertAllAbsent(ibEntities);
assertAllAbsent(oaEntities);
@@ -201,7 +207,7 @@ class DeleteProberDataActionTest {
.setCreationTimeForTest(DateTime.now(UTC).minusYears(1))
.build());
action.run();
DateTime timeAfterDeletion = DateTime.now(UTC);
Instant timeAfterDeletion = Instant.now();
assertThat(ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", timeAfterDeletion))
.isEmpty();
assertThat(loadByEntity(domain).getDeletionTime()).isLessThan(timeAfterDeletion);
@@ -217,7 +223,7 @@ class DeleteProberDataActionTest {
.setCreationTimeForTest(DateTime.now(UTC).minusYears(1))
.build());
action.run();
DateTime timeAfterDeletion = DateTime.now(UTC);
Instant timeAfterDeletion = Instant.now();
resetAction();
action.run();
assertThat(ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", timeAfterDeletion))
@@ -237,7 +243,7 @@ class DeleteProberDataActionTest {
Optional<Domain> domain =
ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", DateTime.now(UTC));
assertThat(domain).isPresent();
assertThat(domain.get().getDeletionTime()).isEqualTo(END_OF_TIME);
assertThat(domain.get().getDeletionTime()).isEqualTo(END_INSTANT);
}
@Test
@@ -250,7 +256,7 @@ class DeleteProberDataActionTest {
.build());
action.isDryRun = true;
action.run();
assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(END_OF_TIME);
assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(END_INSTANT);
}
@Test
@@ -97,7 +97,8 @@ class SendExpiringCertificateNotificationEmailActionTest {
EXPIRATION_WARNING_EMAIL_SUBJECT_TEXT,
sendEmailService,
certificateChecker,
response);
response,
clock);
sampleRegistrar =
persistResource(createRegistrar("clientId", "sampleRegistrar", null, null).build());
@@ -25,6 +25,8 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources;
import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer;
import static google.registry.testing.DatabaseHelper.persistNewRegistrars;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DateTimeUtils.toInstant;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -113,11 +115,12 @@ public class ResaveAllEppResourcesPipelineTest {
DateTime now = fakeClock.nowUtc();
Domain domain =
persistDomainWithDependentResources("domain", "tld", now, now, now.plusYears(1));
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(now.plusYears(1));
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(plusYears(toInstant(now), 1));
fakeClock.advanceBy(Duration.standardDays(500));
runPipeline();
Domain postPipeline = loadByEntity(domain);
assertThat(postPipeline.getRegistrationExpirationTime()).isEqualTo(now.plusYears(2));
assertThat(postPipeline.getRegistrationExpirationTime())
.isEqualTo(plusYears(toInstant(now), 2));
}
@Test
@@ -85,10 +85,13 @@ class SafeBrowsingTransformsTest {
private final CloseableHttpClient mockHttpClient =
mock(CloseableHttpClient.class, withSettings().serializable());
private final FakeClock clock = new FakeClock();
private final EvaluateSafeBrowsingFn safeBrowsingFn =
new EvaluateSafeBrowsingFn(
"API_KEY",
new Retrier(new FakeSleeper(new FakeClock()), 1),
new Retrier(new FakeSleeper(clock), 1),
clock,
Suppliers.ofInstance(mockHttpClient));
@RegisterExtension
@@ -187,7 +187,8 @@ class Spec11PipelineTest {
EvaluateSafeBrowsingFn safeBrowsingFn =
new EvaluateSafeBrowsingFn(
SAFE_BROWSING_API_KEY,
new Retrier(new FakeSleeper(new FakeClock()), 1),
new Retrier(new FakeSleeper(fakeClock), 1),
fakeClock,
Suppliers.ofInstance(mockHttpClient));
when(mockHttpClient.execute(any(HttpPost.class))).thenAnswer(new HttpResponder());
Spec11Pipeline spec11Pipeline = new Spec11Pipeline(options, safeBrowsingFn);
@@ -17,6 +17,7 @@ package google.registry.export;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.export.ExportPremiumTermsAction.EXPORT_MIME_TYPE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.deleteTld;
import static google.registry.testing.DatabaseHelper.persistResource;
@@ -75,7 +76,7 @@ public class ExportPremiumTermsActionTest {
@BeforeEach
void beforeEach() throws Exception {
createTld("tld");
PremiumList pl = PremiumListDao.save("pl-name", USD, PREMIUM_NAMES);
PremiumList pl = tm().transact(() -> PremiumListDao.save("pl-name", USD, PREMIUM_NAMES));
persistResource(
Tld.get("tld").asBuilder().setPremiumList(pl).setDriveFolderId("folder_id").build());
when(driveConnection.createOrUpdateFile(
@@ -488,7 +488,7 @@ class EppLifecycleDomainTest extends EppTestCase {
// Make sure that in the future, the domain expiration is unchanged after deletion
Domain clonedDomain = domain.cloneProjectedAtTime(deleteTime.plusYears(5));
assertThat(clonedDomain.getRegistrationExpirationTime()).isEqualTo(createTime.plusYears(2));
assertThat(clonedDomain.getRegistrationExpirationDateTime()).isEqualTo(createTime.plusYears(2));
}
@Test
@@ -182,7 +182,7 @@ public abstract class FlowTestCase<F extends Flow> {
GracePeriod.create(
entry.getKey().getType(),
entry.getKey().getDomainRepoId(),
entry.getKey().getExpirationTime(),
entry.getKey().getExpirationDateTime(),
entry.getKey().getRegistrarId(),
null,
1L),
@@ -361,7 +361,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId(getUniqueIdFromCommand())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setRecurrenceEndTime(END_OF_TIME)
.setDomainHistory(historyEntry)
.setRenewalPriceBehavior(expectedRenewalPriceBehavior)
@@ -397,7 +397,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
new PollMessage.Autorenew.Builder()
.setTargetId(domain.getDomainName())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntry)
.build());
@@ -1720,7 +1720,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
new PollMessage.Autorenew.Builder()
.setTargetId(domain.getDomainName())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntry)
.build(),
@@ -1853,7 +1853,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
new PollMessage.Autorenew.Builder()
.setTargetId(domain.getDomainName())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntry)
.build(),
@@ -376,7 +376,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
runFlowAssertResponse(loadFile("domain_delete_response_pending.xml"));
Domain domain = reloadResourceByForeignKey();
DateTime redemptionEndTime = domain.getLastEppUpdateTime().plusDays(3);
DateTime redemptionEndTime = domain.getLastEppUpdateDateTime().plusDays(3);
Domain domainAtRedemptionTime = domain.cloneProjectedAtTime(redemptionEndTime);
assertAboutDomains()
.that(domainAtRedemptionTime)
@@ -418,7 +418,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
null));
// We should see exactly one poll message, which is for the autorenew 1 month in the future.
assertPollMessages(createAutorenewPollMessage("TheRegistrar").build());
DateTime expectedExpirationTime = domain.getRegistrationExpirationTime().minusYears(2);
DateTime expectedExpirationTime = domain.getRegistrationExpirationDateTime().minusYears(2);
clock.advanceOneMilli();
runFlowAssertResponse(loadFile(responseFilename, substitutions));
Domain resource = reloadResourceByForeignKey();
@@ -462,7 +462,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
// There should be a future poll message at the deletion time. The previous autorenew poll
// message should now be deleted.
assertAboutDomains().that(domain).hasDeletePollMessage();
DateTime deletionTime = domain.getDeletionTime();
DateTime deletionTime = domain.getDeletionDateTime();
assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).isEmpty();
assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(1);
assertThat(domain.getDeletePollMessage())
@@ -496,7 +496,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
runFlowAssertResponse(loadFile("domain_delete_response_pending.xml"));
// There should now be two poll messages; one for the delete of the domain (in the future), and
// another for the unacked autorenew messages.
DateTime deletionTime = reloadResourceByForeignKey().getDeletionTime();
DateTime deletionTime = reloadResourceByForeignKey().getDeletionDateTime();
assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).hasSize(1);
assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(2);
}
@@ -613,7 +613,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
.isEqualTo(Trid.create("transferClient-trid", "transferServer-trid"));
assertThat(panData.getActionResult()).isFalse();
// There should be a future poll message to the losing registrar at the deletion time.
DateTime deletionTime = domain.getDeletionTime();
DateTime deletionTime = domain.getDeletionDateTime();
assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).isEmpty();
assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(1);
assertOnlyBillingEventIsClosedAutorenew("TheRegistrar");
@@ -247,7 +247,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
@Nullable Money renewalPrice)
throws Exception {
assertMutatingFlow(true);
DateTime currentExpiration = reloadResourceByForeignKey().getRegistrationExpirationTime();
DateTime currentExpiration = reloadResourceByForeignKey().getRegistrationExpirationDateTime();
DateTime newExpiration = currentExpiration.plusYears(renewalYears);
runFlowAssertResponse(
CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions));
@@ -303,7 +303,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId(getUniqueIdFromCommand())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setRecurrenceEndTime(END_OF_TIME)
.setDomainHistory(historyEntryDomainRenew)
.build());
@@ -313,7 +313,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
new PollMessage.Autorenew.Builder()
.setTargetId(getUniqueIdFromCommand())
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntryDomainRenew)
@@ -817,7 +817,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
new PollMessage.Autorenew.Builder()
.setTargetId(getUniqueIdFromCommand())
.setRegistrarId("TheRegistrar")
.setEventTime(reloadResourceByForeignKey().getRegistrationExpirationTime())
.setEventTime(reloadResourceByForeignKey().getRegistrationExpirationDateTime())
.setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntryDomainRenew)
@@ -201,7 +201,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
new PollMessage.Autorenew.Builder()
.setTargetId("example.tld")
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntryDomainRestore)
@@ -269,7 +269,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
new PollMessage.Autorenew.Builder()
.setTargetId("example.tld")
.setRegistrarId("TheRegistrar")
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.")
.setHistoryEntry(historyEntryDomainRestore)
@@ -24,6 +24,7 @@ import static google.registry.model.reporting.DomainTransactionRecord.Transactio
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEventsForResource;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.deleteTestDomain;
@@ -148,7 +149,8 @@ class DomainTransferApproveFlowTest
.copyConstantFieldsToBuilder()
.setTransferStatus(TransferStatus.CLIENT_APPROVED)
.setPendingTransferExpirationTime(clock.nowUtc())
.setTransferredRegistrationExpirationTime(domain.getRegistrationExpirationTime())
.setTransferredRegistrationExpirationTime(
domain.getRegistrationExpirationDateTime())
.build());
}
@@ -216,7 +218,7 @@ class DomainTransferApproveFlowTest
// should be one at the current time to the gaining registrar, as well as one at the domain's
// autorenew time.
assertThat(getPollMessages(domain, "NewRegistrar", clock.nowUtc().plusMonths(1))).hasSize(1);
assertThat(getPollMessages(domain, "NewRegistrar", domain.getRegistrationExpirationTime()))
assertThat(getPollMessages(domain, "NewRegistrar", domain.getRegistrationExpirationDateTime()))
.hasSize(2);
PollMessage gainingTransferPollMessage =
@@ -225,11 +227,11 @@ class DomainTransferApproveFlowTest
getOnlyPollMessage(
domain,
"NewRegistrar",
domain.getRegistrationExpirationTime(),
domain.getRegistrationExpirationDateTime(),
PollMessage.Autorenew.class);
assertThat(gainingTransferPollMessage.getEventTime()).isEqualTo(clock.nowUtc());
assertThat(gainingAutorenewPollMessage.getEventTime())
.isEqualTo(domain.getRegistrationExpirationTime());
.isEqualTo(domain.getRegistrationExpirationDateTime());
DomainTransferResponse transferResponse =
gainingTransferPollMessage
.getResponseData()
@@ -239,7 +241,7 @@ class DomainTransferApproveFlowTest
.collect(onlyElement());
assertThat(transferResponse.getTransferStatus()).isEqualTo(TransferStatus.CLIENT_APPROVED);
assertThat(transferResponse.getExtendedRegistrationExpirationTime())
.isEqualTo(domain.getRegistrationExpirationTime());
.isEqualTo(domain.getRegistrationExpirationDateTime());
PendingActionNotificationResponse panData =
gainingTransferPollMessage
.getResponseData()
@@ -294,9 +296,9 @@ class DomainTransferApproveFlowTest
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setRecurrenceLastExpansion(
domain.getRegistrationExpirationTime().minusYears(1))
domain.getRegistrationExpirationDateTime().minusYears(1))
.setDomainHistory(historyEntryTransferApproved)
.build()))
.toArray(BillingBase[]::new));
@@ -332,9 +334,9 @@ class DomainTransferApproveFlowTest
.build(),
getGainingClientAutorenewEvent()
.asBuilder()
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())
.setRecurrenceLastExpansion(
domain.getRegistrationExpirationTime().minusYears(1))
domain.getRegistrationExpirationDateTime().minusYears(1))
.setDomainHistory(historyEntryTransferApproved)
.build()))
.toArray(BillingBase[]::new));
@@ -349,7 +351,7 @@ class DomainTransferApproveFlowTest
tld,
commandFilename,
expectedXmlFilename,
domain.getRegistrationExpirationTime().plusYears(1),
domain.getRegistrationExpirationDateTime().plusYears(1),
1);
}
@@ -511,12 +513,14 @@ class DomainTransferApproveFlowTest
@Test
void testSuccess_nonpremiumPriceRenewalBehavior_carriesOver() throws Exception {
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
tm().transact(
() ->
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build()));
persistResource(Tld.get("tld").asBuilder().setPremiumList(pl).build());
domain = loadByEntity(domain);
persistResource(
@@ -557,12 +561,14 @@ class DomainTransferApproveFlowTest
@Test
void testSuccess_specifiedPriceRenewalBehavior_carriesOver() throws Exception {
PremiumList pl =
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build());
tm().transact(
() ->
PremiumListDao.save(
new PremiumList.Builder()
.setCurrency(USD)
.setName("tld")
.setLabelsToPrices(ImmutableMap.of("example", new BigDecimal("67.89")))
.build()));
persistResource(Tld.get("tld").asBuilder().setPremiumList(pl).build());
domain = loadByEntity(domain);
persistResource(
@@ -821,7 +827,7 @@ class DomainTransferApproveFlowTest
"tld",
"domain_transfer_approve.xml",
"domain_transfer_approve_response_zero_period.xml",
domain.getRegistrationExpirationTime());
domain.getRegistrationExpirationDateTime());
assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods();
}
@@ -854,7 +860,7 @@ class DomainTransferApproveFlowTest
"tld",
"domain_transfer_approve.xml",
"domain_transfer_approve_response_zero_period_autorenew_grace.xml",
domain.getRegistrationExpirationTime());
domain.getRegistrationExpirationDateTime());
assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods();
}

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