1
0
mirror of https://github.com/google/nomulus synced 2026-05-14 20:01:46 +00:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Juan Celhay
1bff89085b Build Cloud Deploy artifacts via Cloud Build job (#3044)
* add README

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

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

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

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

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

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

This PR defines a new pipeline that performs a lightweight SQL
query and minimal processing. The build process can launch it
in a test environment to verify that the pipelines in the build
can run. The run script is also provided.
2026-05-07 20:41:13 +00:00
gbrodman
80eefc6498 Fix remote cache prefixing by handling it all in the Jedis client (#3035)
Found this out while testing metrics. In hindsight, not the best idea to
handle prefixing outside of the client itself. Instead, we'll enforce
the prefixing closer to Valkey, all in one place.
2026-05-07 20:28:56 +00:00
Ben McIlwain
74f9f5d478 Refactor bsa, dns, batch, and reporting packages to java.time (#3031)
This commit migrates the BSA, DNS, batch, and reporting packages from Joda-Time
to java.time. Key changes include:

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

Verified with a clean full build and all relevant test suites passing.
2026-05-06 21:44:40 +00:00
gbrodman
81b3a2fc5b Add an action to sync the remote Valkey cache (#3032)
This uses two cursors (one for hosts and one for domains) to track our
progress in "catching up", or syncing recent changes to the database,
using the update-timestamp field. When the cache is in use and fully
caught up, these
cursors should be kept relatively up-to-date to the actual time, i.e.
less than one hour behind
2026-05-05 15:29:43 +00:00
gbrodman
f44642fe28 Add expiration/deletion to Valkey cache (#3024)
This will be necessary for the batch job that runs however often to
"catch up" to the existing state.

We also only store "real" domains in Valkey.
2026-04-30 21:48:59 +00:00
Ben McIlwain
6e77a6b0e7 Migrate EPP Flows, TLD, and Domain Base models to java.time (#3025)
Migrates the massive DomainBase, DomainHistory, and Registrar models to use java.time.Instant natively, removing all deprecated DateTime accessors and fixing their associated JPA converters.
Migrates the Tld entity and its entire JSON/YAML testing ecosystem, including implementing an InstantKeySerializer to preserve millisecond precision in Jackson.
Migrates the entire Epp Flow ecosystem (Create, Update, Delete, Renew, Transfer for Domains/Hosts/Contacts) to use native Instant parameters and operations.
Migrates EppTestCase and EppLifecycleDomainTest to use Instant natively instead of constantly double-wrapping timestamps.
Rebases against upstream and standardizes all Duration and DateTimeUtils static imports across the test suites.
2026-04-30 00:05:55 +00:00
Juan Celhay
859f356466 Add folder and files for skeleton cloud deploy delivery pipeline. (#3029) 2026-04-29 19:56:34 +00:00
Ben McIlwain
fa15a66d9a Migrate Domain, Registrar, and Token models to java.time (#3022)
Migrated core EppResource and Token models from Joda-Time DateTime to java.time.Instant.

Specific migrations include:
- `DomainBase` and `Domain`: Migrated `registrationExpirationTime` and various other timestamps to use `Instant` directly.
- `Registrar`: Migrated `lastPocVerificationDate` and certificate dates to `Instant`.
- `BulkPricingPackage`: Migrated `nextBillingDate` and `lastNotificationSent`.
- `AllocationToken`: Migrated `tokenStatusTransitions` map keys to `Instant`.
- `LaunchNotice`: Migrated `acceptedTime` and `expirationTime`.

Updated all associated EPP flows (e.g., DomainCreateFlow, DomainRenewFlow), batch actions (e.g., CheckBulkComplianceAction, DeleteExpiredDomainsAction), command-line tools (e.g., UnrenewDomainCommand, UpdateBulkPricingPackageCommand), and tests to handle `Instant` directly.
2026-04-29 14:06:25 +00:00
sharma1210
76131fbd4e Add -J to --add-opens for Kythe extraction (#3028) 2026-04-29 08:15:27 +00:00
sharma1210
1196cd163b Fix Kythe extraction failure caused by Error Prone access to JDK internals (#3026) 2026-04-28 06:45:22 +00:00
gbrodman
4a412546f9 Upgrade beam deps (#3027)
https://docs.cloud.google.com/dataflow/docs/support/beam-runtime-support
looks like we need a later version for java 25
2026-04-27 19:40:10 +00:00
Ben McIlwain
6be0a32741 Migrate core, billing, and history to java.time (#3020)
Migrated core entity primitives (GracePeriod, RegistryLock, TimeOfYear), transfer objects (BaseTransferObject, DomainTransferData, TransferResponse), and HostBase from Joda-Time DateTime to java.time.Instant as Phases 5 and 7.
Migrated the Billing Ecosystem (BillingBase, BillingEvent, BillingRecurrence, BillingCancellation) and associated Beam pipelines (ExpandBillingRecurrencesPipeline, InvoicingPipeline) to java.time.Instant as Phase 6.
Migrated PollMessage event times and all associated Poll flow utilities (PollAckFlow, PollRequestFlow) to use Instant natively.
Migrated core timestamp tracking on EppResource (creationTime, lastEppUpdateTime, deletionTime) as well as CreateAutoTimestamp and UpdateAutoTimestamp to Instant, shedding deprecated DateTime accessors.
Migrated the entire HistoryEntry reporting ecosystem (HistoryEntry, DomainTransactionRecord, HistoryEntryDao) completely to java.time.Instant.
Updated all associated EPP flows, tools, and testing helpers to handle Instants directly where supported.
2026-04-24 19:50:55 +00:00
gbrodman
8cf222d1c9 Add Jedis (for Valkey) caches for domains and hosts (#3013)
We add optional Valkey caching of hosts and domains for future use. Eventually, this will allow us to pre-warm large amounts of data in Valkey for quick retrieval during actions like RDAP.

Note: this doesn't actually use the caches yet.

We use Jedis instead of Redisson for speed purposes
(https://www.instaclustr.com/blog/redis-java-clients-and-client-side-caching/)
which means that we have to implement our own multilayer cache but
that's not the worst thing in the world.

Tested on crash with logging and RDAP code that's not included in this
PR -- it behaves as you'd expect, where the local cache works for
immediate re-lookups and the remote cache works after a restart.
2026-04-24 19:50:01 +00:00
gbrodman
903414c76b Add Errorprone plugin for removing FQCNs (#3021)
These annoy me and AI loves to add them. Let's automatically remove them.
2026-04-23 20:17:19 +00:00
Ben McIlwain
925482ea58 Migrate TMCH, SMD, and Fee models to java.time (#3019)
Continues the project-wide migration from Joda-Time's DateTime to java.time.Instant, focusing on Trademark Clearinghouse (TMCH), Signed Mark Data (SMD), and Fee extension models.

Key updates:
- TMCH & SMD: Updated SmdRevocationList and domain check/create flows to use Instant for sunrise validations and revocation checks.
- Fee Extension Ecosystem: Refactored FeeCheckRequest, FeeCreateCommandExtension, and BaseFee to use Instant for effective dates and period calculations.
- EPP Objects: Updated DomainInfoData, TransferResponse, and PollMessage objects to use Instant for event timestamps.
- Pricing Logic: DomainPricingLogic methods now accept Instant for cost calculations.

Additionally, DateTimeUtils was enhanced with Instant compatibility methods for plusMonths and minusMonths to safely handle leap years.

Redundant conversions between DateTime and Instant were eliminated throughout the flows and tests. DomainFlowUtils leverages Instant natively to avoid inline casting, and test assertions now utilize Truth's Instant subjects for cleaner validation.
2026-04-22 16:44:47 +00:00
794 changed files with 9629 additions and 10027 deletions

8
.gitignore vendored
View File

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

View File

@@ -13,15 +13,14 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Verification**: Before finalizing any change, scan the imports section for redundancy.
- **License Headers**: When creating new files, ensure the license header uses the current year (e.g., 2026). Existing files should retain their original year.
## 2. Time and Precision Handling (java.time Migration)
## 2. Time and Precision Handling
- **Idiomatic java.time Usage:** Avoid redundant conversions between `Instant` and `DateTime`. If a field or parameter is an `Instant`, use it directly. Do not convert to `DateTime` just to call a deprecated method if an `Instant` alternative exists or can be easily created.
- **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).
- **UTC Timezones:** Do not use `ZoneId.of("UTC")`. Use a statically imported `UTC` from `ZoneOffset` instead (`import static java.time.ZoneOffset.UTC;`).
- **Clock Injection:**
- Avoid direct calls to `Instant.now()`, `DateTime.now()`, `ZonedDateTime.now()`, or `System.currentTimeMillis()`.
- Avoid direct calls to `Instant.now()`, `OffsetDateTime.now()`, or `System.currentTimeMillis()`.
- Inject `google.registry.util.Clock` (production) or `google.registry.testing.FakeClock` (tests).
- Use `clock.nowDate()` to get a `ZonedDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time. Avoid using the Unix epoch (`START_INSTANT`) unless specifically testing epoch-related logic; instead, use realistic dates and vary them across different test suites to ensure logic isn't dependent on a specific "standard" date.
- Use `clock.nowDate()` to get a `LocalDate` in UTC, or `clock.nowDateTime()` to get an `OffsetDateTime` in UTC.
- When defining timestamps for tests, prefer using a fixed, static constant (e.g., `Instant.parse("2024-03-27T10:15:30.105Z")`) over capturing `clock.now()` to prevent flaky tests caused by the passage of real time.
- **Beam Pipelines:**
- Ensure `Clock` is serializable (it is by default in this project) when used in Beam `DoFn`s.
- Pass the `Clock` through the constructor or via Dagger provider methods in the pipeline module.
@@ -36,26 +35,33 @@ This document outlines foundational mandates, architectural patterns, and projec
- **Test Components:** Use `TestRegistryToolComponent` for command-line tool tests to bridge the gap between `main` and `nonprod/test` source sets.
### 4. Database Consistency
- **JPA Converters:** Be aware that JPA converters (like `DateTimeConverter`) may perform truncation or transformation. Ensure application-level logic matches these transformations to avoid "dirty" state or unexpected diffs.
- **Transaction Management:**
- **Top-Level:** Define database transactions (`tm().transact(...)`) at the highest possible level in the call chain (e.g., in an Action, a Command, or a Flow). This ensures all operations are atomic and handled by the retry logic.
- **DAO Methods:** Avoid declaring transactions inside low-level DAO methods. Use `tm().assertInTransaction()` to ensure that these methods are only called within a valid transactional context.
- **Utility/Cache Methods:** Use `tm().reTransact(...)` for utility methods or Caffeine cache loaders that might be invoked from both transactional and non-transactional paths.
- `reTransact` will join an existing transaction if one is present (acting as a no-op) or start a new one if not.
- This is particularly useful for in-memory caches where the loader must be able to fetch data regardless of whether the caller is currently in a transaction.
- **Transactional Time:** Ensure code that relies on `tm().getTransactionTime()` is executed within a transaction context.
- **Test Helpers & Timestamps:** If a static test helper method (like in `DatabaseHelper`) needs the database transaction time but might be called from outside a transaction, using `tm().reTransact(tm()::getTxTime)` is acceptable. However, NEVER wrap it redundantly like `tm().transact(() -> tm().reTransact(tm()::getTxTime))`. If you are just setting an arbitrary timestamp in a test where the exact DB transaction time isn't strictly required, prefer `Instant.now()` or `clock.now()` to avoid creating unnecessary database transactions.
- **Production Code:** In production code, if a flow fails because it is calling `getTxTime()` outside of a transaction, you must wrap the *caller* in a transaction instead of adding an unnecessary `reTransact()` around `getTxTime()`.
- **Transactional Time:** Ensure code that relies on `tm().getTransactionTime()` (or `tm().getTxTime()`) is executed within a transaction context.
### 5. Testing Best Practices
- **FakeClock and Sleeper:** Use `FakeClock` and `Sleeper` for any logic involving timeouts, delays, or expiration.
- **Empirical Reproduction:** Before fixing a bug, always create a test case that reproduces the failure.
- **Base Classes:** Leverage `CommandTestCase`, `EppToolCommandTestCase`, etc., to reduce boilerplate and ensure consistent setup (e.g., clock initialization).
- **Gradle Test Patterns:** When running tests to investigate fixes in the "core" directory, try to first use the "standardTest" Gradle task. It is faster than the "test" task, which includes the "fragileTest" task. Only run the full "test" task after "standardTest" succeeds.
### 6. Project Dependencies
- **Common Module:** When using `Clock` or other core utilities in a new or separate module (like `load-testing`), ensure `implementation project(':common')` is added to the module's `build.gradle`.
### 7. Search and Discovery
- **No CodeSearch:** This project is hosted on GitHub, not Google3. Do NOT use `mcp_Coding_search_for_files_codesearch` or other internal Google3 search tools.
- **Local Grep:** Use local shell commands like `git grep` or `grep` via `run_shell_command` to search the codebase.
## 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.
- **Code Formatting:** Do not write custom Python scripts or manual regex replacements to fix code formatting issues (e.g., unused imports, import ordering, line length). Instead, use the project's built-in formatting tools: run `./gradlew spotlessApply` to fix unused/unordered imports and `./gradlew javaIncrementalFormatApply` (or `google-java-format --replace <files>`) to automatically fix Java formatting and indentation errors.
## General Code Review Lessons & Avoidable Mistakes
Based on historical PR reviews, avoid the following common mistakes:
@@ -66,6 +72,7 @@ Based on historical PR reviews, avoid the following common mistakes:
- **Immutable Types:** Declare variables, fields, and return types explicitly as Guava immutable types (e.g., `ImmutableList<T>`, `ImmutableMap<K, V>`) instead of their generic interfaces (`List<T>`, `Map<K, V>`) to clearly communicate immutability contracts to callers. Use `toImmutableList()` and `toImmutableMap()` collectors in streams rather than manually accumulating into an `ArrayList` or `HashMap`.
- **Constructors:** Do not perform heavy logic, I/O, or external API calls inside constructors. Initialization logic should be deferred or handled in a factory method or a dedicated startup routine.
- **Exception Handling:** Do not catch generic `Exception` or `Throwable` if a more specific exception is expected. Never "log and re-throw" the same exception; either handle it entirely (and log), or throw it up the chain. For batch processes, catch exceptions at the individual item/chunk level so one failure doesn't abort the entire batch.
- **Optional Assertions:** Prefer Truth's `.hasValue(...)` over `.isEqualTo(Optional.of(...))` for cleaner and more descriptive assertions on `Optional` types.
- **Fail Fast:** Validate inputs and fail fast (using `Preconditions.checkArgument` or similar) at the highest level possible rather than passing invalid state (like `null`s) deeper into business logic.
- **Magic Numbers:** Always document magic numbers or hardcoded limits (like `50.0` or `30`) with inline comments explaining the rationale.
- **Null Safety and Optional:** Prefer using `Optional` for any variable that is expected to potentially be null. For any other variable that can be null but cannot use an `Optional` (e.g., function parameters or return types where `Optional` is not idiomatic), it MUST be annotated with `@Nullable`. Always use the `javax.annotation.Nullable` annotation.
@@ -81,59 +88,67 @@ This document captures high-level architectural patterns, lessons learned from l
- **Transaction Management:** The codebase uses a custom wrapper around JPA. Always use `tm()` (from `TransactionManagerFactory`) to interact with the database.
- **Dependency Injection:** Dagger 2 is used extensively. If you see "cannot find symbol" errors for classes starting with `Dagger...`, the project is in a state where annotation processing failed. Fix compilation in core models first to restore generated code.
- **Value Types:** AutoValue and "ImmutableObject" patterns are dominant. Most models follow a `Buildable` pattern with a nested `Builder`.
- **Temporal Logic:** The project is migrating from Joda-Time to `java.time`.
- Core boundaries: `DateTimeUtils.START_OF_TIME_INSTANT` (Unix Epoch) and `END_OF_TIME_INSTANT` (Long.MAX_VALUE / 1000).
- Year Arithmetic: Use `DateTimeUtils.plusYears()` and `DateTimeUtils.minusYears()` to handle February 29th logic correctly.
- **Temporal Logic:** The project uses `java.time` for all temporal representations.
- Core boundaries: `DateTimeUtils.START_INSTANT` (Unix Epoch) and `DateTimeUtils.END_INSTANT` (Long.MAX_VALUE / 1000).
## Source Control
- **Committing:** Always create a new commit on the branch if one hasn't been created yet for the branch's specific work. Only perform amending (`git commit --amend --no-edit`) for subsequent changes once the initial commit has been successfully created.
- **One Commit Per PR:** All changes for a single PR must be squashed into a single commit before merging.
- **Default to Amend:** Once an initial commit is created for a PR, all subsequent functional changes should be amended into that same commit by default (`git commit --amend --no-edit`). This ensures the PR remains a single, clean unit of work throughout the development lifecycle.
- **Commit Message Style:** Follow standard Git commit best practices. The subject line (first line) should be concise, capitalized, and **must not end with punctuation** (e.g., a period).
- **Final Validation:** Always run `git status` as the final step before declaring a task complete to ensure all changes are committed and the working directory is clean.
- **Commit Verification:** After any commit or amendment, explicitly verify the success of the operation (e.g., using `git status` and reviewing the diff). Never report a Git operation as "done" without having first successfully executed the command and confirmed the repository state.
- **Commit Message Style:** Follow standard Git commit best practices. The subject line (first line) MUST be a maximum of 50 characters, concise, capitalized, and **must not end with punctuation** (e.g., a period). The body MUST explicitly encapsulate and summarize all changes made across the entire diff, detailing the "what" and "why" comprehensively.
- **Strict Completion Verification:** You MUST NEVER declare a task, commit, or amendment as complete until you have explicitly verified that the workspace is clean. You MUST follow this exact sequence of actions across multiple conversational turns if necessary:
1. Execute the `git commit` or `git commit --amend` command.
2. Wait for the tool to return successfully.
3. Execute `git status`.
4. Wait for the tool to return and explicitly verify the output contains `nothing to commit, working tree clean` (or similar indication that no unstaged changes remain). If changes remain, stage them and amend the commit, then repeat this verification loop.
5. **Only after** step 4 has successfully returned a clean working directory may you generate a text response to the user declaring that the task is complete.
- **Diff Review:** Before finalizing a task, review the full diff (e.g., `git diff HEAD^`) to ensure all changes are functional and relevant. Identify and revert any formatting-only changes in files that do not contain functional updates to keep the commit focused.
## Self-Review Guidelines
Before finalizing any PR or declaring a task complete, you MUST perform a thorough, rigorous self-review of your entire diff. Run `git diff HEAD^` (or review the staged changes) and actively verify the following against every modified line:
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.util.Date` and `java.sql.Date`), one MUST remain fully qualified to avoid a compilation conflict.
2. **Diff Scope:** Are there any formatting-only changes in files that I did not functionally modify? If so, revert them. Does the total line count of the diff align with the approved scope (e.g., ~1,000 lines for migrations)?
3. **Commit Message:** Does the commit message title fit within 50 characters? Does the body encapsulate the entirety of the changes across the diff cleanly and professionally?
4. **Missing Tests & Coverage:** *Perform a structured check for any new methods or modified behavior.* Did I add a new utility method (like `plusMonths(Instant, int)`) or change core logic? If so, I MUST open the corresponding test file and write tests to cover the new functionality (including edge cases, negative values, and leap years) before considering the task complete. A code review is not thorough if it only checks for compilation. I must actively ensure every new branch of logic has a test.
5. **Package Lock:** Did I include `console-webapp/package-lock.json` in my diff? If so, I MUST revert it (`git checkout console-webapp/package-lock.json`) unless I explicitly intended to modify NPM dependencies. This file is often modified by the build process and should not be committed accidentally.
Only after actively confirming these checks against your diff are you permitted to finalize the task.
## Refactoring & Migration Guardrails
### 1. Compiler Warnings are Errors (`-Werror`)
This project treats Error Prone warnings as errors.
- **`@InlineMeSuggester`**: When creating deprecated Joda-Time bridge methods (e.g., `getTimestamp() -> return toDateTime(getTimestampInstant())`), you **MUST** immediately add `@SuppressWarnings("InlineMeSuggester")`. If you don't, the build will fail.
- **Repeatable Annotations**: `@SuppressWarnings` is **NOT** repeatable in this environment. If a method or class already has a suppression (e.g., `@SuppressWarnings("unchecked")`), you must merge them:
-`@SuppressWarnings("unchecked") @SuppressWarnings("InlineMeSuggester")`
-`@SuppressWarnings({"unchecked", "InlineMeSuggester"})`
-`@SuppressWarnings("unchecked") @SuppressWarnings("MustBeClosedChecker")`
-`@SuppressWarnings({"unchecked", "MustBeClosedChecker"})`
### 2. Resolving Ambiguity
- **Null Overloads**: Adding an `Instant` overload to a method that previously took `DateTime` will break all `create(null)` calls. You must cast them: `create((Instant) null)`.
- **Type Erasure**: Methods taking `Optional<DateTime>` and `Optional<Instant>` will clash due to erasure. Use distinct names, e.g., `setAutorenewEndTimeInstant(Optional<Instant> time)`.
### 3. Build Strategy
- **Surgical Changes**: In large-scale migrations, focus on "leaf" nodes first (Utilities -> Models -> Flows -> Actions).
- **PR Size**: Minimize PR size by retaining Joda-Time bridge methods for high-level "Action" and "Flow" classes unless a full migration is requested. Reverting changes to DNS and Reporting logic while updating the underlying models is a valid strategy to keep PRs reviewable.
- **Validation**: Always run `./gradlew build -x test` before attempting to run unit tests. Unit tests will not run if there are compilation errors in any part of the `core` module. Before finalizing a PR or declaring a task done, you MUST run the entire build using `./gradlew build` and verify that it succeeds completely without errors. Do not declare success if formatting checks (e.g., `spotlessCheck` or `javaIncrementalFormatCheck`) or tests fail. If formatting fails, run `./gradlew spotlessApply` and then re-run `./gradlew build` to verify everything passes.
### 2. Build Strategy
- **Validation**: Always run `./gradlew build -x test` before attempting to run unit tests. Unit tests will not run if there are compilation errors in any part of the `core` module. Before finalizing a PR or declaring a task done, you MUST verify your changes. **Prefer scoped builds** (e.g., `./gradlew :core:build`) if you are only modifying backend Java code. Running the global `./gradlew build` triggers the frontend `console-webapp` build, which unnecessarily runs `npmInstallDeps` and modifies `package-lock.json`. If you must run a global build, you must revert `console-webapp/package-lock.json` afterwards. Do not declare success if formatting checks (e.g., `spotlessCheck` or `javaIncrementalFormatCheck`) or tests fail. If formatting fails, run `./gradlew spotlessApply` and then re-run your build command to verify everything passes.
## 🚫 Common Pitfalls to Avoid
- **Do not go in circles with the build:** If you see an `InlineMeSuggester` error, apply the suppression to **ALL** similar methods in that file and related files in one turn. Do not fix them one by one.
- **Serialization Precision (`.000Z`):** When asserting against or generating XML/YAML files, remember that millisecond precision (`.000Z`) is required. Always use `DateTimeUtils.formatInstant(...)` to format `Instant` objects (it preserves the `.000Z` suffix) instead of `Instant.toString()` (which drops it for exact seconds). We have added custom Jackson `InstantKeySerializer`s for this purpose, but you must keep this precision in mind when manually updating `.xml` or `.yaml` test data.
- Dagger/AutoValue corruption: If you modify a builder or a component incorrectly, Dagger will fail to generate code, leading to hundreds of "cannot find symbol" errors. If this happens, `git checkout` the last working state of the specific file and re-apply changes more surgically.
- **`replace` tool context**: When using `replace` on large files (like `Tld.java` or `DomainBase.java`), provide significant surrounding context. These files have many similar method signatures (getters/setters) that can lead to incorrect replacements.
---
# GitHub and Pull Request Protocol
## GitHub and Pull Request Protocol
This protocol defines the standard for interacting with GitHub repositories and processing Pull Request (PR) feedback.
## 1. Interaction via `gh` CLI
### 1. Interaction via `gh` CLI
- **Primary Tool:** ALWAYS use the `gh` CLI for all GitHub-related operations (listing PRs, viewing PR content, checking status, adding comments).
- **Credential Safety:** Never expose tokens or credentials in shell commands.
## 2. Processing PR Feedback
### 2. Processing PR Feedback
- **Systematic Review:** When asked to address PR comments, first fetch all comments using `gh pr view <number> --json reviews,comments`.
- **Minimal Scope Expansion:** Address comments surgically. If a fix requires changes beyond a few lines or expands the PR's original scope significantly, DO NOT implement it without explicit user approval. Instead, report the issue to the user.
- **Verification:** After addressing feedback, run the full build (`./gradlew build`) and relevant tests to ensure no regressions were introduced.
## 3. PR Lifecycle Management
### 3. PR Lifecycle Management
- **One Commit Per PR:** Ensure all changes are squashed into a single, clean commit. Use `git commit --amend --no-edit` for follow-up fixes.
- **Clean Workspace:** Always run `git status` and verify the repository state before declaring a task complete.
- **Package Lock:** The Gradle build automatically modifies `console-webapp/package-lock.json` via the `npmInstallDeps` task. ALWAYS revert this file (`git checkout console-webapp/package-lock.json`) before staging changes or finalizing a commit unless you explicitly modified NPM dependencies.

View File

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

View File

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

View File

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

View File

@@ -19,38 +19,18 @@ import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import java.sql.Date;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import java.time.temporal.ChronoUnit;
/** Utilities methods and constants related to Joda {@link DateTime} objects. */
public abstract class DateTimeUtils {
/** The start of the epoch, in a convenient constant. */
@Deprecated public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC);
/** The start of the UNIX epoch (which is defined in UTC), in a convenient constant. */
public static final Instant START_INSTANT = Instant.ofEpochMilli(0);
/**
* A date in the far future that we can treat as infinity.
*
* <p>This value is (2^63-1)/1000 rounded down. Postgres can store dates as 64 bit microseconds,
* but Java uses milliseconds, so this is the largest representable date that will survive a
* round-trip through the database.
*/
@Deprecated
public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, DateTimeZone.UTC);
/**
* An instant in the far future that we can treat as infinity.
*
@@ -65,15 +45,25 @@ public abstract class DateTimeUtils {
*
* <p>Example: {@code 2024-03-27T10:15:30.105Z}
*
* <p>Handles large/negative years by using a sign prefix if necessary, compatible with {@link
* Instant#parse}.
* <p>Note: We deliberately strip the leading {@code +} sign from the formatted year field if
* present. While standard ISO 8601 specifies that years with more than 4 digits should be
* prefixed with a {@code +} sign, W3C XML Schema 1.0 (which our EPP RDE XSD uses) strictly
* forbids leading plus signs in {@code xsd:dateTime} strings. Suppressing the plus sign ensures
* our generated XML continues to pass strict XSD validation for large years (e.g. {@code
* 294247-01-10T04:00:54.775Z}).
*/
public static final DateTimeFormatter ISO_8601_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NORMAL)
.appendPattern("-MM-dd'T'HH:mm:ss.SSS'Z'")
.toFormatter()
.withZone(ZoneOffset.UTC);
private static final DateTimeFormatter ISO_8601_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);
/** A formatter that produces lowercase, filename-safe and job-name-safe timestamps. */
public static final DateTimeFormatter LOWERCASE_TIMESTAMP_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd't'HH-mm-ss'z'").withZone(ZoneOffset.UTC);
/** Formats an {@link Instant} to an ISO-8601 string. */
public static String formatInstant(Instant instant) {
String formatted = ISO_8601_FORMATTER.format(instant);
return formatted.startsWith("+") ? formatted.substring(1) : formatted;
}
/**
* Parses an ISO-8601 string to an {@link Instant}.
@@ -83,74 +73,48 @@ public abstract class DateTimeUtils {
* large years (e.g. {@code 294247-01-10T04:00:54.775Z}).
*/
public static Instant parseInstant(String timestamp) {
if (!timestamp.startsWith("+") && !timestamp.startsWith("-")) {
int dashIndex = timestamp.indexOf('-');
if (dashIndex > 4) {
timestamp = "+" + timestamp;
}
}
try {
// Try the standard millisecond precision format first.
return Instant.from(ISO_8601_FORMATTER.parse(timestamp));
return Instant.from(DateTimeFormatter.ISO_INSTANT.parse(timestamp));
} catch (DateTimeParseException e) {
// Fall back to the standard ISO instant parser which handles varied precision.
return Instant.parse(timestamp);
}
}
/** Returns the earliest of a number of given {@link DateTime} instances. */
public static DateTime earliestOf(DateTime first, DateTime... rest) {
return earliestDateTimeOf(Lists.asList(first, rest));
}
/** Returns the earliest of a number of given {@link Instant} instances. */
public static Instant earliestOf(Instant first, Instant... rest) {
return earliestOf(Lists.asList(first, rest));
}
/** Returns the earliest element in a {@link DateTime} iterable. */
public static DateTime earliestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().min(dates);
}
/** Returns the earliest element in a {@link Instant} iterable. */
/** Returns the earliest element in an {@link Instant} iterable. */
public static Instant earliestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().min(instants);
}
/** Returns the latest of a number of given {@link DateTime} instances. */
public static DateTime latestOf(DateTime first, DateTime... rest) {
return latestDateTimeOf(Lists.asList(first, rest));
}
/** Returns the latest of a number of given {@link Instant} instances. */
public static Instant latestOf(Instant first, Instant... rest) {
return latestOf(Lists.asList(first, rest));
}
/** Returns the latest element in a {@link DateTime} iterable. */
public static DateTime latestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().max(dates);
}
/** Returns the latest element in a {@link Instant} iterable. */
/** Returns the latest element in an {@link Instant} iterable. */
public static Instant latestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().max(instants);
}
/** Returns whether the first {@link DateTime} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(DateTime timeToCheck, DateTime timeToCompareTo) {
return !timeToCheck.isAfter(timeToCompareTo);
}
/** Returns whether the first {@link Instant} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isAfter(timeToCompareTo);
}
/** Returns whether the first {@link DateTime} is equal to or later than the second. */
public static boolean isAtOrAfter(DateTime timeToCheck, DateTime timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
}
/** Returns whether the first {@link Instant} is equal to or later than the second. */
public static boolean isAtOrAfter(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
@@ -158,36 +122,30 @@ public abstract class DateTimeUtils {
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link DateTime#plusYears} to ensure that we never end up on February 29.
* {@link java.time.OffsetDateTime#plusYears} to ensure that we never end up on February 29.
*/
public static DateTime plusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.plusYears(1).plusYears(years - 1);
}
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link java.time.ZonedDateTime#plusYears} to ensure that we never end up on February 29.
*/
public static Instant plusYears(Instant now, long years) {
public static Instant plusYears(Instant now, int 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.
*/
public static DateTime minusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.minusYears(1).minusYears(years - 1);
/** Adds months to a date. */
public static Instant plusMonths(Instant now, int months) {
checkArgument(months >= 0);
return now.atZone(ZoneOffset.UTC).plusMonths(months).toInstant();
}
/** Subtracts months from a date. */
public static Instant minusMonths(Instant now, int months) {
checkArgument(months >= 0);
return now.atZone(ZoneOffset.UTC).minusMonths(months).toInstant();
}
/**
* Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead
* of {@link java.time.ZonedDateTime#minusYears} to ensure that we never end up on February 29.
* of {@link java.time.OffsetDateTime#minusYears} to ensure that we never end up on February 29.
*/
public static Instant minusYears(Instant now, long years) {
checkArgument(years >= 0);
@@ -196,55 +154,40 @@ public abstract class DateTimeUtils {
: now.atZone(ZoneOffset.UTC).minusYears(1).minusYears(years - 1).toInstant();
}
/**
* @deprecated Use {@link #plusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeAddYears(DateTime now, int years) {
return plusYears(now, years);
/** Converts an Instant to a java.time.LocalDate in UTC. */
public static LocalDate toLocalDate(Instant instant) {
return instant.atZone(ZoneOffset.UTC).toLocalDate();
}
/**
* @deprecated Use {@link #minusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeSubtractYears(DateTime now, int years) {
return minusYears(now, years);
public static Instant plusHours(Instant instant, long hours) {
return instant.plus(hours, ChronoUnit.HOURS);
}
public static Date toSqlDate(LocalDate localDate) {
return new Date(localDate.toDateTimeAtStartOfDay().getMillis());
public static Instant minusHours(Instant instant, long hours) {
return instant.minus(hours, ChronoUnit.HOURS);
}
public static LocalDate toLocalDate(Date date) {
return new LocalDate(date.getTime(), DateTimeZone.UTC);
public static Instant plusMinutes(Instant instant, long minutes) {
return instant.plus(minutes, ChronoUnit.MINUTES);
}
/** 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());
public static Instant minusMinutes(Instant instant, long minutes) {
return instant.minus(minutes, ChronoUnit.MINUTES);
}
/** 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);
public static Instant plusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).plusWeeks(weeks).toInstant();
}
/** 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 minusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).minusWeeks(weeks).toInstant();
}
public static Instant plusDays(Instant instant, int days) {
public static Instant plusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).plusDays(days).toInstant();
}
public static Instant minusDays(Instant instant, int days) {
public static Instant minusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).minusDays(days).toInstant();
}
}

View File

@@ -14,8 +14,8 @@
package google.registry.util;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
/**
* An object which accepts requests to put the current thread to sleep.
@@ -30,7 +30,7 @@ public interface Sleeper {
*
* @throws InterruptedException if this thread was interrupted
*/
void sleep(ReadableDuration duration) throws InterruptedException;
void sleep(Duration duration) throws InterruptedException;
/**
* Puts the current thread to sleep, ignoring interrupts.
@@ -40,7 +40,7 @@ public interface Sleeper {
*
* @see com.google.common.util.concurrent.Uninterruptibles#sleepUninterruptibly
*/
void sleepUninterruptibly(ReadableDuration duration);
void sleepUninterruptibly(Duration duration);
/**
* Puts the current thread to interruptible sleep.
@@ -48,7 +48,7 @@ public interface Sleeper {
* <p>This is a convenience method for {@link #sleep} that properly converts an {@link
* InterruptedException} to a {@link RuntimeException}.
*/
default void sleepInterruptibly(ReadableDuration duration) {
default void sleepInterruptibly(Duration duration) {
try {
sleep(duration);
} catch (InterruptedException e) {

View File

@@ -14,13 +14,11 @@
package google.registry.util;
import static org.joda.time.DateTimeZone.UTC;
import static java.time.temporal.ChronoUnit.MILLIS;
import jakarta.inject.Inject;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.DateTime;
/** Clock implementation that proxies to the real system clock. */
@ThreadSafe
@@ -31,18 +29,11 @@ public class SystemClock implements Clock {
@Inject
public SystemClock() {}
/** Returns the current time. */
@Override
public DateTime nowUtc() {
return DateTime.now(UTC);
}
@Override
public Instant now() {
// Truncate to milliseconds to match the precision of Joda DateTime and our database schema
// (which uses millisecond precision via DateTimeConverter). This prevents subtle comparison
// bugs where a high-precision Instant would be considered "after" a truncated database
// timestamp.
return Instant.now().truncatedTo(ChronoUnit.MILLIS);
// Truncate to milliseconds to match the precision of our database schema.
// This prevents subtle comparison bugs where a high-precision Instant would be
// considered "after" a truncated database timestamp.
return Instant.now().truncatedTo(MILLIS);
}
}

View File

@@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.util.concurrent.Uninterruptibles;
import jakarta.inject.Inject;
import java.io.Serializable;
import java.time.Duration;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
/** Implementation of {@link Sleeper} for production use. */
@ThreadSafe
@@ -32,14 +32,14 @@ public final class SystemSleeper implements Sleeper, Serializable {
public SystemSleeper() {}
@Override
public void sleep(ReadableDuration duration) throws InterruptedException {
checkArgument(duration.getMillis() >= 0);
Thread.sleep(duration.getMillis());
public void sleep(Duration duration) throws InterruptedException {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
Thread.sleep(duration.toMillis());
}
@Override
public void sleepUninterruptibly(ReadableDuration duration) {
checkArgument(duration.getMillis() >= 0);
Uninterruptibles.sleepUninterruptibly(java.time.Duration.ofMillis(duration.getMillis()));
public void sleepUninterruptibly(Duration duration) {
checkArgument(!duration.isNegative(), "Duration must be non-negative");
Uninterruptibles.sleepUninterruptibly(duration);
}
}

View File

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

View File

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

View File

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

View File

@@ -102,9 +102,25 @@ PRESUBMITS = {
{"node_modules/", ".idea"}, REQUIRED):
"Source files must end in a newline.",
# Files must not end with extraneous blank lines
PresubmitCheck(
r".*\n\n$",
("java", "js", "soy", "sql", "py", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea", "nomulus.golden.sql"},
):
"Source files must not end with extraneous blank lines.",
# Duplicate empty lines
PresubmitCheck(
r".*\n\n\n.*",
("java", "js", "soy", "sh", "gradle", "ts", "xml"),
{"node_modules/", ".idea"},
):
"Source files must not contain duplicate empty lines.",
# System.(out|err).println should only appear in tools/ or load-testing/
PresubmitCheck(
r".*\bSystem\.(out|err)\.print", "java", {
r".*\bSystem\s*\.\s*(?:out|err)\s*\.\s*print.*", "java", {
"/tools/", "/example/", "/load-testing/",
"RegistryTestServerMain.java", "TestServerExtension.java"
}):
@@ -139,7 +155,7 @@ PRESUBMITS = {
):
"All soy templates must use strict autoescaping",
PresubmitCheck(
r".*\nimport (static )?.*\.shaded\..*",
r".*\nimport\s+(?:static\s+)?.*\.shaded\..*",
"java",
{"/node_modules/"},
):
@@ -153,7 +169,16 @@ PRESUBMITS = {
PresubmitCheck(
r".*java\.util\.Date.*",
"java",
{"/node_modules/", "JpaTransactionManagerImpl.java", "DateTimeUtils.java"},
{
"/node_modules/",
"JpaTransactionManagerImpl.java",
"DateTimeUtils.java",
"SelfSignedCaCertificate.java",
"X509Utils.java",
"TmchCertificateAuthority.java",
"DelegatedCredentials.java",
"SslInitializerTestUtils.java"
},
):
"Do not use java.util.Date. Use classes in java.time package instead.",
PresubmitCheck(
@@ -163,7 +188,7 @@ PRESUBMITS = {
):
"Use status code from jakarta.servlet.http.HttpServletResponse.",
PresubmitCheck(
r".*mock\(Response\.class\).*",
r".*mock\(\s*Response\.class\s*\).*",
"java",
{"/node_modules/"},
):
@@ -181,13 +206,37 @@ PRESUBMITS = {
):
"Do not use javax.inject.* Use jakarta.inject.* instead.",
PresubmitCheck(
r".*import jakarta.persistence.(Pre|Post)(Persist|Load|Remove|Update);",
r".*import\s+jakarta\.persistence\.(?:Pre|Post)(?:Persist|Load|Remove|Update)\s*;",
"java",
{"EntityCallbacksListener.java"},
):
"Hibernate lifecycle events aren't called for embedded entities, so it's "
"usually best to avoid them. Instead, use the annotations defined in "
"EntityCallbacksListener.java"
"EntityCallbacksListener.java",
PresubmitCheck(
r".*\.isEqualTo\(\s*Optional\.of\(.*",
"java",
{},
):
"Do not use .isEqualTo(Optional.of(...)). Use Truth's .hasValue(...) instead.",
PresubmitCheck(
r".*java\.time\.ZonedDateTime.*",
"java",
{},
):
"Do not use java.time.ZonedDateTime. Use java.time.OffsetDateTime per go/avoid-zdt.",
PresubmitCheck(
r".*ZoneId\.of\(\s*\"UTC\"\s*\).*",
"java",
{},
):
"Do not use ZoneId.of(\"UTC\"). Use java.time.ZoneOffset.UTC.",
PresubmitCheck(
r".*org\.joda\.time.*",
"java",
{"SafeBrowsingTransforms.java"},
):
"Do not use Joda-Time. Use java.time instead.",
}
# Note that this regex only works for one kind of Flyway file. If we want to

View File

@@ -629,15 +629,15 @@
}
},
"node_modules/@angular/build/node_modules/@types/node": {
"version": "25.5.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.5.0.tgz",
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
"version": "25.7.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/@types/node/-/node-25.7.0.tgz",
"integrity": "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"undici-types": "~7.18.0"
"undici-types": "~7.21.0"
}
},
"node_modules/@angular/build/node_modules/@vitejs/plugin-basic-ssl": {
@@ -744,9 +744,9 @@
}
},
"node_modules/@angular/build/node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"version": "7.21.0",
"resolved": "https://us-npm.pkg.dev/artifact-foundry-prod/ah-3p-staging-npm/undici-types/-/undici-types-7.21.0.tgz",
"integrity": "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==",
"dev": true,
"license": "MIT",
"optional": true,

View File

@@ -190,12 +190,14 @@ dependencies {
testRuntimeOnly deps['guru.nidi:graphviz-java-all-j2v8']
testImplementation deps['io.github.classgraph:classgraph']
testRuntimeOnly deps['io.github.java-diff-utils:java-diff-utils']
testImplementation deps['io.github.ss-bhatt:testcontainers-valkey']
implementation deps['io.protostuff:protostuff-core']
implementation deps['io.protostuff:protostuff-runtime']
implementation deps['jakarta.inject:jakarta.inject-api']
implementation deps['jakarta.mail:jakarta.mail-api']
implementation deps['jakarta.persistence:jakarta.persistence-api']
implementation deps['jakarta.servlet:jakarta.servlet-api']
implementation deps['jakarta.xml.bind:jakarta.xml.bind-api']
implementation deps['joda-time:joda-time']
implementation deps['org.antlr:antlr4']
implementation deps['org.antlr:antlr4-runtime']
implementation deps['org.apache.avro:avro']
@@ -243,6 +245,7 @@ dependencies {
implementation deps['org.testcontainers:postgresql']
testImplementation deps['org.testcontainers:selenium']
testImplementation deps['org.testcontainers:testcontainers']
implementation deps['redis.clients:jedis']
implementation deps['us.fatehi:schemacrawler']
implementation deps['us.fatehi:schemacrawler-api']
implementation deps['us.fatehi:schemacrawler-diagram']
@@ -475,7 +478,6 @@ Optional<List<String>> getToolArgsList() {
return Optional.empty()
}
// To run the nomulus tools with these command line tokens:
// "--foo", "bar baz", "--qux=quz"
// gradle core:registryTool --args="--foo 'bar baz' --qux=quz"
@@ -575,6 +577,11 @@ if (environment == 'alpha') {
mainClass: 'google.registry.beam.resave.ResaveAllEppResourcesPipeline',
metaData: 'google/registry/beam/resave_all_epp_resources_pipeline_metadata.json'
],
smokeTest:
[
mainClass: 'google.registry.beam.common.SmokeTestPipeline',
metaData: 'google/registry/beam/smoke_test_pipeline_metadata.json'
],
]
project.tasks.create("stageBeamPipelines") {
doLast {
@@ -810,7 +817,6 @@ test {
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
// When we override tests, we also break the cleanTest command.
cleanTest.dependsOn(cleanFragileTest, cleanStandardTest,
cleanRegistryToolIntegrationTest, cleanSqlIntegrationTest)

View File

@@ -13,19 +13,18 @@ com.fasterxml.jackson.datatype:jackson-datatype-joda:2.20.2=compileClasspath,dep
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.jackson:jackson-bom:2.20.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.fasterxml.woodstox:woodstox-core:7.0.0=testCompileClasspath,testRuntimeClasspath
com.fasterxml:classmate:1.7.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.github.ben-manes.caffeine:caffeine:3.2.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.ben-manes.caffeine:caffeine:3.2.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-api:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport-zerodep:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.docker-java:docker-java-transport:3.4.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jffi:1.3.14=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jffi:1.3.15=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-a64asm:1.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-constants:0.10.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-enxio:0.32.19=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-ffi:2.2.18=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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-enxio:0.32.20=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-ffi:2.2.19=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-posix:3.1.22=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.github.jnr:jnr-unixsocket:0.38.25=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,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.android:annotations:4.1.1.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -36,82 +35,59 @@ com.google.api-client:google-api-client-servlet:2.7.0=deploy_jar,nonprodRuntimeC
com.google.api-client:google-api-client-servlet:2.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api-client:google-api-client:2.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.9.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.181.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.181.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.181.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.181.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.43.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.44.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.114.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.115.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.14.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-pubsublite-v1:1.14.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:gapic-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta1:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigquerystorage-v1beta2:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-bigtable-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-pubsub-v1:1.130.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-database-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-admin-instance-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.43.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:grpc-google-common-protos:2.45.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.9.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.9.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.9.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.181.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.181.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.181.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.181.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.43.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.44.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.43.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.44.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:grpc-google-common-protos:2.65.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1alpha:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta1:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta2:0.193.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigquerystorage-v1beta:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-admin-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-bigtable-v2:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-compute-v1:1.82.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.112.2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.113.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.25.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.26.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.114.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.115.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.14.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-pubsublite-v1:1.14.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-datastore-v1:0.125.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-firestore-v1:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-monitoring-v3:3.85.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-pubsub-v1:1.130.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-secretmanager-v1beta2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-executor-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-database-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-admin-instance-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-spanner-v1:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-control-v2:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.67.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-storage-v2:2.68.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta2:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-cloud-tasks-v2beta3:0.141.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-common-protos:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.50.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.65.0=testCompileClasspath,testRuntimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.60.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api.grpc:proto-google-iam-v1:1.66.0=testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.57.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:api-common:2.62.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-grpc:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.69.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-httpjson:2.79.0=testCompileClasspath,testRuntimeClasspath
com.google.api:api-common:2.63.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-grpc:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-grpc:2.80.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax-httpjson:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.api:gax-httpjson:2.80.0=testCompileClasspath,testRuntimeClasspath
com.google.api:gax:2.74.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-admin-directory:directory_v1-rev20260227-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-bigquery:v2-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-bigquery:v2-rev20251012-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-cloudresourcemanager:v1-rev20250606-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dataflow:v1b3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260402-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260405-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260112-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-dns:v1-rev20260421-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-drive:v3-rev20260428-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-gmail:v1-rev20260427-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-groupssettings:v1-rev20220614-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-healthcare:v1-rev20240130-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-iam:v2-rev20250502-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -119,61 +95,52 @@ com.google.apis:google-api-services-iamcredentials:v1-rev20211203-2.0.0=compileC
com.google.apis:google-api-services-monitoring:v3-rev20260129-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-pubsub:v1-rev20220904-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sheets:v4-rev20260213-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20251201-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20250312-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.apis:google-api-services-sqladmin:v1beta4-rev20260317-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.apis:google-api-services-storage:v1-rev20251118-2.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.apis:google-api-services-storage:v1-rev20260204-2.0.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-credentials:1.46.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.43.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.46.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-credentials:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-credentials:1.47.0=testCompileClasspath,testRuntimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.46.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.auth:google-auth-library-oauth2-http:1.47.0=testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service-annotations:1.0.1=nonprodAnnotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.auto.service:auto-service:1.1.1=annotationProcessor
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,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.value:auto-value:1.11.1=annotationProcessor,deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testRuntimeClasspath
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.bigdataoss:gcsio:2.2.26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.bigdataoss:util:2.2.26=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
com.google.cloud.datastore:datastore-v1-proto-client:2.21.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.31.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.33.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud.datastore:datastore-v1-proto-client:2.34.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.opentelemetry:detector-resources-support:0.33.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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,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
com.google.cloud:google-cloud-bigtable:2.44.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud.sql:jdbc-socket-factory-core:1.28.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud.sql:postgres-socket-factory:1.28.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigquerystorage:3.21.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-bigtable:2.73.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-compute:1.82.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.54.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-grpc:2.64.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-grpc:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.54.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.cloud:google-cloud-core-http:2.69.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core-http:2.70.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-core:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.25.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-firestore:3.26.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.52.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.131.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.132.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-pubsub:1.133.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsublite:1.14.1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-pubsublite:1.14.3=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-firestore:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-monitoring:3.85.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-nio:0.132.0=testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-pubsub:1.148.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-secretmanager:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.74.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.cloud:google-cloud-spanner:6.77.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-spanner:6.111.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage-control:2.44.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-storage:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:google-cloud-tasks:2.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:grpc-gcp:1.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.cloud:grpc-gcp:1.9.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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.cloud:proto-google-cloud-firestore-bundle-v1:3.37.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,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.code.gson:gson:2.13.2=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
com.google.dagger:dagger-compiler:2.59.2=annotationProcessor,testAnnotationProcessor
com.google.dagger:dagger-spi:2.59.2=annotationProcessor,testAnnotationProcessor
@@ -182,17 +149,15 @@ com.google.devtools.ksp:symbol-processing-api:2.2.20-2.0.3=annotationProcessor,t
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.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_annotations:2.48.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,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
com.google.flogger:flogger-system-backend:0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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.flatbuffers:flatbuffers-java:24.3.25=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger-system-backend:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flogger:flogger:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.flogger:google-extensions:0.7.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
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
@@ -201,8 +166,8 @@ com.google.guava:guava-testlib:33.3.0-jre=testRuntimeClasspath
com.google.guava:guava-testlib:33.6.0-jre=testCompileClasspath
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,testRuntimeClasspath
com.google.guava:guava:33.6.0-jre=testCompileClasspath
com.google.guava:guava:33.5.0-jre=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.6.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,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
@@ -212,8 +177,7 @@ com.google.http-client:google-http-client-appengine:2.1.0=testCompileClasspath,t
com.google.http-client:google-http-client-gson:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client-jackson2:1.46.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.http-client:google-http-client-jackson2:2.1.0=testCompileClasspath,testRuntimeClasspath
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-protobuf:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.http-client:google-http-client:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.inject:guice:7.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.j2objc:j2objc-annotations:3.0.0=checkstyle
@@ -231,12 +195,11 @@ com.google.oauth-client:google-oauth-client-servlet:1.36.0=deploy_jar,nonprodRun
com.google.oauth-client:google-oauth-client-servlet:1.39.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
com.google.oauth-client:google-oauth-client:1.39.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.33.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
com.google.protobuf:protobuf-java-util:4.34.1=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java-util:4.35.0-RC2=testCompileClasspath,testRuntimeClasspath
com.google.protobuf:protobuf-java:3.21.7=soy
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.34.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
com.google.re2j:re2j:1.8=testRuntimeClasspath
com.google.protobuf:protobuf-java:4.35.0-RC2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.re2j:re2j:1.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.google.template:soy:2024-02-26=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
com.google.truth:truth:1.4.5=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.googlecode.json-simple:json-simple:1.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -266,8 +229,8 @@ com.squareup:kotlinpoet:1.11.0=annotationProcessor,testAnnotationProcessor
com.squareup:kotlinpoet:1.15.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-runtime:4.1.2=deploy_jar,jaxb,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
com.sun.istack:istack-commons-tools:4.1.2=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.7=jaxb
com.sun.xml.bind.external:rngom:4.0.7=jaxb
com.sun.xml.bind.external:relaxng-datatype:4.0.8=jaxb
com.sun.xml.bind.external:rngom:4.0.8=jaxb
com.sun.xml.dtd-parser:dtd-parser:1.5.1=jaxb
com.zaxxer:HikariCP:7.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
commons-beanutils:commons-beanutils:1.10.1=checkstyle
@@ -290,70 +253,56 @@ io.github.classgraph:classgraph:4.8.162=compileClasspath,deploy_jar,nonprodCompi
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
io.grpc:grpc-alts:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.70.0=compileClasspath,nonprodCompileClasspath
io.grpc:grpc-api:1.71.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-api:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-auth:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-census:1.68.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.71.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-context:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-core:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-googleapis:1.80.0=testRuntimeClasspath
io.grpc:grpc-grpclb:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-grpclb:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-inprocess:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-netty-shaded:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-netty:1.68.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-opentelemetry:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf-lite:1.80.0=testRuntimeClasspath
io.grpc:grpc-protobuf:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.80.0=testRuntimeClasspath
io.grpc:grpc-services:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-services:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-services:1.80.0=testRuntimeClasspath
io.grpc:grpc-stub:1.70.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-stub:1.80.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-util:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-util:1.80.0=testRuntimeClasspath
io.grpc:grpc-xds:1.66.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.grpc:grpc-xds:1.70.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-xds:1.80.0=testRuntimeClasspath
io.netty:netty-buffer:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-buffer:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-codec-http2:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-codec-http:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec-socks:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-codec:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-common:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-common:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-handler-proxy:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-handler:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-handler:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-resolver:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-resolver:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.github.ss-bhatt:testcontainers-valkey:1.0.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-alts:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-alts:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-api:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-api:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-auth:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-auth:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-census:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-context:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-context:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-core:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-core:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-googleapis:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-googleapis:1.81.0=testRuntimeClasspath
io.grpc:grpc-grpclb:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-grpclb:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-inprocess:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-inprocess:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty-shaded:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-netty-shaded:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-netty:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-opentelemetry:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-opentelemetry:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-protobuf-lite:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf-lite:1.81.0=testRuntimeClasspath
io.grpc:grpc-protobuf:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-protobuf:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-rls:1.76.2=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-rls:1.81.0=testRuntimeClasspath
io.grpc:grpc-services:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-services:1.81.0=testRuntimeClasspath
io.grpc:grpc-stub:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.grpc:grpc-stub:1.81.0=testCompileClasspath,testRuntimeClasspath
io.grpc:grpc-util:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-util:1.81.0=testRuntimeClasspath
io.grpc:grpc-xds:1.76.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath
io.grpc:grpc-xds:1.81.0=testRuntimeClasspath
io.netty:netty-buffer:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http2:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-http:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-codec-socks:4.1.124.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-codec:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-common:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-handler-proxy:4.1.124.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-handler:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-resolver:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-tcnative-boringssl-static:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-tcnative-classes:2.0.52.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport-native-unix-common:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-transport-native-unix-common:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-transport:4.1.100.Final=compileClasspath,nonprodCompileClasspath,testCompileClasspath
io.netty:netty-transport:4.1.110.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.netty:netty-transport-native-unix-common:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.netty:netty-transport:4.1.124.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-api:0.31.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-contrib-exemplar-util:0.31.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opencensus:opencensus-contrib-grpc-metrics:0.31.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
@@ -371,53 +320,57 @@ io.opentelemetry.instrumentation:opentelemetry-grpc-1.6:2.1.0-alpha=compileClass
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api-incubator:2.1.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.instrumentation:opentelemetry-instrumentation-api:2.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry.semconv:opentelemetry-semconv:1.29.0-alpha=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api-incubator:1.42.1-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-api:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-bom:1.42.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-context:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-context:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-context:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-exporter-logging:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-extension-incubator:1.35.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-common:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.47.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk:1.60.1=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-semconv:1.26.0-alpha=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-logs:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-metrics:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.62.0=testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.51.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
io.opentelemetry:opentelemetry-sdk:1.62.0=testCompileClasspath,testRuntimeClasspath
io.outfoxx:swiftpoet:1.3.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.perfmark:perfmark-api:0.27.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
io.protostuff:protostuff-api:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.protostuff:protostuff-collectionschema:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.protostuff:protostuff-core:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.protostuff:protostuff-runtime:1.8.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta-regexp:jakarta-regexp:1.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.1.4=jaxb
jakarta.activation:jakarta.activation-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.activation:jakarta.activation-api:2.2.0-M2=compileClasspath,nonprodCompileClasspath,testCompileClasspath
jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.mail:jakarta.mail-api:2.2.0-M1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.persistence:jakarta.persistence-api:3.2.0=annotationProcessor,compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
jakarta.servlet:jakarta.servlet-api:6.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.transaction:jakarta.transaction-api:2.0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=compileClasspath,jaxb,nonprodCompileClasspath,testCompileClasspath
jakarta.xml.bind:jakarta.xml.bind-api:4.0.5=jaxb
jakarta.xml.bind:jakarta.xml.bind-api:4.1.0-M1=compileClasspath,nonprodCompileClasspath,testCompileClasspath
javax.annotation:javax.annotation-api:1.3.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
javax.annotation:jsr250-api:1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testCompileClasspath,testRuntimeClasspath
javax.inject:javax.inject:1=annotationProcessor,compileClasspath,deploy_jar,nonprodAnnotationProcessor,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,soy,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
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
joda-time:joda-time:2.14.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
junit:junit:4.13.2=nonprodCompileClasspath,nonprodRuntimeClasspath,testCompileClasspath,testRuntimeClasspath
net.arnx:nashorn-promise:0.1.1=testRuntimeClasspath
net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.14.12=compileClasspath,nonprodCompileClasspath
net.bytebuddy:byte-buddy:1.17.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.17.7=compileClasspath,nonprodCompileClasspath
net.bytebuddy:byte-buddy:1.18.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.8-jdk5=testCompileClasspath
net.java.dev.jna:jna:5.13.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
net.ltgt.gradle.incap:incap:0.2=annotationProcessor,testAnnotationProcessor
net.sf.saxon:Saxon-HE:12.5=checkstyle
@@ -426,36 +379,38 @@ org.antlr:ST4:4.3.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodR
org.antlr:antlr-runtime:3.5.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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
org.apache.arrow:arrow-vector:15.0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.12.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-format:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-memory-core:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.arrow:arrow-vector:17.0.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.avro:avro:1.11.4=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-fn-execution:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-job-management:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-model-pipeline:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-construction-java:2.54.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.60.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-core-java:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-direct-java:2.72.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-google-cloud-dataflow-java:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-runners-java-fn-execution:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-core:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-expansion-service:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-arrow:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-avro:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-google-cloud-platform-core:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-extensions-protobuf:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-fn-execution:2.54.0=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-transform-service-launcher:2.60.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_60_1:0.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-harness:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-sdks-java-transform-service-launcher:2.72.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_60_1:0.1=testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-grpc-1_69_0:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.beam:beam-vendor-guava-32_1_2-jre:0.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-compress:1.28.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-compress:1.26.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.apache.commons:commons-csv:1.14.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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-pool2:2.12.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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
@@ -476,7 +431,7 @@ org.apache.sshd:sshd-common:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-core:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-scp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.sshd:sshd-sftp:3.0.0-M3=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.21=testCompileClasspath,testRuntimeClasspath
org.apache.tomcat:tomcat-annotations-api:11.0.22=testCompileClasspath,testRuntimeClasspath
org.apache.xbean:xbean-reflect:3.7=checkstyle
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
org.bouncycastle:bcpg-jdk18on:1.84=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -487,11 +442,10 @@ org.checkerframework:checker-compat-qual:2.5.3=annotationProcessor,compileClassp
org.checkerframework:checker-compat-qual:2.5.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.19.0=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.checkerframework:checker-qual:3.33.0=soy
org.checkerframework:checker-qual:3.49.0=compileClasspath,nonprodCompileClasspath,testCompileClasspath
org.checkerframework:checker-qual:3.49.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.checkerframework:checker-qual:3.49.3=checkstyle
org.checkerframework:checker-qual:3.52.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.24=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.26=testCompileClasspath,testRuntimeClasspath
org.codehaus.mojo:animal-sniffer-annotations:1.27=testCompileClasspath,testRuntimeClasspath
org.codehaus.plexus:plexus-classworlds:2.6.0=checkstyle
org.codehaus.plexus:plexus-component-annotations:2.1.0=checkstyle
org.codehaus.plexus:plexus-container-default:2.1.0=checkstyle
@@ -501,45 +455,43 @@ org.conscrypt:conscrypt-openjdk-uber:2.5.2=compileClasspath,deploy_jar,nonprodCo
org.eclipse.angus:angus-activation:2.0.3=jaxb
org.eclipse.angus:angus-activation:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.angus:jakarta.mail:2.1.0-M1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.eclipse.collections:eclipse-collections-api:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.collections:eclipse-collections:11.1.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.8=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.8=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.4.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.7=jaxb
org.eclipse.jetty.ee10:jetty-ee10-servlet:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee10:jetty-ee10-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty.ee:jetty-ee-webapp:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-http:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-io:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-security:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-server:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-session:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-util:12.1.9=testCompileClasspath,testRuntimeClasspath
org.eclipse.jetty:jetty-xml:12.1.9=testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-core:12.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.flywaydb:flyway-database-postgresql:12.6.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.glassfish.jaxb:codemodel:4.0.8=jaxb
org.glassfish.jaxb:jaxb-core:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-core:4.0.7=jaxb
org.glassfish.jaxb:jaxb-core:4.0.8=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:jaxb-runtime:4.0.7=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.7=jaxb
org.glassfish.jaxb:jaxb-runtime:4.0.8=jaxb
org.glassfish.jaxb:jaxb-xjc:4.0.8=jaxb
org.glassfish.jaxb:txw2:4.0.6=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.glassfish.jaxb:txw2:4.0.7=jaxb
org.glassfish.jaxb:xsom:4.0.7=jaxb
org.glassfish.jaxb:txw2:4.0.8=jaxb
org.glassfish.jaxb:xsom:4.0.8=jaxb
org.gwtproject:gwt-user:2.10.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-core:1.3=nonprodCompileClasspath,nonprodRuntimeClasspath
org.hamcrest:hamcrest-core:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest-library:3.0=testCompileClasspath,testRuntimeClasspath
org.hamcrest:hamcrest:2.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath
org.hamcrest:hamcrest:3.0=testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.0.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.2.7.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.models:hibernate-models:1.1.1=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-ant:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-core:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.hibernate.orm:hibernate-hikaricp:7.3.4.Final=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jacoco:org.jacoco.agent:0.8.14=jacocoAgent,jacocoAnt
org.jacoco:org.jacoco.ant:0.8.14=jacocoAnt
org.jacoco:org.jacoco.core:0.8.14=jacocoAnt
org.jacoco:org.jacoco.report:0.8.14=jacocoAnt
org.javassist:javassist:3.28.0-GA=checkstyle
org.jboss.logging:jboss-logging:3.6.1.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jboss.logging:jboss-logging:3.6.3.Final=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jcommander:jcommander:2.0=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-bom:1.4.0=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
org.jetbrains.kotlin:kotlin-metadata-jvm:2.2.20=annotationProcessor,testAnnotationProcessor
@@ -563,21 +515,21 @@ org.jetbrains:annotations:17.0.0=compileClasspath,deploy_jar,nonprodCompileClass
org.jline:jline:3.30.5=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.joda:joda-money:2.0.3=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
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.json:json:20251224=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.jsoup:jsoup:1.22.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,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
org.junit.jupiter:junit-jupiter-migrationsupport:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.13.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.14.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.14.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.14.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-commons:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-engine:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-launcher:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-runner:1.13.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.14.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.14.3=testRuntimeClasspath
org.junit:junit-bom:5.14.3=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-api:1.14.4=testCompileClasspath,testRuntimeClasspath
org.junit.platform:junit-platform-suite-commons:1.14.4=testRuntimeClasspath
org.junit:junit-bom:5.14.4=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath
org.mockito:mockito-junit-jupiter:5.23.0=testCompileClasspath,testRuntimeClasspath
org.objenesis:objenesis:3.3=testRuntimeClasspath
@@ -598,26 +550,26 @@ org.ow2.asm:asm:9.7.1=compileClasspath,nonprodCompileClasspath
org.ow2.asm:asm:9.8=deploy_jar,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.ow2.asm:asm:9.9=jacocoAnt
org.pcollections:pcollections:4.0.1=annotationProcessor,nonprodAnnotationProcessor,testAnnotationProcessor
org.postgresql:postgresql:42.7.10=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.postgresql:postgresql:42.7.11=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.reflections:reflections:0.10.2=checkstyle
org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v145:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.43.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-api:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chrome-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-chromium-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v146:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v147:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-devtools-v148:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-edge-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-firefox-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-http:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-ie-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-java:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-json:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-manager:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-os:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-remote-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-safari-driver:4.44.0=testCompileClasspath,testRuntimeClasspath
org.seleniumhq.selenium:selenium-support:4.44.0=testCompileClasspath,testRuntimeClasspath
org.slf4j:jcl-over-slf4j:1.7.36=testCompileClasspath,testRuntimeClasspath
org.slf4j:jul-to-slf4j:1.7.30=testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -635,16 +587,18 @@ 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
redis.clients.authentication:redis-authx-core:0.1.1-beta2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
redis.clients:jedis:7.4.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-core:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson.core:jackson-databind:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
tools.jackson:jackson-bom:3.1.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-api:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-diagram:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-operations:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-postgresql:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-text:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-tools:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler-utility:17.1.7=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.10.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
us.fatehi:schemacrawler:17.11.1=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
xerces:xmlParserAPIs:2.6.2=compileClasspath,deploy_jar,nonprodCompileClasspath,nonprodRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
empty=devtool,shadow

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,8 +32,8 @@ import google.registry.request.auth.Auth;
import google.registry.ui.server.SendEmailUtils;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.util.Optional;
import org.joda.time.Days;
/**
* An action that checks all {@link BulkPricingPackage} objects for compliance with their max create
@@ -111,8 +111,7 @@ public class CheckBulkComplianceAction implements Runnable {
+ " 'DOMAIN_CREATE'",
Long.class)
.setParameter("token", bulkPricingPackage.getToken())
.setParameter(
"lastBilling", minusYears(bulkPricingPackage.getNextBillingDateInstant(), 1))
.setParameter("lastBilling", minusYears(bulkPricingPackage.getNextBillingDate(), 1))
.getSingleResult();
if (creates > bulkPricingPackage.getMaxCreates()) {
long overage = creates - bulkPricingPackage.getMaxCreates();
@@ -186,7 +185,7 @@ public class CheckBulkComplianceAction implements Runnable {
int daysSinceLastNotification =
bulkPricingPackage
.getLastNotificationSent()
.map(sentDate -> Days.daysBetween(sentDate, clock.nowUtc()).getDays())
.map(sentDate -> (int) Duration.between(sentDate, clock.now()).toDays())
.orElse(Integer.MAX_VALUE);
// Send a warning email if 30-39 days since last notification and an upgrade email if 40+ days
if (daysSinceLastNotification >= THIRTY_DAYS) {
@@ -222,7 +221,7 @@ public class CheckBulkComplianceAction implements Runnable {
bulkPricingPackage.getMaxDomains(),
activeDomains);
sendNotification(bulkToken, emailSubject, body, registrar.get());
tm().put(bulkPricingPackage.asBuilder().setLastNotificationSent(clock.nowUtc()).build());
tm().put(bulkPricingPackage.asBuilder().setLastNotificationSent(clock.now()).build());
} else {
throw new IllegalStateException(
String.format("Could not find registrar for bulk token %s", bulkToken));

View File

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

View File

@@ -42,11 +42,11 @@ import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import google.registry.util.Clock;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import org.joda.time.Duration;
/**
* An action that deletes all non-renewing domains whose expiration dates have now passed.
@@ -116,7 +116,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
return null;
};
if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) {
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
// Send a 200-series status code to prevent this conflicting action from retrying.
response.setStatus(SC_NO_CONTENT);
response.setPayload("Could not acquire lock; already running?");
@@ -172,7 +172,7 @@ public class DeleteExpiredDomainsAction implements Runnable {
() -> {
Domain transDomain = tm().loadByKey(domain.createVKey());
if (domain.getAutorenewEndTime().isEmpty()
|| domain.getAutorenewEndTime().get().isAfter(tm().getTransactionTime())) {
|| domain.getAutorenewEndTime().get().isAfter(tm().getTxTime())) {
logger.atSevere().log(
"Failed to delete domain %s because of its autorenew end time: %s.",
transDomain.getDomainName(), transDomain.getAutorenewEndTime());

View File

@@ -20,7 +20,7 @@ import static google.registry.persistence.PersistenceModule.TransactionIsolation
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.PARAM_DRY_RUN;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.RegistryEnvironment.PRODUCTION;
import com.google.common.collect.ImmutableList;
@@ -99,7 +99,7 @@ public class DeleteLoadTestDataAction implements Runnable {
private void deletePollMessages(String registrarId) {
ImmutableList<PollMessage> pollMessages =
PollFlowUtils.createPollMessageQuery(registrarId, END_OF_TIME).list();
PollFlowUtils.createPollMessageQuery(registrarId, END_INSTANT).list();
if (isDryRun) {
logger.atInfo().log(
"Would delete %d poll messages for registrar %s.", pollMessages.size(), registrarId);
@@ -115,7 +115,7 @@ public class DeleteLoadTestDataAction implements Runnable {
VKey<Host> hostVKey = host.createVKey();
// We can remove hosts from linked domains, so we should do so then delete the hosts
ImmutableSet<VKey<Domain>> linkedDomains =
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.nowUtc(), null);
EppResourceUtils.getLinkedDomainKeys(hostVKey, clock.now(), null);
tm().loadByKeys(linkedDomains)
.values()
.forEach(

View File

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

View File

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

View File

@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
@@ -36,13 +37,12 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.tools.DomainLockUtils;
import google.registry.util.DateTimeUtils;
import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.util.Optional;
import org.joda.time.Duration;
/** Task that re-locks a previously-Registry-Locked domain after a predetermined period of time. */
@Action(
@@ -59,8 +59,8 @@ public class RelockDomainAction implements Runnable {
static final int ATTEMPTS_BEFORE_SLOWDOWN = 36; // every ten minutes for six hours then every hour
static final int FAILURES_BEFORE_EMAIL = 2; // email after three failures, one half hour
private static final Duration TEN_MINUTES = Duration.standardMinutes(10);
private static final Duration ONE_HOUR = Duration.standardHours(1);
private static final Duration TEN_MINUTES = Duration.ofMinutes(10);
private static final Duration ONE_HOUR = Duration.ofHours(1);
private static final String RELOCK_SUCCESS_EMAIL_TEMPLATE =
"""
@@ -134,7 +134,7 @@ public class RelockDomainAction implements Runnable {
String.format("Unknown revision ID %d", oldUnlockRevisionId)));
domain =
tm().loadByKey(VKey.create(Domain.class, oldLock.getRepoId()))
.cloneProjectedAtTime(tm().getTransactionTime());
.cloneProjectedAtTime(tm().getTxTime());
} catch (Throwable t) {
handleTransientFailure(Optional.ofNullable(oldLock), t);
return;
@@ -188,7 +188,7 @@ public class RelockDomainAction implements Runnable {
"Domain %s has a pending delete.",
domainName);
checkArgument(
!DateTimeUtils.isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
!isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()),
"Domain %s has been deleted.",
domainName);
checkArgument(

View File

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

View File

@@ -17,6 +17,7 @@ package google.registry.batch;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import static java.time.ZoneOffset.UTC;
import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
import static org.apache.http.HttpStatus.SC_OK;
@@ -41,11 +42,10 @@ import google.registry.util.EmailMessage;
import jakarta.inject.Inject;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/** An action that sends notification emails to registrars whose certificates are expiring soon. */
@Action(
@@ -55,6 +55,7 @@ import org.joda.time.format.DateTimeFormatter;
public class SendExpiringCertificateNotificationEmailAction implements Runnable {
public static final String PATH = "/_dr/task/sendExpiringCertificateNotificationEmail";
/**
* Used as an offset when storing the last notification email sent date.
*
@@ -63,10 +64,11 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
* next day at 2am, the date difference will be less than a day, which will lead to the date
* difference between two successive email sent date being the expected email interval days + 1;
*/
protected static final Duration UPDATE_TIME_OFFSET = Duration.standardMinutes(10);
protected static final Duration UPDATE_TIME_OFFSET = Duration.ofMinutes(10);
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(UTC);
private final CertificateChecker certificateChecker;
private final String expirationWarningEmailBodyText;
@@ -147,7 +149,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@VisibleForTesting
boolean sendNotificationEmail(
Registrar registrar,
DateTime lastExpiringCertNotificationSentDate,
Instant lastExpiringCertNotificationSentDate,
CertificateType certificateType,
Optional<String> certificate) {
if (certificate.isEmpty()
@@ -158,8 +160,8 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
try {
ImmutableSet<InternetAddress> recipients = getEmailAddresses(registrar, Type.TECH);
ImmutableSet<InternetAddress> ccs = getEmailAddresses(registrar, Type.ADMIN);
DateTime expirationDate =
new DateTime(certificateChecker.getCertificate(certificate.get()).getNotAfter());
Instant expirationDate =
certificateChecker.getCertificate(certificate.get()).getNotAfter().toInstant();
logger.atInfo().log(
" %s SSL certificate of registrar '%s' will expire on %s.",
certificateType.getDisplayName(), registrar.getRegistrarName(), expirationDate);
@@ -188,9 +190,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
* for applicable certificate.
*/
updateLastNotificationSentDate(
registrar,
clock.nowUtc().minusMinutes((int) UPDATE_TIME_OFFSET.getStandardMinutes()),
certificateType);
registrar, clock.now().minus(UPDATE_TIME_OFFSET), certificateType);
return true;
} catch (Exception e) {
throw new RuntimeException(
@@ -203,7 +203,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
/** Updates the last notification sent date in database. */
@VisibleForTesting
void updateLastNotificationSentDate(
Registrar registrar, DateTime now, CertificateType certificateType) {
Registrar registrar, Instant now, CertificateType certificateType) {
try {
tm().transact(
() -> {
@@ -215,7 +215,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
logger.atInfo().log(
"Updated last notification email sent date to %s for %s certificate of "
+ "registrar %s.",
DATE_FORMATTER.print(now),
DATE_FORMATTER.format(now),
certificateType.getDisplayName(),
registrar.getRegistrarName());
}
@@ -225,7 +225,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
logger.atInfo().log(
"Updated last notification email sent date to %s for %s certificate of "
+ "registrar %s.",
DATE_FORMATTER.print(now),
DATE_FORMATTER.format(now),
certificateType.getDisplayName(),
registrar.getRegistrarName());
}
@@ -298,7 +298,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
@VisibleForTesting
@SuppressWarnings("lgtm[java/dereferenced-value-may-be-null]")
String getEmailBody(
String registrarName, CertificateType type, DateTime expirationDate, String registrarId) {
String registrarName, CertificateType type, Instant expirationDate, String registrarId) {
checkArgumentNotNull(expirationDate, "Expiration date cannot be null");
checkArgumentNotNull(type, "Certificate type cannot be null");
checkArgumentNotNull(registrarId, "Registrar Id cannot be null");
@@ -306,7 +306,7 @@ public class SendExpiringCertificateNotificationEmailAction implements Runnable
expirationWarningEmailBodyText,
registrarName,
type.getDisplayName(),
DATE_FORMATTER.print(expirationDate),
DATE_FORMATTER.format(expirationDate),
registrarId);
}

View File

@@ -0,0 +1,192 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.batch;
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_DOMAIN_SYNC;
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_HOST_SYNC;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.cache.SimplifiedJedisClient;
import google.registry.model.EppResource;
import google.registry.model.common.Cursor;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tlds;
import google.registry.request.Action;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.function.Function;
@Action(
service = Action.Service.BACKEND,
path = SyncRemoteCacheAction.PATH,
method = POST,
auth = Auth.AUTH_ADMIN)
public class SyncRemoteCacheAction implements Runnable {
public static final String PATH = "/_dr/task/syncRemoteCache";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final String LOCK_NAME = "syncRemoteCacheAction";
private static final int BATCH_SIZE = 10000;
private final LockHandler lockHandler;
private final Response response;
private final Optional<SimplifiedJedisClient> jedisClient;
@Inject
public SyncRemoteCacheAction(
LockHandler lockHandler, Response response, Optional<SimplifiedJedisClient> jedisClient) {
this.lockHandler = lockHandler;
this.response = response;
this.jedisClient = jedisClient;
}
@Override
public void run() {
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
if (jedisClient.isEmpty()) {
response.setStatus(SC_NO_CONTENT);
response.setPayload("No Jedis/Valkey configuration found");
return;
}
Callable<Void> runner =
() -> {
try {
runLocked();
response.setStatus(SC_OK);
} catch (Exception e) {
logger.atSevere().withCause(e).log("Errored out during execution.");
response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setPayload(String.format("Errored out with cause: %s", e));
}
return null;
};
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
// Send a 200-series status code to prevent this conflicting action from retrying.
response.setStatus(SC_NO_CONTENT);
response.setPayload("Could not acquire lock; already running?");
}
}
private void runLocked() {
// Note: the transaction ordering means that cursors in our database are updated only if all the
// operations for the entity type succeeded. There is no downside to processing the same objects
// multiple times if, for some reason, saving the cursor to the DB fails.
int syncedDomains = tm().transact(this::syncDomains);
int syncedHosts = tm().transact(this::syncHosts);
String message = String.format("Synced %d domains and %d hosts.", syncedDomains, syncedHosts);
logger.atInfo().log(message);
response.setPayload(message);
}
private int syncDomains() {
Instant domainCursorTime = getPreviousCursorTime(REMOTE_CACHE_DOMAIN_SYNC);
ImmutableSet<String> realTlds = Tlds.getTldsOfType(Tld.TldType.REAL);
List<Domain> domains =
tm().query(
"FROM Domain WHERE updateTimestamp.lastUpdateTime > :cursorTime AND tld IN"
+ " :realTlds ORDER BY updateTimestamp ASC",
Domain.class)
.setParameter("cursorTime", domainCursorTime)
.setParameter("realTlds", realTlds)
.setMaxResults(BATCH_SIZE)
.getResultList();
if (domains.isEmpty()) {
logger.atInfo().log("No domains to process");
return 0;
}
logger.atInfo().log("Processing %d domains", domains.size());
processResources(Domain.class, domains, Domain::getDomainName);
setNewCursorTime(domains, REMOTE_CACHE_DOMAIN_SYNC);
return domains.size();
}
private int syncHosts() {
Instant hostCursorTime = getPreviousCursorTime(REMOTE_CACHE_HOST_SYNC);
List<Host> hosts =
tm().query(
"FROM Host WHERE updateTimestamp.lastUpdateTime > :cursorTime ORDER BY"
+ " updateTimestamp ASC",
Host.class)
.setParameter("cursorTime", hostCursorTime)
.setMaxResults(BATCH_SIZE)
.getResultList();
if (hosts.isEmpty()) {
logger.atInfo().log("No hosts to process");
return 0;
}
logger.atInfo().log("Processing %d hosts", hosts.size());
processResources(Host.class, hosts, Host::getRepoId);
setNewCursorTime(hosts, REMOTE_CACHE_HOST_SYNC);
return hosts.size();
}
private <T extends EppResource> void processResources(
Class<T> clazz, List<T> resources, Function<T, String> getKeyFunction) {
ImmutableList.Builder<String> toDeleteBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<SimplifiedJedisClient.JedisResource<T>> toSaveBuilder =
new ImmutableList.Builder<>();
for (T resource : resources) {
String key = getKeyFunction.apply(resource);
if (resource.getDeletionTime().isAfter(tm().getTxTime())) {
toSaveBuilder.add(new SimplifiedJedisClient.JedisResource<>(key, resource));
} else {
toDeleteBuilder.add(key);
}
}
ImmutableList<String> toDelete = toDeleteBuilder.build();
ImmutableList<SimplifiedJedisClient.JedisResource<T>> toSave = toSaveBuilder.build();
jedisClient.get().deleteAll(clazz, toDelete);
logger.atInfo().log("Invalidated %d from the remote cache", toDelete.size());
jedisClient.get().setAll(toSave);
logger.atInfo().log("Set %d in the remote cache", toSave.size());
}
private Instant getPreviousCursorTime(Cursor.CursorType cursorType) {
return tm().loadByKeyIfPresent(Cursor.createGlobalVKey(cursorType))
.map(Cursor::getCursorTime)
.orElse(START_INSTANT);
}
private void setNewCursorTime(
List<? extends EppResource> resources, Cursor.CursorType cursorType) {
Instant lastUpdateTime = Iterables.getLast(resources).getUpdateTimestamp().getTimestamp();
tm().put(Cursor.createGlobal(cursorType, lastUpdateTime));
logger.atInfo().log("Set new %s cursor time to %s", cursorType, lastUpdateTime);
}
}

View File

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

View File

@@ -14,12 +14,17 @@
package google.registry.beam.billing;
import static google.registry.util.DateTimeUtils.toLocalDate;
import static java.time.ZoneOffset.UTC;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import google.registry.reporting.billing.BillingModule;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.regex.Pattern;
import org.apache.beam.sdk.coders.AtomicCoder;
import org.apache.beam.sdk.coders.Coder;
@@ -29,16 +34,13 @@ import org.apache.beam.sdk.coders.StringUtf8Coder;
import org.apache.beam.sdk.coders.VarIntCoder;
import org.apache.beam.sdk.coders.VarLongCoder;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/**
* A record representing a single billable event, parsed from a {@code SchemaAndRecord}.
*
* @param id The unique ID for the {@code BillingEvent} associated with this event.
* @param billingTime The DateTime (in UTC) this event becomes billable.
* @param eventTime The DateTime (in UTC) this event was generated.
* @param billingTime The Instant (in UTC) this event becomes billable.
* @param eventTime The Instant (in UTC) this event was generated.
* @param registrarId The billed registrar's name.
* @param billingId The billed registrar's billing account key.
* @param poNumber The Purchase Order number.
@@ -53,8 +55,8 @@ import org.joda.time.format.DateTimeFormatter;
*/
public record BillingEvent(
long id,
DateTime billingTime,
DateTime eventTime,
Instant billingTime,
Instant eventTime,
String registrarId,
String billingId,
String poNumber,
@@ -68,7 +70,7 @@ public record BillingEvent(
String flags) {
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss zzz");
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss 'UTC'").withZone(UTC);
private static final Pattern SYNTHETIC_REGEX = Pattern.compile("SYNTHETIC", Pattern.LITERAL);
@@ -92,8 +94,8 @@ public record BillingEvent(
/** Creates a concrete {@link BillingEvent}. */
static BillingEvent create(
long id,
DateTime billingTime,
DateTime eventTime,
Instant billingTime,
Instant eventTime,
String registrarId,
String billingId,
String poNumber,
@@ -143,8 +145,8 @@ public record BillingEvent(
.join(
ImmutableList.of(
id(),
DATE_TIME_FORMATTER.print(billingTime()),
DATE_TIME_FORMATTER.print(eventTime()),
DATE_TIME_FORMATTER.format(billingTime()),
DATE_TIME_FORMATTER.format(eventTime()),
registrarId(),
billingId(),
poNumber(),
@@ -162,11 +164,10 @@ public record BillingEvent(
/** Returns the grouping key for this {@code BillingEvent}, to generate the overall invoice. */
InvoiceGroupingKey getInvoiceGroupingKey() {
return new InvoiceGroupingKey(
billingTime().toLocalDate().withDayOfMonth(1).toString(),
toLocalDate(billingTime()).withDayOfMonth(1).toString(),
years() == 0
? ""
: billingTime()
.toLocalDate()
: toLocalDate(billingTime())
.withDayOfMonth(1)
.plusYears(years())
.minusDays(1)
@@ -224,7 +225,6 @@ public record BillingEvent(
"UnitPriceCurrency",
"PONumber");
/** Generates the CSV header for the overall invoice. */
static String invoiceHeader() {
return Joiner.on(",").join(INVOICE_HEADERS);
@@ -308,8 +308,8 @@ public record BillingEvent(
@Override
public void encode(BillingEvent value, OutputStream outStream) throws IOException {
longCoder.encode(value.id(), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.print(value.billingTime()), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.print(value.eventTime()), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.format(value.billingTime()), outStream);
stringCoder.encode(DATE_TIME_FORMATTER.format(value.eventTime()), outStream);
stringCoder.encode(value.registrarId(), outStream);
stringCoder.encode(value.billingId(), outStream);
stringCoder.encode(value.poNumber(), outStream);
@@ -327,8 +327,8 @@ public record BillingEvent(
public BillingEvent decode(InputStream inStream) throws IOException {
return new BillingEvent(
longCoder.decode(inStream),
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
DATE_TIME_FORMATTER.parseDateTime(stringCoder.decode(inStream)),
Instant.from(DATE_TIME_FORMATTER.parse(stringCoder.decode(inStream))),
Instant.from(DATE_TIME_FORMATTER.parse(stringCoder.decode(inStream))),
stringCoder.decode(inStream),
stringCoder.decode(inStream),
stringCoder.decode(inStream),

View File

@@ -26,7 +26,6 @@ import static google.registry.util.DateTimeUtils.earliestOf;
import static google.registry.util.DateTimeUtils.latestOf;
import static google.registry.util.DateTimeUtils.minusYears;
import static google.registry.util.DateTimeUtils.plusYears;
import static google.registry.util.DateTimeUtils.toDateTime;
import static org.apache.beam.sdk.values.TypeDescriptors.voids;
import com.google.common.collect.ImmutableMap;
@@ -56,7 +55,6 @@ import google.registry.util.Clock;
import google.registry.util.SystemClock;
import jakarta.inject.Singleton;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
@@ -277,12 +275,12 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
ImmutableSet.copyOf(
billingRecurrence
.getRecurrenceTimeOfYear()
.getInstancesInRangeInstant(
.getInstancesInRange(
Range.closedOpen(
latestOf(
plusYears(billingRecurrence.getRecurrenceLastExpansionInstant(), 1),
plusYears(billingRecurrence.getRecurrenceLastExpansion(), 1),
startTime),
earliestOf(billingRecurrence.getRecurrenceEndTimeInstant(), endTime))));
earliestOf(billingRecurrence.getRecurrenceEndTime(), endTime))));
} catch (IllegalArgumentException e) {
return;
}
@@ -307,14 +305,13 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
return;
}
Instant recurrenceLastExpansionTime = billingRecurrence.getRecurrenceLastExpansionInstant();
Instant recurrenceLastExpansionTime = billingRecurrence.getRecurrenceLastExpansion();
// Create new OneTime and DomainHistory for EventTimes that needs to be expanded.
for (Instant eventTime : eventTimesToExpand) {
recurrenceLastExpansionTime = latestOf(recurrenceLastExpansionTime, eventTime);
oneTimesToExpandCounter.inc();
Instant billingTime =
eventTime.plus(Duration.ofMillis(tld.getAutoRenewGracePeriodLength().getMillis()));
Instant billingTime = eventTime.plus(tld.getAutoRenewGracePeriodLength());
// Note that the DomainHistory is created as of transaction time, as opposed to event time.
// This might be counterintuitive because other DomainHistories are created at the time
// mutation events occur, such as in DomainDeleteFlow or DomainRenewFlow. Therefore, it is
@@ -402,7 +399,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
.getRenewPrice(
tld,
billingRecurrence.getTargetId(),
toDateTime(eventTime),
eventTime,
1,
billingRecurrence,
Optional.empty())
@@ -448,7 +445,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable {
Cursor.createGlobalVKey(RECURRING_BILLING))
.orElse(
Cursor.createGlobal(RECURRING_BILLING, START_INSTANT))
.getCursorTimeInstant();
.getCursorTime();
if (!currentCursorTime.equals(startTime)) {
throw new IllegalStateException(
String.format(

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,6 +32,7 @@ import google.registry.model.host.Host;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.VKey;
import java.io.Serializable;
import java.time.Instant;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.coders.StringUtf8Coder;
@@ -42,13 +43,12 @@ import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.transforms.WithKeys;
import org.apache.beam.sdk.util.ShardedKey;
import org.apache.beam.sdk.values.KV;
import org.joda.time.DateTime;
/**
* A Dataflow Flex pipeline that resaves changed EPP resources in SQL.
*
* <p>Due to the way that Hibernate works, if an entity is unchanged by {@link
* EppResource#cloneProjectedAtTime(DateTime)} it will not actually be re-persisted to the database.
* EppResource#cloneProjectedAtTime(Instant)} it will not actually be re-persisted to the database.
* Thus, the only actual changes occur when objects are changed by projecting them to now, such as
* when a pending transfer is resolved.
*/
@@ -102,7 +102,7 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
* transfers, grace periods).
*
* <p>The logic of what might have changed is paraphrased from {@link
* DomainBase#cloneProjectedAtTime(DateTime)}.
* DomainBase#cloneProjectedAtTime(Instant)}.
*/
private void fastResaveDomains(Pipeline pipeline) {
Read<String, String> repoIdRead =
@@ -157,7 +157,7 @@ public class ResaveAllEppResourcesPipeline implements Serializable {
public void processElement(@Element KV<ShardedKey<Integer>, Iterable<String>> element) {
tm().transact(
() -> {
DateTime now = tm().getTransactionTime();
Instant now = tm().getTxTime();
ImmutableList<VKey<? extends EppResource>> keys =
Streams.stream(element.getValue())
.map(repoId -> VKey.create(clazz, repoId))

View File

@@ -22,7 +22,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.io.CharStreams;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import google.registry.util.Retrier;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -132,9 +131,13 @@ public class SafeBrowsingTransforms {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach(
(kv) ->
context.output(
kv, DateTimeUtils.toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
kv -> {
// The Apache Beam API requires org.joda.time.Instant here.
@SuppressWarnings("UnnecessarilyFullyQualified")
org.joda.time.Instant timestamp =
org.joda.time.Instant.ofEpochMilli(clock.nowMillis());
context.output(kv, timestamp, GlobalWindow.INSTANCE);
});
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -88,14 +88,14 @@ public class BsaValidateAction implements Runnable {
IdnChecker idnChecker,
BsaEmailSender emailSender,
@Config("bsaTxnBatchSize") int transactionBatchSize,
@Config("bsaValidationMaxStaleness") org.joda.time.Duration maxStaleness,
@Config("bsaValidationMaxStaleness") Duration maxStaleness,
Clock clock,
Response response) {
this.gcsClient = gcsClient;
this.idnChecker = idnChecker;
this.emailSender = emailSender;
this.transactionBatchSize = transactionBatchSize;
this.maxStaleness = Duration.ofMillis(maxStaleness.getMillis());
this.maxStaleness = maxStaleness;
this.clock = clock;
this.response = response;
}
@@ -228,7 +228,7 @@ public class BsaValidateAction implements Runnable {
}
boolean isStalenessAllowed(Domain domain) {
return domain.getCreationTimeInstant().plus(maxStaleness).isAfter(clock.now());
return domain.getCreationTime().plus(maxStaleness).isAfter(clock.now());
}
/** Returns unique labels across all block lists in the download specified by {@code jobName}. */

View File

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

View File

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

View File

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

View File

@@ -17,7 +17,7 @@ package google.registry.bsa.persistence;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static google.registry.bsa.DownloadStage.DONE;
import static google.registry.bsa.DownloadStage.DOWNLOAD_BLOCK_LISTS;
import static google.registry.util.DateTimeUtils.ISO_8601_FORMATTER;
import static google.registry.util.DateTimeUtils.formatInstant;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
@@ -84,7 +84,7 @@ class BsaDownload {
*/
String getJobName() {
// Return a value based on job start time, which is unique.
return ISO_8601_FORMATTER.format(getCreationTime()).toLowerCase(Locale.ROOT).replace(":", "");
return formatInstant(getCreationTime()).toLowerCase(Locale.ROOT).replace(":", "");
}
boolean isDone() {

View File

@@ -45,6 +45,7 @@ import google.registry.model.domain.Domain;
import google.registry.model.tld.Tld;
import google.registry.model.tld.Tld.TldType;
import google.registry.util.BatchedStreams;
import java.time.Duration;
import java.time.Instant;
import java.util.HashSet;
import java.util.List;
@@ -95,7 +96,7 @@ public final class DomainsRefresher {
public DomainsRefresher(
Instant prevRefreshStartTime,
Instant now,
java.time.Duration domainTxnMaxDuration,
Duration domainTxnMaxDuration,
int transactionBatchSize) {
this.prevRefreshStartTime = prevRefreshStartTime.minus(domainTxnMaxDuration);
this.now = now;

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,168 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import dagger.Module;
import dagger.Provides;
import google.registry.config.CredentialModule.ApplicationDefaultCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.EppResource;
import google.registry.model.ForeignKeyUtils;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import google.registry.util.Clock;
import google.registry.util.GoogleCredentialsBundle;
import jakarta.inject.Singleton;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Optional;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.RedisClient;
import redis.clients.jedis.RedisClusterClient;
import redis.clients.jedis.UnifiedJedis;
/** Dagger module to provide the {@link Jedis}-based cache for Valkey. */
@Module
public final class CacheModule {
@Provides
@Singleton
public static Optional<UnifiedJedis> provideJedis(
@ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
@Config("valkeyHostsAndPorts") Optional<ImmutableList<String>> valkeyHostsAndPorts,
@Config("valkeySslSocketFactory") SSLSocketFactory valkeySslSocketFactory) {
if (valkeyHostsAndPorts.map(ImmutableList::isEmpty).orElse(true)) {
return Optional.empty();
}
ImmutableSet<HostAndPort> hostsAndPorts =
valkeyHostsAndPorts.get().stream().map(HostAndPort::from).collect(toImmutableSet());
JedisClientConfig clientConfig =
DefaultJedisClientConfig.builder()
.ssl(true)
.sslSocketFactory(valkeySslSocketFactory)
.credentialsProvider(new ValkeyCredentialsProvider(credentialsBundle))
.build();
if (hostsAndPorts.size() > 1) {
return Optional.of(
RedisClusterClient.builder().clientConfig(clientConfig).nodes(hostsAndPorts).build());
}
return Optional.of(
RedisClient.builder()
.clientConfig(clientConfig)
.hostAndPort(Iterables.getOnlyElement(hostsAndPorts))
.build());
}
@Provides
@Singleton
public static Optional<SimplifiedJedisClient> provideJedisClient(Optional<UnifiedJedis> jedis) {
return jedis.map(SimplifiedJedisClient::new);
}
@Provides
@Singleton
public static DomainCache provideDomainCache(
Optional<SimplifiedJedisClient> jedisClient, Clock clock, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return domainName ->
ForeignKeyUtils.loadResourceByCache(Domain.class, domainName, clock.now());
}
return new MultilayerDomainCache(jedisClient.get(), clock, cacheMetrics);
}
@Provides
@Singleton
public static HostCache provideHostCache(
Optional<SimplifiedJedisClient> jedisClient, CacheMetrics cacheMetrics) {
if (jedisClient.isEmpty()) {
return repoId ->
Optional.ofNullable(EppResource.loadByCache(VKey.create(Host.class, repoId)));
}
return new MultilayerHostCache(jedisClient.get(), cacheMetrics);
}
@Provides
@Singleton
@Config("valkeySslSocketFactory")
static SSLSocketFactory provideValkeySslSocketFactory(
@Config("valkeyCertificateAuthority") String valkeyCertificateAuthority) {
try {
ImmutableList<X509Certificate> trustedCerts =
CertificateFactory.getInstance("X.509")
.generateCertificates(
new ByteArrayInputStream(
valkeyCertificateAuthority.getBytes(StandardCharsets.UTF_8)))
.stream()
.map(X509Certificate.class::cast)
.collect(toImmutableList());
// This is a roundabout way to trust the Cloud Memorystore-issued certificate authority even
// though it's not a root cert (it's an intermediate cert).
TrustManager x509TrustManager =
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return trustedCerts.toArray(new X509Certificate[0]);
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
Exception lastException = null;
for (X509Certificate cert : certs) {
for (X509Certificate trustedCert : trustedCerts) {
try {
cert.verify(trustedCert.getPublicKey());
return;
} catch (Exception e) {
// Verification failed, try the next one
lastException = e;
}
}
}
throw new CertificateException(
"None of the server certificates were signed by the provided CA", lastException);
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {x509TrustManager}, null);
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Could not create X.509 certificate from provided PEM", e);
}
}
}

View File

@@ -0,0 +1,23 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import google.registry.model.domain.Domain;
import java.util.Optional;
/** Interface for some type of cache that loads {@link Domain}s by domain name. */
public interface DomainCache {
Optional<Domain> loadByDomainName(String domainName);
}

View File

@@ -1,4 +1,4 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
// 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.
@@ -12,10 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.tools.params;
package google.registry.cache;
import org.joda.time.Interval;
import google.registry.model.host.Host;
import java.util.Optional;
/** Optional wrapper for IntervalParameter. */
public final class OptionalIntervalParameter
extends OptionalParameterConverterValidator<Interval, IntervalParameter> {}
/** Interface for some type of cache that loads {@link Host}s by repo ID. */
public interface HostCache {
Optional<Host> loadByRepoId(String repoId);
}

View File

@@ -0,0 +1,64 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import com.google.common.collect.ImmutableList;
import google.registry.model.ForeignKeyUtils;
import google.registry.model.domain.Domain;
import google.registry.model.tld.Tld;
import google.registry.util.Clock;
import java.time.Instant;
import java.util.Optional;
/**
* A multi-layer cache for {@link Domain} objects.
*
* <p>It uses a local Caffeine cache, a remote Jedis cache, and finally the database.
*/
public class MultilayerDomainCache extends MultilayerEppResourceCache<Domain>
implements DomainCache {
private final Clock clock;
public MultilayerDomainCache(
SimplifiedJedisClient jedisClient, Clock clock, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
this.clock = clock;
}
@Override
public Optional<Domain> loadByDomainName(String domainName) {
return loadFromCaches(Domain.class, domainName);
}
@Override
protected Optional<Domain> loadFromDatabase(String domainName) {
// Don't use the cache (avoid caching the same domain twice). Do use the replica SQL instance.
Optional<Domain> possibleDomain =
Optional.ofNullable(
ForeignKeyUtils.loadMostRecentResourceObjects(
Domain.class, ImmutableList.of(domainName), true)
.get(domainName));
Instant now = clock.now();
return possibleDomain
.filter(domain -> now.isBefore(domain.getDeletionTime()))
.map(domain -> domain.cloneProjectedAtTime(now));
}
@Override
protected boolean shouldPersistToRemoteCache(Domain domain) {
return Tld.get(domain.getTld()).getTldType().equals(Tld.TldType.REAL);
}
}

View File

@@ -0,0 +1,83 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import google.registry.config.RegistryConfig;
import google.registry.model.EppResource;
import java.time.Duration;
import java.util.Optional;
/**
* A multi-layer cache for {@link EppResource}s.
*
* <p>It uses a local Caffeine cache, a remote Jedis cache, and finally the database.
*/
public abstract class MultilayerEppResourceCache<V extends EppResource> {
// Don't use a loading cache; it'd complicate the nesting
private final Cache<String, V> localCache =
Caffeine.newBuilder()
.expireAfterWrite(Duration.ofHours(1))
.maximumSize(RegistryConfig.getEppResourceMaxCachedEntries())
.build();
private final SimplifiedJedisClient jedisClient;
private final CacheMetrics cacheMetrics;
protected MultilayerEppResourceCache(
SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
this.jedisClient = jedisClient;
this.cacheMetrics = cacheMetrics;
}
protected abstract Optional<V> loadFromDatabase(String key);
protected boolean shouldPersistToRemoteCache(V value) {
return true;
}
protected Optional<V> loadFromCaches(Class<V> clazz, String key) {
// hopefully the resource is in the local cache
Optional<V> possibleValue = Optional.ofNullable(localCache.getIfPresent(key));
if (possibleValue.isPresent()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.LOCAL);
return possibleValue;
}
// if not, try the remote cache
possibleValue = jedisClient.get(clazz, key);
if (possibleValue.isPresent()) {
localCache.put(key, possibleValue.get());
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.REMOTE);
return possibleValue;
}
// lastly, try the DB
possibleValue = loadFromDatabase(key);
if (possibleValue.isEmpty()) {
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS_NONEXISTENT);
return possibleValue;
}
V value = possibleValue.get();
if (shouldPersistToRemoteCache(value)) {
jedisClient.set(new SimplifiedJedisClient.JedisResource<>(key, value));
}
localCache.put(key, value);
cacheMetrics.recordLookup(clazz.getSimpleName(), CacheMetrics.CacheHitType.MISS);
return possibleValue;
}
}

View File

@@ -0,0 +1,44 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm;
import google.registry.model.host.Host;
import google.registry.persistence.VKey;
import java.util.Optional;
/**
* A multi-layer cache for {@link Host} objects.
*
* <p>It uses a local Caffeine cache, a remote Jedis cache, and finally the database.
*/
public class MultilayerHostCache extends MultilayerEppResourceCache<Host> implements HostCache {
public MultilayerHostCache(SimplifiedJedisClient jedisClient, CacheMetrics cacheMetrics) {
super(jedisClient, cacheMetrics);
}
@Override
public Optional<Host> loadByRepoId(String repoId) {
return loadFromCaches(Host.class, repoId);
}
@Override
protected Optional<Host> loadFromDatabase(String repoId) {
return replicaTm()
.transact(() -> replicaTm().loadByKeyIfPresent(VKey.create(Host.class, repoId)));
}
}

View File

@@ -0,0 +1,154 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource;
import google.registry.model.domain.Domain;
import google.registry.model.host.Host;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import redis.clients.jedis.AbstractPipeline;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.params.SetParams;
/**
* A {@link UnifiedJedis} client that handles serialization/deserialization.
*
* <p>We use protobufs for serialization to handle the immutable collections that our objects use.
*
* <p>{@link UnifiedJedis} pairs key-value types, so we need the key to be serialized to a byte
* array as well.
*/
public class SimplifiedJedisClient {
public record JedisResource<V extends EppResource>(String key, V value) {}
private static final ImmutableMap<Class<? extends EppResource>, String> TYPE_PREFIXES =
ImmutableMap.of(
Domain.class, "d_",
Host.class, "h_");
private static final ImmutableMap<Class<? extends EppResource>, Schema<? extends EppResource>>
VALUE_SCHEMAS =
ImmutableMap.of(
Domain.class, RuntimeSchema.getSchema(Domain.class),
Host.class, RuntimeSchema.getSchema(Host.class));
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final int BATCH_SIZE = 500;
private final UnifiedJedis jedis;
SimplifiedJedisClient(UnifiedJedis jedis) {
this.jedis = jedis;
}
/** Gets the value from the remote cache. Returns null if it does not exist. */
public <V extends EppResource> Optional<V> get(Class<V> clazz, String key) {
checkNotNull(key, "Key cannot be null");
byte[] data = jedis.get(convertKey(clazz, key));
return Optional.ofNullable(data).map(d -> deserialize(clazz, d));
}
/** Sets the value in the remote cache. */
public <V extends EppResource> void set(JedisResource<V> resource) {
checkNotNull(resource.key, "Key cannot be null");
checkNotNull(resource.value, "Value cannot be null");
jedis.set(
convertKey(resource.value.getClass(), resource.key),
serialize(resource.value),
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli()));
}
/** Sets multiple values in the remote cache using a Jedis {@link AbstractPipeline}. */
public <V extends EppResource> void setAll(ImmutableCollection<JedisResource<V>> resources) {
logger.atInfo().log("Processing %d resources", resources.size());
for (Iterable<JedisResource<V>> batch : Iterables.partition(resources, BATCH_SIZE)) {
try (AbstractPipeline pipeline = jedis.pipelined()) {
batch.forEach(
resource ->
pipeline.set(
convertKey(resource.value.getClass(), resource.key),
serialize(resource.value),
new SetParams().pxAt(resource.value.getDeletionTime().toEpochMilli())));
pipeline.sync();
}
}
}
/**
* Deletes all values associated with the given keys in Valkey.
*
* <p>If any given key does not exist, it does nothing.
*
* <p>Note: we use {@code unlink} here instead of {@code del} so that the actual deletion can
* happen in the background whenever the server wants. The keys are removed from the namespace
* immediately, and we don't need the memory to be reclaimed this instant.
*
* <p>This could also be accomplished by using {@link #setAll(ImmutableCollection)} with
* expiration times that are in the past, but this is clearer.
*/
public void deleteAll(Class<?> valueType, ImmutableCollection<String> keys) {
// we use a reasonably small batch size to avoid overwhelming the network
for (Iterable<String> batch : Iterables.partition(keys, BATCH_SIZE)) {
byte[][] keysToUnlink =
Streams.stream(batch).map(key -> convertKey(valueType, key)).toArray(byte[][]::new);
jedis.unlink(keysToUnlink);
}
}
private <V extends EppResource> byte[] serialize(V value) {
@SuppressWarnings("unchecked")
Schema<V> valueSchema = (Schema<V>) getValueSchema(value.getClass());
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
return ProtostuffIOUtil.toByteArray(value, valueSchema, buffer);
} finally {
buffer.clear();
}
}
private <V extends EppResource> V deserialize(Class<V> clazz, byte[] data) {
// We use protobufs because other deserializers don't play nicely with immutable collections
Schema<V> valueSchema = getValueSchema(clazz);
V value = valueSchema.newMessage();
ProtostuffIOUtil.mergeFrom(data, value, valueSchema);
return value;
}
private byte[] convertKey(Class<?> clazz, String key) {
checkArgument(TYPE_PREFIXES.containsKey(clazz), "Unknown class type %s", clazz);
return (TYPE_PREFIXES.get(clazz) + key).getBytes(StandardCharsets.UTF_8);
}
@SuppressWarnings("unchecked")
private <V extends EppResource> Schema<V> getValueSchema(Class<V> clazz) {
checkArgument(VALUE_SCHEMAS.containsKey(clazz), "Unknown class type %s", clazz);
return (Schema<V>) VALUE_SCHEMAS.get(clazz);
}
}

View File

@@ -0,0 +1,46 @@
// Copyright 2026 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.cache;
import com.google.auth.oauth2.GoogleCredentials;
import google.registry.util.GoogleCredentialsBundle;
import java.io.IOException;
import java.util.function.Supplier;
import redis.clients.jedis.DefaultRedisCredentials;
import redis.clients.jedis.RedisCredentials;
public class ValkeyCredentialsProvider implements Supplier<RedisCredentials> {
private static final String MEMORYSTORE_AUTH_SCOPE =
"https://www.googleapis.com/auth/cloud-platform";
private final GoogleCredentials credentials;
public ValkeyCredentialsProvider(GoogleCredentialsBundle credentialsBundle) {
this.credentials =
credentialsBundle.getGoogleCredentials().createScoped(MEMORYSTORE_AUTH_SCOPE);
}
@Override
public RedisCredentials get() {
try {
credentials.refreshIfExpired();
} catch (IOException e) {
throw new RuntimeException("Unable to refresh IAM token for Memorystore", e);
}
String token = credentials.getAccessToken().getTokenValue();
return new DefaultRedisCredentials(null, token);
}
}

View File

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

View File

@@ -18,7 +18,7 @@ import static com.google.common.base.Suppliers.memoize;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap;
import static google.registry.config.ConfigUtils.makeUrl;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.Comparator.naturalOrder;
@@ -50,14 +50,14 @@ import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.net.URI;
import java.net.URL;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Duration;
/**
* Central clearing-house for all configuration.
@@ -271,7 +271,7 @@ public final class RegistryConfig {
@Provides
@Config("brdaDayOfWeek")
public static int provideBrdaDayOfWeek() {
return DateTimeConstants.TUESDAY;
return DayOfWeek.TUESDAY.getValue();
}
/**
@@ -282,7 +282,7 @@ public final class RegistryConfig {
@Provides
@Config("brdaInterval")
public static Duration provideBrdaInterval() {
return Duration.standardDays(7);
return Duration.ofDays(7);
}
/**
@@ -316,7 +316,7 @@ public final class RegistryConfig {
@Provides
@Config("publishDnsUpdatesLockDuration")
public static Duration providePublishDnsUpdatesLockDuration() {
return Duration.standardMinutes(3);
return Duration.ofMinutes(3);
}
/**
@@ -344,7 +344,7 @@ public final class RegistryConfig {
@Provides
@Config("readDnsRefreshRequestsActionRuntime")
public static Duration provideReadDnsRefreshRequestsRuntime() {
return Duration.standardSeconds(45);
return Duration.ofSeconds(45);
}
/**
@@ -355,7 +355,7 @@ public final class RegistryConfig {
@Provides
@Config("dnsDefaultATtl")
public static Duration provideDnsDefaultATtl() {
return Duration.standardHours(1);
return Duration.ofHours(1);
}
/**
@@ -366,7 +366,7 @@ public final class RegistryConfig {
@Provides
@Config("dnsDefaultNsTtl")
public static Duration provideDnsDefaultNsTtl() {
return Duration.standardHours(3);
return Duration.ofHours(3);
}
/**
@@ -377,7 +377,7 @@ public final class RegistryConfig {
@Provides
@Config("dnsDefaultDsTtl")
public static Duration provideDnsDefaultDsTtl() {
return Duration.standardHours(1);
return Duration.ofHours(1);
}
@Provides
@@ -758,7 +758,7 @@ public final class RegistryConfig {
@Provides
@Config("rdeInterval")
public static Duration provideRdeInterval() {
return Duration.standardDays(1);
return Duration.ofDays(1);
}
/**
@@ -769,7 +769,7 @@ public final class RegistryConfig {
@Provides
@Config("rdeReportLockTimeout")
public static Duration provideRdeReportLockTimeout() {
return Duration.standardMinutes(1);
return Duration.ofMinutes(1);
}
/**
@@ -793,7 +793,7 @@ public final class RegistryConfig {
@Provides
@Config("rdeUploadLockTimeout")
public static Duration provideRdeUploadLockTimeout() {
return Duration.standardMinutes(30);
return Duration.ofMinutes(30);
}
/**
@@ -806,7 +806,7 @@ public final class RegistryConfig {
@Provides
@Config("rdeUploadSftpCooldown")
public static Duration provideRdeUploadSftpCooldown() {
return Duration.standardHours(2);
return Duration.ofHours(2);
}
/**
@@ -842,7 +842,7 @@ public final class RegistryConfig {
@Provides
@Config("sheetLockTimeout")
public static Duration provideSheetLockTimeout() {
return Duration.standardHours(1);
return Duration.ofHours(1);
}
/**
@@ -866,7 +866,7 @@ public final class RegistryConfig {
@Provides
@Config("emailThrottleDuration")
public static Duration provideEmailThrottleSeconds(RegistryConfigSettings config) {
return Duration.standardSeconds(config.misc.emailThrottleSeconds);
return Duration.ofSeconds(config.misc.emailThrottleSeconds);
}
/**
@@ -947,7 +947,7 @@ public final class RegistryConfig {
@Provides
@Config("sshTimeout")
public static Duration provideSshTimeout() {
return Duration.standardSeconds(30);
return Duration.ofSeconds(30);
}
/**
@@ -958,7 +958,7 @@ public final class RegistryConfig {
@Provides
@Config("transactionCooldown")
public static Duration provideTransactionCooldown() {
return Duration.standardMinutes(5);
return Duration.ofMinutes(5);
}
/**
@@ -1034,7 +1034,7 @@ public final class RegistryConfig {
@Provides
@Config("metricsWriteInterval")
public static Duration provideMetricsWriteInterval(RegistryConfigSettings config) {
return Duration.standardSeconds(config.monitoring.writeIntervalSeconds);
return Duration.ofSeconds(config.monitoring.writeIntervalSeconds);
}
/**
@@ -1148,8 +1148,8 @@ public final class RegistryConfig {
@Provides
@Config("tokenRefreshDelay")
public static java.time.Duration provideTokenRefreshDelay(RegistryConfigSettings config) {
return java.time.Duration.ofSeconds(config.credentialOAuth.tokenRefreshDelaySeconds);
public static Duration provideTokenRefreshDelay(RegistryConfigSettings config) {
return Duration.ofSeconds(config.credentialOAuth.tokenRefreshDelaySeconds);
}
/** OAuth client ID used by the nomulus tool. */
@@ -1186,28 +1186,28 @@ public final class RegistryConfig {
@Provides
@Config("maxValidityDaysSchedule")
public static ImmutableSortedMap<DateTime, Integer> provideValidityDaysMap(
public static ImmutableSortedMap<Instant, Integer> provideValidityDaysMap(
RegistryConfigSettings config) {
return config.sslCertificateValidation.maxValidityDaysSchedule.entrySet().stream()
.collect(
toImmutableSortedMap(
naturalOrder(),
e ->
"START_OF_TIME".equals(e.getKey())
? START_OF_TIME
: DateTime.parse(e.getKey()),
"START_INSTANT".equals(e.getKey())
? START_INSTANT
: Instant.parse(e.getKey()),
Entry::getValue));
}
@Provides
@Config("expirationWarningDays")
public static int provideExpirationWarningDays(RegistryConfigSettings config) {
public static long provideExpirationWarningDays(RegistryConfigSettings config) {
return config.sslCertificateValidation.expirationWarningDays;
}
@Provides
@Config("expirationWarningIntervalDays")
public static int provideExpirationWarningIntervalDays(RegistryConfigSettings config) {
public static long provideExpirationWarningIntervalDays(RegistryConfigSettings config) {
return config.sslCertificateValidation.expirationWarningIntervalDays;
}
@@ -1328,14 +1328,14 @@ public final class RegistryConfig {
@Provides
@Config("bsaLockLeaseExpiry")
public static Duration provideBsaLockLeaseExpiry(RegistryConfigSettings config) {
return Duration.standardMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
return Duration.ofMinutes(config.bsa.bsaLockLeaseExpiryMinutes);
}
/** Returns the desired interval between successive BSA downloads. */
@Provides
@Config("bsaDownloadInterval")
public static Duration provideBsaDownloadInterval(RegistryConfigSettings config) {
return Duration.standardMinutes(config.bsa.bsaDownloadIntervalMinutes);
return Duration.ofMinutes(config.bsa.bsaDownloadIntervalMinutes);
}
/**
@@ -1345,7 +1345,7 @@ public final class RegistryConfig {
@Provides
@Config("bsaMaxNopInterval")
public static Duration provideBsaMaxNopInterval(RegistryConfigSettings config) {
return Duration.standardHours(config.bsa.bsaMaxNopIntervalHours);
return Duration.ofHours(config.bsa.bsaMaxNopIntervalHours);
}
@Provides
@@ -1357,13 +1357,13 @@ public final class RegistryConfig {
@Provides
@Config("domainCreateTxnCommitTimeLag")
public static Duration provideDomainCreateTxnCommitTimeLag(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
return Duration.ofSeconds(config.bsa.domainCreateTxnCommitTimeLagSeconds);
}
@Provides
@Config("bsaValidationMaxStaleness")
public static Duration provideBsaValidationMaxStaleness(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
return Duration.ofSeconds(config.bsa.bsaValidationMaxStalenessSeconds);
}
@Provides
@@ -1375,7 +1375,7 @@ public final class RegistryConfig {
@Provides
@Config("bsaAuthTokenExpiry")
public static Duration provideBsaAuthTokenExpiry(RegistryConfigSettings config) {
return Duration.standardSeconds(config.bsa.authTokenExpirySeconds);
return Duration.ofSeconds(config.bsa.authTokenExpirySeconds);
}
@Provides
@@ -1463,6 +1463,14 @@ public final class RegistryConfig {
return config.mosapi.tldThreadCount;
}
@Provides
@Config("valkeyHostsAndPorts")
public static Optional<ImmutableList<String>> provideValkeyHostsAndPorts(
RegistryConfigSettings config) {
return Optional.ofNullable(config.valkey)
.map(valkey -> ImmutableList.copyOf(valkey.hostsAndPorts));
}
private static String formatComments(String text) {
return Splitter.on('\n').omitEmptyStrings().trimResults().splitToList(text).stream()
.map(s -> "# " + s)
@@ -1481,7 +1489,7 @@ public final class RegistryConfig {
* @see google.registry.tools.server.GenerateZoneFilesAction
*/
public static Duration getDatabaseRetention() {
return Duration.standardDays(30);
return Duration.ofDays(30);
}
public static boolean areServersLocal() {
@@ -1497,8 +1505,8 @@ public final class RegistryConfig {
}
/** Returns the amount of time a singleton should be cached, before expiring. */
public static java.time.Duration getSingletonCacheRefreshDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds);
public static Duration getSingletonCacheRefreshDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds);
}
/**
@@ -1507,13 +1515,13 @@ public final class RegistryConfig {
* @see google.registry.model.tld.label.ReservedList
* @see google.registry.model.tld.label.PremiumList
*/
public static java.time.Duration getDomainLabelListCacheDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds);
public static Duration getDomainLabelListCacheDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.domainLabelCachingSeconds);
}
/** Returns the amount of time a singleton should be cached in persist mode, before expiring. */
public static java.time.Duration getSingletonCachePersistDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds);
public static Duration getSingletonCachePersistDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.singletonCachePersistSeconds);
}
/**
@@ -1535,8 +1543,8 @@ public final class RegistryConfig {
/**
* Returns the amount of time an EPP resource or key should be cached in memory before expiring.
*/
public static java.time.Duration getEppResourceCachingDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds);
public static Duration getEppResourceCachingDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.eppResourceCachingSeconds);
}
/** Returns the maximum number of EPP resources and keys to keep in in-memory cache. */
@@ -1545,8 +1553,8 @@ public final class RegistryConfig {
}
/** Returns the amount of time that a particular claims list should be cached. */
public static java.time.Duration getClaimsListCacheDuration() {
return java.time.Duration.ofSeconds(CONFIG_SETTINGS.get().caching.claimsListCachingSeconds);
public static Duration getClaimsListCacheDuration() {
return Duration.ofSeconds(CONFIG_SETTINGS.get().caching.claimsListCachingSeconds);
}
/** Returns the email address that outgoing emails from the app are sent from. */
@@ -1629,7 +1637,6 @@ public final class RegistryConfig {
return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix;
}
/** A discount for all sunrise domain creates, between 0.0 (no discount) and 1.0 (free). */
public static double getSunriseDomainCreateDiscount() {
return CONFIG_SETTINGS.get().registryPolicy.sunriseDomainCreateDiscount;

View File

@@ -43,6 +43,7 @@ public class RegistryConfigSettings {
public BulkPricingPackageMonitoring bulkPricingPackageMonitoring;
public Bsa bsa;
public MosApi mosapi;
public Valkey valkey;
/** Configuration options that apply to the entire GCP project. */
public static class GcpProject {
@@ -213,8 +214,8 @@ public class RegistryConfigSettings {
/** Configuration for the certificate checker. */
public static class SslCertificateValidation {
public Map<String, Integer> maxValidityDaysSchedule;
public int expirationWarningDays;
public int expirationWarningIntervalDays;
public long expirationWarningDays;
public long expirationWarningIntervalDays;
public int minimumRsaKeyLength;
public Set<String> allowedEcdsaCurves;
public String expirationWarningEmailBodyText;
@@ -267,4 +268,9 @@ public class RegistryConfigSettings {
public List<String> services;
public int tldThreadCount;
}
/** Configuration for Valkey caching. */
public static class Valkey {
public List<String> hostsAndPorts;
}
}

View File

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

View File

@@ -476,7 +476,7 @@ sslCertificateValidation:
# The entry key is the date closest before the date the certificate was issued
# and the entry value is the applicable maximum validity days for that certificate.
maxValidityDaysSchedule:
"START_OF_TIME": 825
"START_INSTANT": 825
"2020-09-01T00:00:00Z": 398
# The number of days before a certificate expires that indicates the
# certificate is nearing expiration and warnings should be sent.
@@ -639,3 +639,7 @@ mosapi:
# ICANN MoSAPI Specification, Section 12.3</a>
tldThreadCount: 4
valkey:
# Optional: hosts and ports for remote Valkey caching, e.g.
# - "127.0.0.1:6379"
hostsAndPorts: []

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,8 @@ import static google.registry.model.registrar.RegistrarPoc.Type.MARKETING;
import static google.registry.model.registrar.RegistrarPoc.Type.TECH;
import static google.registry.model.registrar.RegistrarPoc.Type.WHOIS;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.START_INSTANT;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
@@ -37,13 +38,12 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registrar.RegistrarPoc;
import google.registry.util.Clock;
import google.registry.util.DateTimeUtils;
import jakarta.inject.Inject;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
/**
* Class for synchronizing all {@link Registrar} objects to a Google Spreadsheet.
@@ -63,9 +63,9 @@ class SyncRegistrarsSheet {
boolean wereRegistrarsModified() {
Optional<Cursor> cursor =
tm().transact(() -> tm().loadByKeyIfPresent(Cursor.createGlobalVKey(SYNC_REGISTRAR_SHEET)));
DateTime lastUpdateTime = cursor.isEmpty() ? START_OF_TIME : cursor.get().getCursorTime();
Instant lastUpdateTime = cursor.isEmpty() ? START_INSTANT : cursor.get().getCursorTime();
for (Registrar registrar : Registrar.loadAllCached()) {
if (DateTimeUtils.isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
if (isAtOrAfter(registrar.getLastUpdateTime(), lastUpdateTime)) {
return true;
}
}
@@ -74,7 +74,7 @@ class SyncRegistrarsSheet {
/** Performs the synchronization operation. */
void run(String spreadsheetId) throws IOException {
final DateTime executionTime = clock.nowUtc();
Instant executionTime = clock.now();
sheetSynchronizer.synchronize(
spreadsheetId,
new Ordering<Registrar>() {

View File

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

View File

@@ -60,9 +60,9 @@ import google.registry.request.Response;
import google.registry.request.auth.Auth;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import org.joda.time.DateTime;
/**
* An action that returns availability and premium checks as JSON.
@@ -130,7 +130,7 @@ public class CheckApiAction implements Runnable {
// Throws an EppException with a reasonable error message which will be sent back to caller.
validateDomainNameWithIdnTables(domainName);
DateTime now = replicaTm().getTransactionTime();
Instant now = replicaTm().getTxTime();
Tld tld = Tld.get(domainName.parent().toString());
try {
verifyNotInPredelegation(tld, now);
@@ -182,7 +182,7 @@ public class CheckApiAction implements Runnable {
}
}
private boolean checkExists(String domainString, DateTime now) {
private boolean checkExists(String domainString, Instant now) {
return ForeignKeyUtils.loadKeyByCache(Domain.class, domainString, now).isPresent();
}

View File

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

View File

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

View File

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

View File

@@ -251,7 +251,7 @@ public class FlowModule {
String registrarId,
EppInput eppInput) {
builder
.setModificationTime(tm().getTransactionTime())
.setModificationTime(tm().getTxTime())
.setTrid(trid)
.setXmlBytes(inputXmlBytes)
.setBySuperuser(isSuperuser)

View File

@@ -16,7 +16,6 @@ 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;
@@ -50,7 +49,6 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.joda.time.DateTime;
/** Static utility functions for resource flows. */
public final class ResourceFlowUtils {
@@ -66,8 +64,7 @@ public final class ResourceFlowUtils {
}
/** Check if there are domains linked to the host to be deleted. Throws an exception if so. */
public static void checkLinkedDomains(final String targetId, final DateTime now)
throws EppException {
public static void checkLinkedDomains(final String targetId, Instant now) throws EppException {
VKey<Host> key =
ForeignKeyUtils.loadKey(Host.class, targetId, now)
.orElseThrow(() -> new ResourceDoesNotExistException(Host.class, targetId));
@@ -89,11 +86,6 @@ 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));
@@ -105,7 +97,7 @@ public final class ResourceFlowUtils {
}
public static <R extends EppResource> void verifyResourceDoesNotExist(
Class<R> clazz, String targetId, DateTime now, String registrarId) throws EppException {
Class<R> clazz, String targetId, Instant now, String registrarId) throws EppException {
Optional<R> resource = ForeignKeyUtils.loadResource(clazz, targetId, now);
if (resource.isPresent()) {
// These are similar exceptions, but we can track them internally as log-based metrics.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ import google.registry.flows.domain.DomainCheckFlow;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppoutput.CheckData.DomainCheck;
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
import org.joda.time.DateTime;
import java.time.Instant;
/**
* A no-op base class for {@link DomainCheckFlow} custom logic.
@@ -75,7 +75,7 @@ public class DomainCheckFlowCustomLogic extends BaseFlowCustomLogic {
* but can be overridden in v&gt;=0.12 of the fee extension.
*/
public record AfterValidationParameters(
ImmutableMap<String, InternetDomainName> domainNames, DateTime asOfDate) {
ImmutableMap<String, InternetDomainName> domainNames, Instant asOfDate) {
public static Builder newBuilder() {
return new AutoBuilder_DomainCheckFlowCustomLogic_AfterValidationParameters_Builder();
@@ -87,7 +87,7 @@ public class DomainCheckFlowCustomLogic extends BaseFlowCustomLogic {
Builder setDomainNames(ImmutableMap<String, InternetDomainName> domainNames);
Builder setAsOfDate(DateTime asOfDate);
Builder setAsOfDate(Instant asOfDate);
AfterValidationParameters build();
}
@@ -102,7 +102,7 @@ public class DomainCheckFlowCustomLogic extends BaseFlowCustomLogic {
public record BeforeResponseParameters(
ImmutableList<DomainCheck> domainChecks,
ImmutableList<? extends ResponseExtension> responseExtensions,
DateTime asOfDate) {
Instant asOfDate) {
public static Builder newBuilder() {
return new AutoBuilder_DomainCheckFlowCustomLogic_BeforeResponseParameters_Builder();
@@ -116,7 +116,7 @@ public class DomainCheckFlowCustomLogic extends BaseFlowCustomLogic {
Builder setResponseExtensions(ImmutableList<? extends ResponseExtension> responseExtensions);
Builder setAsOfDate(DateTime asOfDate);
Builder setAsOfDate(Instant asOfDate);
BeforeResponseParameters build();
}

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