From 028bdffd994a9632020c2c63b990d8bee8d84909 Mon Sep 17 00:00:00 2001 From: aalouane <30903736+ergo14@users.noreply.github.com> Date: Mon, 21 Oct 2024 16:59:26 +0100 Subject: [PATCH] [Named min timestamp Leases] Modify client API (#7386) --- atlasdb-impl-shared/build.gradle | 1 + .../impl/InstrumentedTimelockService.java | 14 ++++----- lock-api-objects/build.gradle | 1 + .../com/palantir/lock/v2/TimelockService.java | 14 +++++---- ...eResult.java => TimestampLeaseResult.java} | 9 ++---- .../lock/v2/TimestampLeaseResults.java | 30 +++++++++++++++++++ .../lock/client/ProfilingTimelockService.java | 15 +++++----- .../client/RemoteTimelockServiceAdapter.java | 12 ++++---- .../palantir/lock/client/TimeLockClient.java | 13 ++++---- .../client/UnreliableTimeLockService.java | 13 ++++---- lock-impl/build.gradle | 1 + .../lock/impl/LegacyTimelockService.java | 9 +++--- .../src/main/conjure/timelock-api.yml | 10 +++---- .../timelock/api/TimestampLeaseName.java | 3 ++ .../timelock/AsyncTimelockServiceImpl.java | 7 ++++- ...ltiClientTimestampLeaseServiceAdapter.java | 4 +-- .../RemotingTimestampLeaseServiceAdapter.java | 13 ++++---- .../timelock/lock/AsyncLockService.java | 4 +-- ...ultiClientConjureTimelockResourceTest.java | 18 +++++------ 19 files changed, 116 insertions(+), 75 deletions(-) rename lock-api-objects/src/main/java/com/palantir/lock/v2/{AcquireNamedMinTimestampLeaseResult.java => TimestampLeaseResult.java} (83%) create mode 100644 lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResults.java diff --git a/atlasdb-impl-shared/build.gradle b/atlasdb-impl-shared/build.gradle index d877e915d2c..4118ddfcae0 100644 --- a/atlasdb-impl-shared/build.gradle +++ b/atlasdb-impl-shared/build.gradle @@ -23,6 +23,7 @@ dependencies { implementation project(":atlasdb-client") implementation project(":atlasdb-commons") implementation project(":atlasdb-coordination-impl") + implementation project(':timelock-api') implementation project(":timestamp-api") implementation 'com.github.ben-manes.caffeine:caffeine' diff --git a/atlasdb-impl-shared/src/main/java/com/palantir/atlasdb/transaction/impl/InstrumentedTimelockService.java b/atlasdb-impl-shared/src/main/java/com/palantir/atlasdb/transaction/impl/InstrumentedTimelockService.java index b7742a716f8..a1841a0428d 100644 --- a/atlasdb-impl-shared/src/main/java/com/palantir/atlasdb/transaction/impl/InstrumentedTimelockService.java +++ b/atlasdb-impl-shared/src/main/java/com/palantir/atlasdb/transaction/impl/InstrumentedTimelockService.java @@ -17,9 +17,9 @@ import com.codahale.metrics.Meter; import com.palantir.atlasdb.AtlasDbMetricNames; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.atlasdb.util.MetricsManager; import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; @@ -27,11 +27,13 @@ import com.palantir.lock.v2.LockToken; import com.palantir.lock.v2.StartIdentifiedAtlasDbTransactionResponse; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.timestamp.TimestampRange; import com.palantir.tritium.metrics.registry.MetricName; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Supplier; @@ -135,16 +137,14 @@ public long currentTimeMillis() { @ReviewedRestrictedApiUsage @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { - return executeWithRecord( - () -> timelockService.acquireNamedMinTimestampLease(timestampName, numFreshTimestamps)); + public TimestampLeaseResults acquireTimestampLeases(Map requests) { + return executeWithRecord(() -> timelockService.acquireTimestampLeases(requests)); } @ReviewedRestrictedApiUsage @Override - public long getMinLeasedTimestampForName(String timestampName) { - return executeWithRecord(() -> timelockService.getMinLeasedTimestampForName(timestampName)); + public Map getMinLeasedTimestamps(Set timestampNames) { + return executeWithRecord(() -> timelockService.getMinLeasedTimestamps(timestampNames)); } private T executeWithRecord(Supplier method) { diff --git a/lock-api-objects/build.gradle b/lock-api-objects/build.gradle index c1e4b9a8354..4106add5d43 100644 --- a/lock-api-objects/build.gradle +++ b/lock-api-objects/build.gradle @@ -4,6 +4,7 @@ apply from: "../gradle/shared.gradle" libsDirName = file('build/artifacts') dependencies { + api project(":timelock-api") api project(":timestamp-api") api project(":timestamp-client") implementation project(":atlasdb-commons") diff --git a/lock-api-objects/src/main/java/com/palantir/lock/v2/TimelockService.java b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimelockService.java index 6046300f2a7..db9bfde11a8 100644 --- a/lock-api-objects/src/main/java/com/palantir/lock/v2/TimelockService.java +++ b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimelockService.java @@ -16,6 +16,7 @@ package com.palantir.lock.v2; import com.google.errorprone.annotations.RestrictedApi; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; import com.palantir.logsafe.Safe; import com.palantir.processors.AutoDelegate; @@ -23,6 +24,7 @@ import com.palantir.timestamp.TimestampRange; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -114,8 +116,10 @@ default List startIdentifiedAtlasDbTr long currentTimeMillis(); /** - * Acquires a lease on a named timestamp. The lease is taken out with a new fresh timestamp. - * The returned timestamps are fresh timestamps obtained strictly after the lease is taken out. + * Acquires a lease on named timestamps. The lease is taken out with a new fresh timestamp. + * The timestamps supplied are fresh timestamps obtained strictly after the lease is taken out. + * The supplier returns exactly the number of timestamps requested and throws on any additional + * interactions. */ @RestrictedApi( explanation = @@ -123,10 +127,10 @@ default List startIdentifiedAtlasDbTr + " given explicit approval. Mis-use can result in SEVERE DATA CORRUPTION and the API contract" + " is subject to change at any time.", allowlistAnnotations = ReviewedRestrictedApiUsage.class) - AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease(String timestampName, int numFreshTimestamps); + TimestampLeaseResults acquireTimestampLeases(Map requests); /** - * Returns the smallest leased timestamp in the associated named collection at the time of the call. + * Returns the smallest leased timestamp for each of the associated named collections at the time of the call. * If there are no active leases, a fresh timestamp is obtained and returned. */ @RestrictedApi( @@ -135,5 +139,5 @@ default List startIdentifiedAtlasDbTr + " given explicit approval. Mis-use can result in SEVERE DATA CORRUPTION and the API contract" + " is subject to change at any time.", allowlistAnnotations = ReviewedRestrictedApiUsage.class) - long getMinLeasedTimestampForName(String timestampName); + Map getMinLeasedTimestamps(Set timestampNames); } diff --git a/lock-api-objects/src/main/java/com/palantir/lock/v2/AcquireNamedMinTimestampLeaseResult.java b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResult.java similarity index 83% rename from lock-api-objects/src/main/java/com/palantir/lock/v2/AcquireNamedMinTimestampLeaseResult.java rename to lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResult.java index dd36f489178..218df2779a3 100644 --- a/lock-api-objects/src/main/java/com/palantir/lock/v2/AcquireNamedMinTimestampLeaseResult.java +++ b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResult.java @@ -16,17 +16,14 @@ package com.palantir.lock.v2; -import java.util.List; +import java.util.function.LongSupplier; import org.immutables.value.Value; @Value.Immutable -public interface AcquireNamedMinTimestampLeaseResult { +public interface TimestampLeaseResult { @Value.Parameter long minLeasedTimestamp(); @Value.Parameter - LockToken lock(); - - @Value.Parameter - List freshTimestamps(); + LongSupplier freshTimestampsSupplier(); } diff --git a/lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResults.java b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResults.java new file mode 100644 index 00000000000..f14c78fc917 --- /dev/null +++ b/lock-api-objects/src/main/java/com/palantir/lock/v2/TimestampLeaseResults.java @@ -0,0 +1,30 @@ +/* + * (c) Copyright 2024 Palantir Technologies Inc. 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 com.palantir.lock.v2; + +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; +import java.util.Map; +import org.immutables.value.Value; + +@Value.Immutable +public interface TimestampLeaseResults { + @Value.Parameter + LockToken lock(); + + @Value.Parameter + Map results(); +} diff --git a/lock-api/src/main/java/com/palantir/lock/client/ProfilingTimelockService.java b/lock-api/src/main/java/com/palantir/lock/client/ProfilingTimelockService.java index 616e5e8979e..8227aa95315 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/ProfilingTimelockService.java +++ b/lock-api/src/main/java/com/palantir/lock/client/ProfilingTimelockService.java @@ -19,9 +19,9 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; import com.google.common.util.concurrent.RateLimiter; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.common.base.Throwables; import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; @@ -29,6 +29,7 @@ import com.palantir.lock.v2.LockToken; import com.palantir.lock.v2.StartIdentifiedAtlasDbTransactionResponse; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.logsafe.SafeArg; @@ -39,6 +40,7 @@ import com.palantir.timestamp.TimestampRange; import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -173,17 +175,14 @@ public long currentTimeMillis() { @ReviewedRestrictedApiUsage @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { - return runTaskTimed( - "acquireNamedMinTimestampLease", - () -> delegate.acquireNamedMinTimestampLease(timestampName, numFreshTimestamps)); + public TimestampLeaseResults acquireTimestampLeases(Map requests) { + return runTaskTimed("acquireTimestampLeases", () -> delegate.acquireTimestampLeases(requests)); } @ReviewedRestrictedApiUsage @Override - public long getMinLeasedTimestampForName(String timestampName) { - return runTaskTimed("getMinLeasedNamedTimestamp", () -> delegate.getMinLeasedTimestampForName(timestampName)); + public Map getMinLeasedTimestamps(Set timestampNames) { + return runTaskTimed("getMinLeasedTimestamps", () -> delegate.getMinLeasedTimestamps(timestampNames)); } private T runTaskTimed(String actionName, Supplier action) { diff --git a/lock-api/src/main/java/com/palantir/lock/client/RemoteTimelockServiceAdapter.java b/lock-api/src/main/java/com/palantir/lock/client/RemoteTimelockServiceAdapter.java index 91a1c21a671..1768809f58e 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/RemoteTimelockServiceAdapter.java +++ b/lock-api/src/main/java/com/palantir/lock/client/RemoteTimelockServiceAdapter.java @@ -20,8 +20,7 @@ import com.palantir.atlasdb.timelock.api.ConjureGetFreshTimestampsResponseV2; import com.palantir.atlasdb.timelock.api.ConjureTimestampRange; import com.palantir.atlasdb.timelock.api.Namespace; -import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; @@ -30,6 +29,7 @@ import com.palantir.lock.v2.NamespacedTimelockRpcClient; import com.palantir.lock.v2.StartIdentifiedAtlasDbTransactionResponse; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.lock.watch.LockWatchCache; @@ -38,6 +38,7 @@ import com.palantir.logsafe.logger.SafeLoggerFactory; import com.palantir.timestamp.TimestampRange; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -170,17 +171,14 @@ public long currentTimeMillis() { return rpcClient.currentTimeMillis(); } - @ReviewedRestrictedApiUsage @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { + public TimestampLeaseResults acquireTimestampLeases(Map requests) { // TODO(aalouane): implement! throw new UnsupportedOperationException("Not implemented yet!"); } - @ReviewedRestrictedApiUsage @Override - public long getMinLeasedTimestampForName(String timestampName) { + public Map getMinLeasedTimestamps(Set timestampNames) { // TODO(aalouane): implement! throw new UnsupportedOperationException("Not implemented yet!"); } diff --git a/lock-api/src/main/java/com/palantir/lock/client/TimeLockClient.java b/lock-api/src/main/java/com/palantir/lock/client/TimeLockClient.java index 4c0f2272e1e..be9524d9242 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/TimeLockClient.java +++ b/lock-api/src/main/java/com/palantir/lock/client/TimeLockClient.java @@ -17,12 +17,12 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.common.base.Throwables; import com.palantir.common.concurrent.NamedThreadFactory; import com.palantir.common.concurrent.PTExecutors; import com.palantir.leader.NotCurrentLeaderException; import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockLeaseRefresher; @@ -31,6 +31,7 @@ import com.palantir.lock.v2.LockToken; import com.palantir.lock.v2.StartIdentifiedAtlasDbTransactionResponse; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.timestamp.CloseableTimestampService; @@ -39,6 +40,7 @@ import java.net.ConnectException; import java.net.UnknownHostException; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ScheduledExecutorService; @@ -184,15 +186,14 @@ public long currentTimeMillis() { @ReviewedRestrictedApiUsage @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { - return delegate.acquireNamedMinTimestampLease(timestampName, numFreshTimestamps); + public TimestampLeaseResults acquireTimestampLeases(Map requests) { + return executeOnTimeLock(() -> delegate.acquireTimestampLeases(requests)); } @ReviewedRestrictedApiUsage @Override - public long getMinLeasedTimestampForName(String timestampName) { - return delegate.getMinLeasedTimestampForName(timestampName); + public Map getMinLeasedTimestamps(Set timestampNames) { + return executeOnTimeLock(() -> delegate.getMinLeasedTimestamps(timestampNames)); } private static T executeOnTimeLock(Callable callable) { diff --git a/lock-api/src/main/java/com/palantir/lock/client/UnreliableTimeLockService.java b/lock-api/src/main/java/com/palantir/lock/client/UnreliableTimeLockService.java index 17852ad8e65..28ea7e04d11 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/UnreliableTimeLockService.java +++ b/lock-api/src/main/java/com/palantir/lock/client/UnreliableTimeLockService.java @@ -19,8 +19,8 @@ import com.google.common.collect.Sets; import com.palantir.atlasdb.buggify.api.BuggifyFactory; import com.palantir.atlasdb.buggify.impl.DefaultBuggifyFactory; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.lock.annotations.ReviewedRestrictedApiUsage; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; @@ -28,6 +28,7 @@ import com.palantir.lock.v2.LockToken; import com.palantir.lock.v2.StartIdentifiedAtlasDbTransactionResponse; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.logsafe.SafeArg; @@ -35,6 +36,7 @@ import com.palantir.logsafe.logger.SafeLoggerFactory; import com.palantir.timestamp.TimestampRange; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -159,15 +161,14 @@ public long currentTimeMillis() { @ReviewedRestrictedApiUsage @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { - return delegate.acquireNamedMinTimestampLease(timestampName, numFreshTimestamps); + public TimestampLeaseResults acquireTimestampLeases(Map requests) { + return delegate.acquireTimestampLeases(requests); } @ReviewedRestrictedApiUsage @Override - public long getMinLeasedTimestampForName(String timestampName) { - return delegate.getMinLeasedTimestampForName(timestampName); + public Map getMinLeasedTimestamps(Set timestampNames) { + return delegate.getMinLeasedTimestamps(timestampNames); } private void maybeRandomlyIncreaseTimestamp() { diff --git a/lock-impl/build.gradle b/lock-impl/build.gradle index ae3ee7ded2d..b677d0d072a 100644 --- a/lock-impl/build.gradle +++ b/lock-impl/build.gradle @@ -19,6 +19,7 @@ dependencies { implementation project(":atlasdb-commons") implementation project(':commons-executors') implementation project(':lock-api-objects') + implementation project(':timelock-api') implementation project(':timestamp-api') testImplementation 'com.fasterxml.jackson.core:jackson-databind' diff --git a/lock-impl/src/main/java/com/palantir/lock/impl/LegacyTimelockService.java b/lock-impl/src/main/java/com/palantir/lock/impl/LegacyTimelockService.java index 855e04359c7..f65873a0114 100644 --- a/lock-impl/src/main/java/com/palantir/lock/impl/LegacyTimelockService.java +++ b/lock-impl/src/main/java/com/palantir/lock/impl/LegacyTimelockService.java @@ -16,6 +16,7 @@ package com.palantir.lock.impl; import com.google.common.collect.ImmutableSortedMap; +import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.common.base.Throwables; import com.palantir.lock.AtlasTimestampLockDescriptor; import com.palantir.lock.LockClient; @@ -24,18 +25,19 @@ import com.palantir.lock.LockRefreshToken; import com.palantir.lock.LockService; import com.palantir.lock.SimpleTimeDuration; -import com.palantir.lock.v2.AcquireNamedMinTimestampLeaseResult; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; import com.palantir.lock.v2.LockResponse; import com.palantir.lock.v2.LockToken; import com.palantir.lock.v2.TimelockService; +import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.lock.v2.WaitForLocksRequest; import com.palantir.lock.v2.WaitForLocksResponse; import com.palantir.timestamp.TimestampRange; import com.palantir.timestamp.TimestampService; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -183,14 +185,13 @@ public long currentTimeMillis() { } @Override - public AcquireNamedMinTimestampLeaseResult acquireNamedMinTimestampLease( - String timestampName, int numFreshTimestamps) { + public TimestampLeaseResults acquireTimestampLeases(Map requests) { // TODO(aalouane): implement! throw new UnsupportedOperationException("Not implemented yet!"); } @Override - public long getMinLeasedTimestampForName(String timestampName) { + public Map getMinLeasedTimestamps(Set timestampNames) { // TODO(aalouane): implement! throw new UnsupportedOperationException("Not implemented yet!"); } diff --git a/timelock-api/src/main/conjure/timelock-api.yml b/timelock-api/src/main/conjure/timelock-api.yml index 59e5038b56a..4c714c9957a 100644 --- a/timelock-api/src/main/conjure/timelock-api.yml +++ b/timelock-api/src/main/conjure/timelock-api.yml @@ -233,12 +233,12 @@ types: safety: safe TimestampLeaseRequests: fields: - requestsId: RequestId + requestId: RequestId numFreshTimestamps: map - TimestampLeasesRequest: + NamespaceTimestampLeaseRequest: alias: list MultiClientTimestampLeaseRequest: - alias: map + alias: map TimestampLeaseResponse: fields: minLeased: Long @@ -247,11 +247,11 @@ types: fields: leaseGuarantee: LeaseGuarantee timestampLeaseResponses: map - TimestampLeasesResponse: + NamespaceTimestampLeaseResponse: fields: alias: list MultiClientTimestampLeaseResponse: - alias: map + alias: map GetMinLeasedTimestampRequests: alias: list MultiClientGetMinLeasedTimestampRequest: diff --git a/timelock-api/src/main/java/com/palantir/atlasdb/timelock/api/TimestampLeaseName.java b/timelock-api/src/main/java/com/palantir/atlasdb/timelock/api/TimestampLeaseName.java index c61af973bcb..3031da7094c 100644 --- a/timelock-api/src/main/java/com/palantir/atlasdb/timelock/api/TimestampLeaseName.java +++ b/timelock-api/src/main/java/com/palantir/atlasdb/timelock/api/TimestampLeaseName.java @@ -21,12 +21,15 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.palantir.logsafe.Preconditions; import com.palantir.logsafe.SafeArg; +import java.util.Comparator; import org.immutables.value.Value; @JsonDeserialize(as = ImmutableTimestampLeaseName.class) @JsonSerialize(as = ImmutableTimestampLeaseName.class) @Value.Immutable public interface TimestampLeaseName { + Comparator COMPARATOR = Comparator.comparing(TimestampLeaseName::name); + String RESERVED_NAME_FOR_IMMUTABLE_TIMESTAMP = "ImmutableTimestamp"; @JsonValue diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImpl.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImpl.java index 2bd10ef0380..fce23c6cdac 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImpl.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImpl.java @@ -16,6 +16,7 @@ package com.palantir.atlasdb.timelock; import com.codahale.metrics.Histogram; +import com.google.common.collect.ImmutableSortedSet; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; @@ -65,6 +66,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.SortedSet; import java.util.UUID; import java.util.function.Supplier; @@ -264,10 +266,13 @@ public ListenableFuture acquireTimestampLease( UUID requestId, Map numFreshTimestamps) { long timestamp = timestampService.getFreshTimestamp(); + SortedSet timestampNames = + ImmutableSortedSet.copyOf(TimestampLeaseName.COMPARATOR, numFreshTimestamps.keySet()); Leased leasedLock = lockService - .acquireTimestampLease(requestId, numFreshTimestamps.keySet(), timestamp) + .acquireTimestampLease(requestId, timestampNames, timestamp) .get(); + // it is crucial that the timestamps acquired are AFTER the timestamp used for locking Map responses = KeyedStream.stream(numFreshTimestamps) .map((timestampName, numFreshTimestampsForName) -> getMinLeasedAndFreshTimestamps(timestampName, numFreshTimestampsForName, timestamp)) diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingMultiClientTimestampLeaseServiceAdapter.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingMultiClientTimestampLeaseServiceAdapter.java index 44e15b7082c..a0045efba1b 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingMultiClientTimestampLeaseServiceAdapter.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingMultiClientTimestampLeaseServiceAdapter.java @@ -27,7 +27,7 @@ import com.palantir.atlasdb.timelock.api.MultiClientTimestampLeaseRequest; import com.palantir.atlasdb.timelock.api.MultiClientTimestampLeaseResponse; import com.palantir.atlasdb.timelock.api.Namespace; -import com.palantir.atlasdb.timelock.api.TimestampLeasesResponse; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseResponse; import com.palantir.common.streams.KeyedStream; import com.palantir.conjure.java.undertow.lib.RequestContext; import java.util.Map; @@ -46,7 +46,7 @@ private RemotingMultiClientTimestampLeaseServiceAdapter(RemotingTimestampLeaseSe ListenableFuture acquireTimestampLeases( MultiClientTimestampLeaseRequest requests, @Nullable RequestContext context) { - Map> futures = KeyedStream.stream(requests.get()) + Map> futures = KeyedStream.stream(requests.get()) .map((namespace, request) -> delegate.acquireTimestampLeases(namespace, request, context)) .collectToMap(); diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapter.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapter.java index 35029459c3f..fda56f79aba 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapter.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapter.java @@ -26,11 +26,11 @@ import com.palantir.atlasdb.timelock.api.GetMinLeasedTimestampRequests; import com.palantir.atlasdb.timelock.api.GetMinLeasedTimestampResponses; import com.palantir.atlasdb.timelock.api.Namespace; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseRequest; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseResponse; import com.palantir.atlasdb.timelock.api.RequestId; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.atlasdb.timelock.api.TimestampLeaseResponses; -import com.palantir.atlasdb.timelock.api.TimestampLeasesRequest; -import com.palantir.atlasdb.timelock.api.TimestampLeasesResponse; import com.palantir.common.streams.KeyedStream; import com.palantir.conjure.java.undertow.lib.RequestContext; import java.util.List; @@ -45,18 +45,17 @@ final class RemotingTimestampLeaseServiceAdapter { this.timelockServices = timelockServices; } - ListenableFuture acquireTimestampLeases( - Namespace namespace, TimestampLeasesRequest requests, @Nullable RequestContext context) { + ListenableFuture acquireTimestampLeases( + Namespace namespace, NamespaceTimestampLeaseRequest requests, @Nullable RequestContext context) { AsyncTimelockService service = getServiceForNamespace(namespace, context); List> futures = requests.get().stream() - .map(request -> - acquireTimestampLease(service, request.getRequestsId(), request.getNumFreshTimestamps())) + .map(request -> acquireTimestampLease(service, request.getRequestId(), request.getNumFreshTimestamps())) .collect(Collectors.toList()); // TODO(aalouane): clean up lease resources in cases of partial failures return Futures.transform( - Futures.allAsList(futures), TimestampLeasesResponse::of, MoreExecutors.directExecutor()); + Futures.allAsList(futures), NamespaceTimestampLeaseResponse::of, MoreExecutors.directExecutor()); } ListenableFuture getMinLeasedTimestamps( diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java index 47e1ca3efbf..967cb8f5abe 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java @@ -144,7 +144,7 @@ public AsyncResult> lockImmutableTimestamp(UUID requestId, lon public AsyncResult> acquireTimestampLease( UUID requestId, Set timestampNames, long timestamp) { return heldLocks.getExistingOrAcquire( - requestId, () -> acquireNamedTimestampLockInternal(requestId, timestampNames, timestamp)); + requestId, () -> acquireNamedTimestampLocksInternal(requestId, timestampNames, timestamp)); } public AsyncResult waitForLocks(UUID requestId, Set lockDescriptors, TimeLimit timeout) { @@ -178,7 +178,7 @@ private AsyncResult acquireImmutableTimestampLock(UUID requestId, lon return lockAcquirer.acquireLocks(requestId, OrderedLocks.fromSingleLock(immutableTsLock), TimeLimit.zero()); } - private AsyncResult acquireNamedTimestampLockInternal( + private AsyncResult acquireNamedTimestampLocksInternal( UUID requestId, Set timestampNames, long timestamp) { List locks = timestampNames.stream() .map(name -> lockManager.getNamedTimestampLock(name, timestamp)) diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/MultiClientConjureTimelockResourceTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/MultiClientConjureTimelockResourceTest.java index 76c3045715f..689f7849a86 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/MultiClientConjureTimelockResourceTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/MultiClientConjureTimelockResourceTest.java @@ -46,13 +46,13 @@ import com.palantir.atlasdb.timelock.api.MultiClientTimestampLeaseRequest; import com.palantir.atlasdb.timelock.api.MultiClientTimestampLeaseResponse; import com.palantir.atlasdb.timelock.api.Namespace; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseRequest; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseResponse; import com.palantir.atlasdb.timelock.api.RequestId; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; import com.palantir.atlasdb.timelock.api.TimestampLeaseRequests; import com.palantir.atlasdb.timelock.api.TimestampLeaseResponse; import com.palantir.atlasdb.timelock.api.TimestampLeaseResponses; -import com.palantir.atlasdb.timelock.api.TimestampLeasesRequest; -import com.palantir.atlasdb.timelock.api.TimestampLeasesResponse; import com.palantir.atlasdb.util.TimelockTestUtils; import com.palantir.common.streams.KeyedStream; import com.palantir.common.time.NanoTime; @@ -219,11 +219,11 @@ public void canAcquireNamedMinTimestampLease() { stubAcquireNamedMinTimestampLeaseInResource(serviceForClient2, requestForClient2, responseForClient2); MultiClientTimestampLeaseRequest request = MultiClientTimestampLeaseRequest.of(Map.of( - client1, TimestampLeasesRequest.of(List.of(request1ForClient1, request2ForClient1)), - client2, TimestampLeasesRequest.of(List.of(requestForClient2)))); + client1, NamespaceTimestampLeaseRequest.of(List.of(request1ForClient1, request2ForClient1)), + client2, NamespaceTimestampLeaseRequest.of(List.of(requestForClient2)))); MultiClientTimestampLeaseResponse response = MultiClientTimestampLeaseResponse.of(Map.of( - client1, TimestampLeasesResponse.of(List.of(response1ForClient1, response2ForClient1)), - client2, TimestampLeasesResponse.of(List.of(responseForClient2)))); + client1, NamespaceTimestampLeaseResponse.of(List.of(response1ForClient1, response2ForClient1)), + client2, NamespaceTimestampLeaseResponse.of(List.of(responseForClient2)))); assertThat(Futures.getUnchecked(resource.acquireTimestampLease(AUTH_HEADER, request, REQUEST_CONTEXT))) .isEqualTo(response); } @@ -330,7 +330,7 @@ private Integer getInclusiveLowerCommitTs(String namespace) { private static void stubAcquireNamedMinTimestampLeaseInResource( AsyncTimelockService service, TimestampLeaseRequests request, TimestampLeaseResponses response) { - when(service.acquireTimestampLease(request.getRequestsId().get(), request.getNumFreshTimestamps())) + when(service.acquireTimestampLease(request.getRequestId().get(), request.getNumFreshTimestamps())) .thenReturn(Futures.immediateFuture(response)); } @@ -341,7 +341,7 @@ private static void stubGetMinLeasedNamedTimestampInResource( private static TimestampLeaseRequests createTimestampLeasesRequest(TimestampLeaseName... names) { TimestampLeaseRequests.Builder builder = - TimestampLeaseRequests.builder().requestsId(RequestId.of(UUID.randomUUID())); + TimestampLeaseRequests.builder().requestId(RequestId.of(UUID.randomUUID())); Map numFreshTimestamps = KeyedStream.of(Arrays.stream(names)) .map(_name -> createRandomPositiveInteger()) @@ -352,7 +352,7 @@ private static TimestampLeaseRequests createTimestampLeasesRequest(TimestampLeas private static TimestampLeaseResponses createTimestampLeasesResponseFor(TimestampLeaseRequests request1ForClient1) { return TimestampLeaseResponses.builder() - .leaseGuarantee(createRandomLeaseGuarantee(request1ForClient1.getRequestsId())) + .leaseGuarantee(createRandomLeaseGuarantee(request1ForClient1.getRequestId())) .timestampLeaseResponses(KeyedStream.stream(request1ForClient1.getNumFreshTimestamps()) .map(_name -> createTimestampLeaseResponse()) .collectToMap())