1
0
mirror of https://github.com/google/nomulus synced 2026-01-04 12:14:19 +00:00

Drop the transact call in IdService (#2561)

* Drop the `transact` call in Id services

All usages already routed through `tm().allocateId()`, which is
guaranteed to be in a transaction.

* Addressing reviews
This commit is contained in:
Weimin Yu
2024-09-18 14:18:36 -04:00
committed by GitHub
parent a988732d65
commit febdbc0468
3 changed files with 34 additions and 81 deletions

View File

@@ -1,42 +0,0 @@
// Copyright 2021 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package google.registry.persistence.transaction;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import java.util.concurrent.atomic.AtomicLong;
/**
* Allocates a {@code long} to use as a {@code @Id}, (part) of the primary SQL key for an entity.
*/
final class IdService {
private IdService() {}
/**
* A SQL Sequence based ID allocator that generates an ID from a monotonically increasing {@link
* AtomicLong}
*
* <p>The generated IDs are project-wide unique.
*/
static long allocateId() {
return tm().transact(
() ->
(Long)
tm().getEntityManager()
.createNativeQuery("SELECT nextval('project_wide_unique_id_seq')")
.getSingleResult());
}
}

View File

@@ -70,6 +70,7 @@ import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -224,7 +225,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
EntityTransaction txn = txnInfo.entityManager.getTransaction();
try {
txn.begin();
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocatedId : IdService::allocateId);
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocateId : this::fetchIdFromSequence);
if (readOnly) {
getEntityManager().createNativeQuery("SET TRANSACTION READ ONLY").executeUpdate();
logger.atInfo().log("Using read-only SQL replica");
@@ -558,6 +559,19 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
return emf.getMetamodel().entity(clazz);
}
/**
* A SQL Sequence based ID allocator that generates an ID from a monotonically increasing {@link
* AtomicLong}
*
* <p>The generated IDs are project-wide unique.
*/
private long fetchIdFromSequence() {
return (Long)
getEntityManager()
.createNativeQuery("SELECT nextval('project_wide_unique_id_seq')")
.getSingleResult();
}
private record EntityId(String name, Object value) {}
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
@@ -1038,4 +1052,23 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
.collect(toImmutableList());
}
}
/**
* Provides {@code long} values for use as {@code id} by JPA model entities in (read-only)
* transactions in the replica database. Each id is only unique in the JVM instance.
*
* <p>The {@link #fetchIdFromSequence database sequence-based id allocator} cannot be used with
* the replica because id generation is a write operation.
*/
private static final class ReplicaDbIdService {
private static final AtomicLong nextId = new AtomicLong(1);
/**
* Returns the next long value from a {@link AtomicLong}. Each id is unique in the JVM instance.
*/
static long allocateId() {
return nextId.getAndIncrement();
}
}
}

View File

@@ -1,38 +0,0 @@
// Copyright 2024 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package google.registry.persistence.transaction;
import java.util.concurrent.atomic.AtomicLong;
/**
* Provides {@code long} values for use as {@code id} by JPA model entities in (read-only)
* transactions in the replica database. Each id is only unique in the JVM instance.
*
* <p>The {@link IdService database sequence-based id service} cannot be used with the replica
* because id generation is a write operation.
*/
final class ReplicaDbIdService {
private ReplicaDbIdService() {}
private static final AtomicLong nextId = new AtomicLong(1);
/**
* Returns the next long value from a {@link AtomicLong}. Each id is unique in the JVM instance.
*/
static final long allocatedId() {
return nextId.getAndIncrement();
}
}