diff --git a/atlasdb-config/src/main/java/com/palantir/atlasdb/factory/DefaultLockAndTimestampServiceFactory.java b/atlasdb-config/src/main/java/com/palantir/atlasdb/factory/DefaultLockAndTimestampServiceFactory.java index df7d0609086..e9039c6b5c8 100644 --- a/atlasdb-config/src/main/java/com/palantir/atlasdb/factory/DefaultLockAndTimestampServiceFactory.java +++ b/atlasdb-config/src/main/java/com/palantir/atlasdb/factory/DefaultLockAndTimestampServiceFactory.java @@ -30,6 +30,7 @@ import com.palantir.atlasdb.keyvalue.api.watch.LockWatchManagerInternal; import com.palantir.atlasdb.table.description.Schema; import com.palantir.atlasdb.timelock.api.ConjureTimelockService; +import com.palantir.atlasdb.timelock.api.Namespace; import com.palantir.atlasdb.transaction.impl.InstrumentedTimelockService; import com.palantir.atlasdb.transaction.impl.TimelockTimestampServiceAdapter; import com.palantir.atlasdb.util.MetricsManager; @@ -45,6 +46,7 @@ import com.palantir.lock.client.LeaderTimeGetter; import com.palantir.lock.client.LegacyLeaderTimeGetter; import com.palantir.lock.client.LegacyLockTokenUnlocker; +import com.palantir.lock.client.LockLeaseService; import com.palantir.lock.client.LockTokenUnlocker; import com.palantir.lock.client.MultiClientTimeLockUnlocker; import com.palantir.lock.client.NamespacedCoalescingLeaderTimeGetter; @@ -60,6 +62,12 @@ import com.palantir.lock.client.TimeLockClient; import com.palantir.lock.client.TimestampCorroboratingTimelockService; import com.palantir.lock.client.metrics.TimeLockFeedbackBackgroundTask; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetter; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseService; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseServiceImpl; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirer; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirerImpl; import com.palantir.lock.impl.LegacyTimelockService; import com.palantir.lock.v2.DefaultNamespacedTimelockRpcClient; import com.palantir.lock.v2.NamespacedTimelockRpcClient; @@ -355,20 +363,14 @@ private static LockAndTimestampServices getLockAndTimestampServices( lockWatchDiagnosticsService); LockWatchManagerInternal lockWatchManager = timeLockHelperServices.lockWatchManager(); - RemoteTimelockServiceAdapter remoteTimelockServiceAdapter = RemoteTimelockServiceAdapter.create( - namespacedTimelockRpcClient, + RemoteTimelockServiceAdapter remoteTimelockServiceAdapter = createRemoteTimelockServiceAdapter( + timelockNamespace, + timelockRequestBatcherProviders, namespacedConjureTimelockService, - getLeaderTimeGetter( - timelockNamespace, - timelockRequestBatcherProviders, - namespacedConjureTimelockService, - multiClientTimelockServiceSupplier), - timeLockHelperServices.requestBatchersFactory(), - getTimeLockUnlocker( - timelockNamespace, - timelockRequestBatcherProviders, - namespacedConjureTimelockService, - multiClientTimelockServiceSupplier)); + multiClientTimelockServiceSupplier, + namespacedTimelockRpcClient, + timeLockHelperServices.requestBatchersFactory()); + TimestampManagementService timestampManagementService = new RemoteTimestampManagementAdapter( serviceProvider.getTimestampManagementRpcClient(), timelockNamespace); @@ -383,6 +385,45 @@ private static LockAndTimestampServices getLockAndTimestampServices( .build(); } + private static RemoteTimelockServiceAdapter createRemoteTimelockServiceAdapter( + String timelockNamespace, + Optional timelockRequestBatcherProviders, + NamespacedConjureTimelockService namespacedConjureTimelockService, + Supplier multiClientTimelockServiceSupplier, + NamespacedTimelockRpcClient namespacedTimelockRpcClient, + RequestBatchersFactory batchersFactory) { + LockTokenUnlocker unlocker = getTimeLockUnlocker( + timelockNamespace, + timelockRequestBatcherProviders, + namespacedConjureTimelockService, + multiClientTimelockServiceSupplier); + + NamespacedTimestampLeaseService timestampLeaseService = new NamespacedTimestampLeaseServiceImpl( + Namespace.of(timelockNamespace), multiClientTimelockServiceSupplier.get()); + + TimestampLeaseAcquirer timestampLeaseAcquirer = + TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker); + + MinLeasedTimestampGetter minLeasedTimestampGetter = new MinLeasedTimestampGetterImpl(timestampLeaseService); + + LockLeaseService lockLeaseService = LockLeaseService.create( + namespacedConjureTimelockService, + getLeaderTimeGetter( + timelockNamespace, + timelockRequestBatcherProviders, + namespacedConjureTimelockService, + multiClientTimelockServiceSupplier), + unlocker); + + return RemoteTimelockServiceAdapter.create( + namespacedTimelockRpcClient, + namespacedConjureTimelockService, + batchersFactory, + lockLeaseService, + timestampLeaseAcquirer, + minLeasedTimestampGetter); + } + // Note: There is some duplication in the following two methods, but extracting a common method requires a fairly // large amount of nontrivial state. Consider extracting a common method if this needs to be implemented again. private static LockTokenUnlocker getTimeLockUnlocker( diff --git a/atlasdb-tests-shared/build.gradle b/atlasdb-tests-shared/build.gradle index 1721bdf6493..5fd9df2223d 100644 --- a/atlasdb-tests-shared/build.gradle +++ b/atlasdb-tests-shared/build.gradle @@ -24,6 +24,7 @@ dependencies { implementation 'com.palantir.refreshable:refreshable' implementation 'com.palantir.safe-logging:safe-logging' implementation 'com.palantir.sls.versions:sls-versions' + implementation 'com.palantir.tokens:auth-tokens' implementation 'com.palantir.tritium:tritium-registry' implementation 'io.dropwizard.metrics:metrics-core' implementation 'org.apache.commons:commons-lang3' @@ -32,7 +33,6 @@ dependencies { implementation 'org.rocksdb:rocksdbjni' implementation 'com.palantir.safe-logging:preconditions-assertj' - implementation project(':atlasdb-api') implementation project(':atlasdb-client') implementation project(':atlasdb-client-protobufs') @@ -45,7 +45,9 @@ dependencies { implementation project(':lock-api-objects') implementation project(':lock-impl') implementation project(':timelock-agent') + implementation project(':timelock-api') implementation project(':timelock-api:timelock-api-jersey') + implementation project(':timelock-api:timelock-api-objects') implementation project(":timelock-impl") implementation project(':timestamp-api') diff --git a/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/AbstractInMemoryTimelockExtension.java b/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/AbstractInMemoryTimelockExtension.java index eca09397212..bf9ec797c59 100644 --- a/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/AbstractInMemoryTimelockExtension.java +++ b/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/AbstractInMemoryTimelockExtension.java @@ -25,6 +25,9 @@ import com.palantir.atlasdb.timelock.ConjureTimelockResource; import com.palantir.atlasdb.timelock.TimeLockServices; import com.palantir.atlasdb.timelock.api.ConjureTimelockService; +import com.palantir.atlasdb.timelock.api.MultiClientConjureTimelockService; +import com.palantir.atlasdb.timelock.api.Namespace; +import com.palantir.atlasdb.timelock.batch.MultiClientConjureTimelockResource; import com.palantir.atlasdb.timelock.lock.LockLog; import com.palantir.atlasdb.util.MetricsManager; import com.palantir.atlasdb.util.MetricsManagers; @@ -36,10 +39,15 @@ import com.palantir.lock.client.LegacyLeaderTimeGetter; import com.palantir.lock.client.LegacyLockTokenUnlocker; import com.palantir.lock.client.LockLeaseService; +import com.palantir.lock.client.LockTokenUnlocker; import com.palantir.lock.client.NamespacedConjureTimelockServiceImpl; import com.palantir.lock.client.RemoteTimelockServiceAdapter; import com.palantir.lock.client.RequestBatchersFactory; import com.palantir.lock.client.TransactionStarter; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseService; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseServiceImpl; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirerImpl; import com.palantir.lock.v2.NamespacedTimelockRpcClient; import com.palantir.lock.v2.TimelockService; import com.palantir.logsafe.exceptions.SafeRuntimeException; @@ -80,6 +88,8 @@ public abstract class AbstractInMemoryTimelockExtension implements TimeLockServi private LockLeaseService lockLeaseService; private NamespacedConjureTimelockServiceImpl namespacedConjureTimelockService; + private NamespacedTimestampLeaseService timestampLeaseService; + private LockTokenUnlocker unlocker; public AbstractInMemoryTimelockExtension() { this("client"); @@ -159,11 +169,19 @@ private void createHelperServices(MetricsManager metricsManager) { RedirectRetryTargeter redirectRetryTargeter = timeLockAgent.redirectRetryTargeter(); ConjureTimelockService conjureTimelockService = ConjureTimelockResource.jersey( redirectRetryTargeter, (_namespace, _context) -> delegate.getTimelockService()); + MultiClientConjureTimelockService multiClientConjureTimelockService = MultiClientConjureTimelockResource.jersey( + redirectRetryTargeter, (_namespace, _context) -> delegate.getTimelockService()); + namespacedConjureTimelockService = new NamespacedConjureTimelockServiceImpl(conjureTimelockService, client); + timestampLeaseService = new NamespacedTimestampLeaseServiceImpl( + Namespace.of(client), + new InMemoryInternalMultiClientConjureTimelockService(multiClientConjureTimelockService)); + + unlocker = new LegacyLockTokenUnlocker(namespacedConjureTimelockService); lockLeaseService = LockLeaseService.create( namespacedConjureTimelockService, new LegacyLeaderTimeGetter(namespacedConjureTimelockService), - new LegacyLockTokenUnlocker(namespacedConjureTimelockService)); + unlocker); } public void tearDown() { @@ -229,7 +247,9 @@ public TimelockService getLegacyTimelockService() { namespacedConjureTimelockService, lockLeaseService, transactionStarter, - commitTimestampGetter); + commitTimestampGetter, + TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker), + new MinLeasedTimestampGetterImpl(timestampLeaseService)); } public LockLeaseService getLockLeaseService() { diff --git a/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/InMemoryInternalMultiClientConjureTimelockService.java b/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/InMemoryInternalMultiClientConjureTimelockService.java new file mode 100644 index 00000000000..20542413784 --- /dev/null +++ b/atlasdb-tests-shared/src/main/java/com/palantir/timelock/paxos/InMemoryInternalMultiClientConjureTimelockService.java @@ -0,0 +1,83 @@ +/* + * (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.timelock.paxos; + +import com.palantir.atlasdb.timelock.api.ConjureStartTransactionsRequest; +import com.palantir.atlasdb.timelock.api.ConjureStartTransactionsResponse; +import com.palantir.atlasdb.timelock.api.ConjureUnlockRequestV2; +import com.palantir.atlasdb.timelock.api.ConjureUnlockResponseV2; +import com.palantir.atlasdb.timelock.api.GetCommitTimestampsRequest; +import com.palantir.atlasdb.timelock.api.GetCommitTimestampsResponse; +import com.palantir.atlasdb.timelock.api.GetMinLeasedTimestampRequests; +import com.palantir.atlasdb.timelock.api.GetMinLeasedTimestampResponses; +import com.palantir.atlasdb.timelock.api.LeaderTimes; +import com.palantir.atlasdb.timelock.api.MultiClientConjureTimelockService; +import com.palantir.atlasdb.timelock.api.MultiClientGetMinLeasedTimestampRequest; +import com.palantir.atlasdb.timelock.api.MultiClientTimestampLeaseRequest; +import com.palantir.atlasdb.timelock.api.Namespace; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseRequest; +import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseResponse; +import com.palantir.lock.client.InternalMultiClientConjureTimelockService; +import com.palantir.tokens.auth.AuthHeader; +import java.util.Map; +import java.util.Set; + +final class InMemoryInternalMultiClientConjureTimelockService implements InternalMultiClientConjureTimelockService { + private static final AuthHeader AUTH_HEADER = AuthHeader.valueOf("Bearer omitted"); + + private final MultiClientConjureTimelockService delegate; + + InMemoryInternalMultiClientConjureTimelockService(MultiClientConjureTimelockService delegate) { + this.delegate = delegate; + } + + @Override + public LeaderTimes leaderTimes(Set namespaces) { + return delegate.leaderTimes(AUTH_HEADER, namespaces); + } + + @Override + public Map getCommitTimestamps( + Map requests) { + return delegate.getCommitTimestampsForClients(AUTH_HEADER, requests); + } + + @Override + public Map startTransactions( + Map requests) { + return delegate.startTransactions(AUTH_HEADER, requests); + } + + @Override + public Map unlock(Map requests) { + return delegate.unlock(AUTH_HEADER, requests); + } + + @Override + public Map acquireTimestampLeases( + Map requests) { + return delegate.acquireTimestampLease(AUTH_HEADER, MultiClientTimestampLeaseRequest.of(requests)) + .get(); + } + + @Override + public Map getMinLeasedTimestamps( + Map requests) { + return delegate.getMinLeasedTimestamp(AUTH_HEADER, MultiClientGetMinLeasedTimestampRequest.of(requests)) + .get(); + } +} 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 1768809f58e..bc1941eb0f4 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 @@ -21,6 +21,8 @@ import com.palantir.atlasdb.timelock.api.ConjureTimestampRange; import com.palantir.atlasdb.timelock.api.Namespace; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetter; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirer; import com.palantir.lock.v2.ClientLockingOptions; import com.palantir.lock.v2.LockImmutableTimestampResponse; import com.palantir.lock.v2.LockRequest; @@ -50,53 +52,73 @@ public final class RemoteTimelockServiceAdapter implements TimelockService, Auto private final LockLeaseService lockLeaseService; private final TransactionStarter transactionStarter; private final CommitTimestampGetter commitTimestampGetter; + private final TimestampLeaseAcquirer timestampLeaseAcquirer; + private final MinLeasedTimestampGetter minLeasedTimestampGetter; - public RemoteTimelockServiceAdapter( + private RemoteTimelockServiceAdapter( NamespacedTimelockRpcClient rpcClient, - NamespacedConjureTimelockService conjureTimelockService, + NamespacedConjureTimelockService conjureClient, LockLeaseService lockLeaseService, - TransactionStarter transactionStarter, - CommitTimestampGetter commitTimestampGetter) { + RequestBatchersFactory batcherFactory, + TimestampLeaseAcquirer timestampLeaseAcquirer, + MinLeasedTimestampGetter minLeasedTimestampGetter) { this.rpcClient = rpcClient; - this.conjureTimelockService = conjureTimelockService; + this.conjureTimelockService = conjureClient; this.lockLeaseService = lockLeaseService; - this.transactionStarter = transactionStarter; - this.commitTimestampGetter = commitTimestampGetter; + this.transactionStarter = TransactionStarter.create(lockLeaseService, batcherFactory); + this.commitTimestampGetter = batcherFactory.createBatchingCommitTimestampGetter(lockLeaseService); + this.timestampLeaseAcquirer = timestampLeaseAcquirer; + this.minLeasedTimestampGetter = minLeasedTimestampGetter; } - private RemoteTimelockServiceAdapter( + public RemoteTimelockServiceAdapter( NamespacedTimelockRpcClient rpcClient, NamespacedConjureTimelockService conjureTimelockService, - LeaderTimeGetter leaderTimeGetter, - RequestBatchersFactory batcherFactory, - LockTokenUnlocker unlocker) { + LockLeaseService lockLeaseService, + TransactionStarter transactionStarter, + CommitTimestampGetter commitTimestampGetter, + TimestampLeaseAcquirer timestampLeaseAcquirer, + MinLeasedTimestampGetter minLeasedTimestampGetter) { this.rpcClient = rpcClient; - this.lockLeaseService = LockLeaseService.create(conjureTimelockService, leaderTimeGetter, unlocker); - this.transactionStarter = TransactionStarter.create(lockLeaseService, batcherFactory); - this.commitTimestampGetter = batcherFactory.createBatchingCommitTimestampGetter(lockLeaseService); this.conjureTimelockService = conjureTimelockService; + this.lockLeaseService = lockLeaseService; + this.transactionStarter = transactionStarter; + this.commitTimestampGetter = commitTimestampGetter; + this.timestampLeaseAcquirer = timestampLeaseAcquirer; + this.minLeasedTimestampGetter = minLeasedTimestampGetter; } - public static RemoteTimelockServiceAdapter create( + public static TimelockService create( Namespace namespace, NamespacedTimelockRpcClient rpcClient, NamespacedConjureTimelockService conjureClient, - LockWatchCache lockWatchCache) { - return create( + LockWatchCache lockWatchCache, + LockLeaseService lockLeaseService, + TimestampLeaseAcquirer timestampLeaseAcquirer, + MinLeasedTimestampGetter minLeasedTimestampGetter) { + return new RemoteTimelockServiceAdapter( rpcClient, conjureClient, - new LegacyLeaderTimeGetter(conjureClient), + lockLeaseService, RequestBatchersFactory.create(lockWatchCache, namespace, Optional.empty()), - new LegacyLockTokenUnlocker(conjureClient)); + timestampLeaseAcquirer, + minLeasedTimestampGetter); } public static RemoteTimelockServiceAdapter create( NamespacedTimelockRpcClient rpcClient, NamespacedConjureTimelockService conjureClient, - LeaderTimeGetter leaderTimeGetter, RequestBatchersFactory batcherFactory, - LockTokenUnlocker unlocker) { - return new RemoteTimelockServiceAdapter(rpcClient, conjureClient, leaderTimeGetter, batcherFactory, unlocker); + LockLeaseService lockLeaseService, + TimestampLeaseAcquirer timestampLeaseAcquirer, + MinLeasedTimestampGetter minLeasedTimestampGetter) { + return new RemoteTimelockServiceAdapter( + rpcClient, + conjureClient, + lockLeaseService, + batcherFactory, + timestampLeaseAcquirer, + minLeasedTimestampGetter); } @Override @@ -173,14 +195,12 @@ public long currentTimeMillis() { @Override public TimestampLeaseResults acquireTimestampLeases(Map requests) { - // TODO(aalouane): implement! - throw new UnsupportedOperationException("Not implemented yet!"); + return timestampLeaseAcquirer.acquireNamedTimestampLeases(requests); } @Override public Map getMinLeasedTimestamps(Set timestampNames) { - // TODO(aalouane): implement! - throw new UnsupportedOperationException("Not implemented yet!"); + return minLeasedTimestampGetter.getMinLeasedTimestamps(timestampNames); } @Override @@ -188,5 +208,7 @@ public void close() { transactionStarter.close(); commitTimestampGetter.close(); lockLeaseService.close(); + timestampLeaseAcquirer.close(); + minLeasedTimestampGetter.close(); } } diff --git a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/MinLeasedTimestampGetter.java b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/MinLeasedTimestampGetter.java index db3c4c1ad38..f2ab8ea45d6 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/MinLeasedTimestampGetter.java +++ b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/MinLeasedTimestampGetter.java @@ -20,7 +20,7 @@ import java.util.Map; import java.util.Set; -interface MinLeasedTimestampGetter extends AutoCloseable { +public interface MinLeasedTimestampGetter extends AutoCloseable { Map getMinLeasedTimestamps(Set timestampNames); @Override diff --git a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/NamespacedTimestampLeaseServiceImpl.java b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/NamespacedTimestampLeaseServiceImpl.java index 001e4973a0e..3fbef676fed 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/NamespacedTimestampLeaseServiceImpl.java +++ b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/NamespacedTimestampLeaseServiceImpl.java @@ -26,11 +26,12 @@ import com.palantir.logsafe.exceptions.SafeRuntimeException; import java.util.Map; -final class NamespacedTimestampLeaseServiceImpl implements NamespacedTimestampLeaseService { +public final class NamespacedTimestampLeaseServiceImpl implements NamespacedTimestampLeaseService { private final Namespace namespace; private final InternalMultiClientConjureTimelockService delegate; - NamespacedTimestampLeaseServiceImpl(Namespace namespace, InternalMultiClientConjureTimelockService delegate) { + public NamespacedTimestampLeaseServiceImpl( + Namespace namespace, InternalMultiClientConjureTimelockService delegate) { this.namespace = namespace; this.delegate = delegate; } diff --git a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirer.java b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirer.java index d858fb5b9a0..3e7e7d572d2 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirer.java +++ b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirer.java @@ -20,7 +20,7 @@ import com.palantir.lock.v2.TimestampLeaseResults; import java.util.Map; -interface TimestampLeaseAcquirer extends AutoCloseable { +public interface TimestampLeaseAcquirer extends AutoCloseable { TimestampLeaseResults acquireNamedTimestampLeases(Map requests); @Override diff --git a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirerImpl.java b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirerImpl.java index 212b38e1ffe..6ad336b7f79 100644 --- a/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirerImpl.java +++ b/lock-api/src/main/java/com/palantir/lock/client/timestampleases/TimestampLeaseAcquirerImpl.java @@ -24,6 +24,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Iterables; import com.palantir.atlasdb.timelock.api.ConjureLockToken; +import com.palantir.atlasdb.timelock.api.ConjureLockTokenV2; import com.palantir.atlasdb.timelock.api.LeaseGuarantee; import com.palantir.atlasdb.timelock.api.LeaseIdentifier; import com.palantir.atlasdb.timelock.api.NamespaceTimestampLeaseRequest; @@ -37,6 +38,7 @@ import com.palantir.lock.ConjureTimestampRangeTimestampSupplier; import com.palantir.lock.LimitingLongSupplier; import com.palantir.lock.client.LeasedLockToken; +import com.palantir.lock.client.LockTokenUnlocker; import com.palantir.lock.v2.TimestampLeaseResult; import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.logsafe.Preconditions; @@ -48,12 +50,13 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.function.LongSupplier; import java.util.function.Supplier; -final class TimestampLeaseAcquirerImpl implements TimestampLeaseAcquirer { +public final class TimestampLeaseAcquirerImpl implements TimestampLeaseAcquirer { private static final SafeLogger log = SafeLoggerFactory.get(TimestampLeaseAcquirerImpl.class); private final NamespacedTimestampLeaseService delegate; @@ -74,10 +77,15 @@ final class TimestampLeaseAcquirerImpl implements TimestampLeaseAcquirer { this.uuidSupplier = uuidSupplier; } - public TimestampLeaseAcquirerImpl(NamespacedTimestampLeaseService delegate, Unlocker unlocker) { + private TimestampLeaseAcquirerImpl(NamespacedTimestampLeaseService delegate, Unlocker unlocker) { this(delegate, unlocker, UniqueIds::pseudoRandomUuidV4); } + public static TimestampLeaseAcquirer create( + NamespacedTimestampLeaseService timestampLeaseService, LockTokenUnlocker unlocker) { + return new TimestampLeaseAcquirerImpl(timestampLeaseService, identifier -> unlock(unlocker, identifier)); + } + @Override public TimestampLeaseResults acquireNamedTimestampLeases(Map requests) { TimestampLeaseResponses response = acquireLeasesWithRetry(requests); @@ -161,6 +169,10 @@ private void unlock(TimestampLeaseResponses responses) { unlocker.unlock(responses.getLeaseGuarantee().getIdentifier()); } + private static void unlock(LockTokenUnlocker unlocker, LeaseIdentifier leaseGuarantee) { + unlocker.unlock(Set.of(ConjureLockTokenV2.of(leaseGuarantee.get()))); + } + private static Map createTimestampLeaseResult( Map requestedTimestamps, Map responses) { diff --git a/timelock-server/src/testCommon/java/com/palantir/atlasdb/timelock/NamespacedClients.java b/timelock-server/src/testCommon/java/com/palantir/atlasdb/timelock/NamespacedClients.java index dbb3a78a05e..06786f0cbcb 100644 --- a/timelock-server/src/testCommon/java/com/palantir/atlasdb/timelock/NamespacedClients.java +++ b/timelock-server/src/testCommon/java/com/palantir/atlasdb/timelock/NamespacedClients.java @@ -18,15 +18,28 @@ import com.google.common.collect.ImmutableSet; import com.palantir.atlasdb.timelock.api.ConjureTimelockService; +import com.palantir.atlasdb.timelock.api.MultiClientConjureTimelockServiceBlocking; import com.palantir.atlasdb.timelock.api.Namespace; import com.palantir.atlasdb.timelock.util.TestProxies.ProxyMode; import com.palantir.lock.ConjureLockV1Service; import com.palantir.lock.LockRpcClient; import com.palantir.lock.LockService; +import com.palantir.lock.client.AuthenticatedInternalMultiClientConjureTimelockService; +import com.palantir.lock.client.InternalMultiClientConjureTimelockService; +import com.palantir.lock.client.LegacyLeaderTimeGetter; +import com.palantir.lock.client.LegacyLockTokenUnlocker; +import com.palantir.lock.client.LockLeaseService; +import com.palantir.lock.client.LockTokenUnlocker; import com.palantir.lock.client.NamespacedConjureTimelockService; import com.palantir.lock.client.NamespacedConjureTimelockServiceImpl; import com.palantir.lock.client.RemoteLockServiceAdapter; import com.palantir.lock.client.RemoteTimelockServiceAdapter; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetter; +import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseService; +import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseServiceImpl; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirer; +import com.palantir.lock.client.timestampleases.TimestampLeaseAcquirerImpl; import com.palantir.lock.v2.DefaultNamespacedTimelockRpcClient; import com.palantir.lock.v2.LockRequest; import com.palantir.lock.v2.LockResponse; @@ -71,11 +84,29 @@ static NamespacedClients from(String namespace, ProxyFactory proxyFactory) { @Value.Derived default TimelockService timelockService() { + LockTokenUnlocker unlocker = new LegacyLockTokenUnlocker(namespacedConjureTimelockService()); + + LockLeaseService lockLeaseService = LockLeaseService.create( + namespacedConjureTimelockService(), + new LegacyLeaderTimeGetter(namespacedConjureTimelockService()), + unlocker); + + NamespacedTimestampLeaseService timestampLeaseService = new NamespacedTimestampLeaseServiceImpl( + Namespace.of(namespace()), internalMultiClientConjureTimelockService()); + + TimestampLeaseAcquirer timestampLeaseAcquirer = + TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker); + + MinLeasedTimestampGetter minLeasedTimestampGetter = new MinLeasedTimestampGetterImpl(timestampLeaseService); + return RemoteTimelockServiceAdapter.create( Namespace.of(namespace()), namespacedTimelockRpcClient(), namespacedConjureTimelockService(), - lockWatchEventCache()); + lockWatchEventCache(), + lockLeaseService, + timestampLeaseAcquirer, + minLeasedTimestampGetter); } @Value.Default @@ -120,6 +151,16 @@ default TimestampManagementService timestampManagementService() { proxyFactory().createProxy(TimestampManagementRpcClient.class, proxyMode()), namespace()); } + @Value.Derived + default InternalMultiClientConjureTimelockService internalMultiClientConjureTimelockService() { + return new AuthenticatedInternalMultiClientConjureTimelockService(multiClientConjureTimelockService()); + } + + @Value.Derived + default MultiClientConjureTimelockServiceBlocking multiClientConjureTimelockService() { + return proxyFactory().createProxy(MultiClientConjureTimelockServiceBlocking.class, proxyMode()); + } + default long getFreshTimestamp() { return timelockService().getFreshTimestamp(); }