mirror of
https://github.com/google/nomulus
synced 2026-01-07 14:05:44 +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:
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -70,6 +70,7 @@ import java.util.NoSuchElementException;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
@@ -224,7 +225,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||||||
EntityTransaction txn = txnInfo.entityManager.getTransaction();
|
EntityTransaction txn = txnInfo.entityManager.getTransaction();
|
||||||
try {
|
try {
|
||||||
txn.begin();
|
txn.begin();
|
||||||
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocatedId : IdService::allocateId);
|
txnInfo.start(clock, readOnly ? ReplicaDbIdService::allocateId : this::fetchIdFromSequence);
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
getEntityManager().createNativeQuery("SET TRANSACTION READ ONLY").executeUpdate();
|
getEntityManager().createNativeQuery("SET TRANSACTION READ ONLY").executeUpdate();
|
||||||
logger.atInfo().log("Using read-only SQL replica");
|
logger.atInfo().log("Using read-only SQL replica");
|
||||||
@@ -558,6 +559,19 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||||||
return emf.getMetamodel().entity(clazz);
|
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 record EntityId(String name, Object value) {}
|
||||||
|
|
||||||
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
|
private static ImmutableSet<EntityId> getEntityIdsFromEntity(
|
||||||
@@ -1038,4 +1052,23 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||||||
.collect(toImmutableList());
|
.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user