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..de1da0f460e 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; @@ -59,7 +61,14 @@ import com.palantir.lock.client.RequestBatchersFactory; import com.palantir.lock.client.TimeLockClient; import com.palantir.lock.client.TimestampCorroboratingTimelockService; +import com.palantir.lock.client.TimestampLeaseMetrics; 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 +364,15 @@ 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), + multiClientTimelockServiceSupplier, + namespacedTimelockRpcClient, timeLockHelperServices.requestBatchersFactory(), - getTimeLockUnlocker( - timelockNamespace, - timelockRequestBatcherProviders, - namespacedConjureTimelockService, - multiClientTimelockServiceSupplier)); + metricsManager); + TimestampManagementService timestampManagementService = new RemoteTimestampManagementAdapter( serviceProvider.getTimestampManagementRpcClient(), timelockNamespace); @@ -383,6 +387,46 @@ private static LockAndTimestampServices getLockAndTimestampServices( .build(); } + private static RemoteTimelockServiceAdapter createRemoteTimelockServiceAdapter( + String timelockNamespace, + Optional timelockRequestBatcherProviders, + NamespacedConjureTimelockService namespacedConjureTimelockService, + Supplier multiClientTimelockServiceSupplier, + NamespacedTimelockRpcClient namespacedTimelockRpcClient, + RequestBatchersFactory batchersFactory, + MetricsManager metricsManager) { + LockTokenUnlocker unlocker = getTimeLockUnlocker( + timelockNamespace, + timelockRequestBatcherProviders, + namespacedConjureTimelockService, + multiClientTimelockServiceSupplier); + + NamespacedTimestampLeaseService timestampLeaseService = new NamespacedTimestampLeaseServiceImpl( + Namespace.of(timelockNamespace), multiClientTimelockServiceSupplier.get()); + + TimestampLeaseAcquirer timestampLeaseAcquirer = TimestampLeaseAcquirerImpl.create( + timestampLeaseService, unlocker, TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())); + + 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..f1db1deb740 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,16 @@ 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.TimestampLeaseMetrics; 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 +89,9 @@ public abstract class AbstractInMemoryTimelockExtension implements TimeLockServi private LockLeaseService lockLeaseService; private NamespacedConjureTimelockServiceImpl namespacedConjureTimelockService; + private NamespacedTimestampLeaseService timestampLeaseService; + private LockTokenUnlocker unlocker; + private final MetricsManager metricsManager = MetricsManagers.createForTests(); public AbstractInMemoryTimelockExtension() { this("client"); @@ -119,8 +131,6 @@ public void setup() { .clusterSnapshot(clusterConfig) .build(); - MetricsManager metricsManager = MetricsManagers.createForTests(); - timeLockAgent = TimeLockAgent.create( metricsManager, install, @@ -136,7 +146,7 @@ public void setup() { () -> System.exit(0)); delegate = timeLockAgent.createInvalidatingTimeLockServices(client); - createHelperServices(metricsManager); + createHelperServices(); // Wait for leadership Awaitility.await() @@ -146,7 +156,7 @@ public void setup() { .until(() -> delegate.getTimestampService().getFreshTimestamp() > 0); } - private void createHelperServices(MetricsManager metricsManager) { + private void createHelperServices() { helperServices = TimeLockHelperServices.create( client, metricsManager, @@ -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,10 @@ public TimelockService getLegacyTimelockService() { namespacedConjureTimelockService, lockLeaseService, transactionStarter, - commitTimestampGetter); + commitTimestampGetter, + TimestampLeaseAcquirerImpl.create( + timestampLeaseService, unlocker, TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())), + 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/changelog/@unreleased/pr-7397.v2.yml b/changelog/0.1176.0/pr-7397.v2.yml similarity index 100% rename from changelog/@unreleased/pr-7397.v2.yml rename to changelog/0.1176.0/pr-7397.v2.yml diff --git a/lock-api/build.gradle b/lock-api/build.gradle index c486f57caab..b066ca23040 100644 --- a/lock-api/build.gradle +++ b/lock-api/build.gradle @@ -5,6 +5,7 @@ apply plugin: 'com.palantir.metric-schema' license { exclude '**/TimestampCorrectnessMetrics.java' exclude '**/TopologyMetrics.java' + exclude '**/TimestampLeaseMetrics.java' } libsDirName = file('build/artifacts') 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..2930793c30f 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 @@ -16,6 +16,7 @@ package com.palantir.lock.client.timestampleases; +import com.codahale.metrics.Counter; import com.github.rholder.retry.Attempt; import com.github.rholder.retry.RetryException; import com.github.rholder.retry.Retryer; @@ -24,6 +25,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 +39,8 @@ 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.client.TimestampLeaseMetrics; import com.palantir.lock.v2.TimestampLeaseResult; import com.palantir.lock.v2.TimestampLeaseResults; import com.palantir.logsafe.Preconditions; @@ -48,17 +52,19 @@ 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; private final Unlocker unlocker; private final Supplier uuidSupplier; + private final Counter notEnoughFreshTimestampsCounter; private final Retryer> retryer = RetryerBuilder.>newBuilder() @@ -66,16 +72,30 @@ final class TimestampLeaseAcquirerImpl implements TimestampLeaseAcquirer { .withStopStrategy(StopStrategies.stopAfterAttempt(3)) .build(); - @VisibleForTesting - TimestampLeaseAcquirerImpl( - NamespacedTimestampLeaseService delegate, Unlocker unlocker, Supplier uuidSupplier) { + private TimestampLeaseAcquirerImpl( + NamespacedTimestampLeaseService delegate, + Unlocker unlocker, + Supplier uuidSupplier, + Counter notEnoughFreshTimestampsCounter) { this.delegate = delegate; this.unlocker = unlocker; this.uuidSupplier = uuidSupplier; + this.notEnoughFreshTimestampsCounter = notEnoughFreshTimestampsCounter; + } + + @VisibleForTesting + TimestampLeaseAcquirerImpl( + NamespacedTimestampLeaseService delegate, Unlocker unlocker, Supplier uuidSupplier) { + this(delegate, unlocker, uuidSupplier, new Counter()); } - public TimestampLeaseAcquirerImpl(NamespacedTimestampLeaseService delegate, Unlocker unlocker) { - this(delegate, unlocker, UniqueIds::pseudoRandomUuidV4); + public static TimestampLeaseAcquirer create( + NamespacedTimestampLeaseService delegate, LockTokenUnlocker unlocker, TimestampLeaseMetrics metrics) { + return new TimestampLeaseAcquirerImpl( + delegate, + identifier -> unlock(unlocker, identifier), + UniqueIds::pseudoRandomUuidV4, + metrics.notEnoughFreshTimestamps()); } @Override @@ -138,29 +158,37 @@ private Optional acquireLeases(Map { - int requestedTimestamps = requestedFreshTimestamps.get(timestampName); - long returnedTimestamps = - responseMap.get(timestampName).getFreshTimestamps().getCount(); - return returnedTimestamps >= requestedTimestamps; - }); + long wereNotFullyFulfilled = requestedFreshTimestamps.keySet().stream() + .filter(timestampName -> { + int requestedTimestamps = requestedFreshTimestamps.get(timestampName); + long returnedTimestamps = + responseMap.get(timestampName).getFreshTimestamps().getCount(); + return returnedTimestamps < requestedTimestamps; + }) + .count(); + + if (wereNotFullyFulfilled > 0) { + notEnoughFreshTimestampsCounter.inc(wereNotFullyFulfilled); - if (!wasFullyFulfilled) { unlock(response); log.info( "Timestamp lease request was not fully fulfilled. This should happen infrequently.", - SafeArg.of("requests", requests), + SafeArg.of("requests", request), SafeArg.of("responses", response)); return Optional.empty(); + } else { + return Optional.of(response); } - - return Optional.of(response); } 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/lock-api/src/main/metrics/metric-schema.yml b/lock-api/src/main/metrics/metric-schema.yml index 6e06eca0dac..783a157ad05 100644 --- a/lock-api/src/main/metrics/metric-schema.yml +++ b/lock-api/src/main/metrics/metric-schema.yml @@ -30,4 +30,10 @@ namespaces: type: timer docs: observed call duration during leader election + timestampLease: + docs: Timestamp lease client side telemetry + metrics: + notEnoughFreshTimestamps: + type: counter + docs: Counts instances where TimeLock returns less than the requested number of timestamps in acquire timestamp lease calls diff --git a/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java b/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java index 5b9265cf012..a8cba94ed94 100644 --- a/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java +++ b/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java @@ -28,6 +28,7 @@ import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics; import com.palantir.atlasdb.timelock.paxos.LeadershipComponents; import com.palantir.atlasdb.timelock.paxos.LeadershipComponents.LeadershipProxies; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.atlasdb.util.MetricsManager; import com.palantir.common.concurrent.NamedThreadFactory; import com.palantir.common.concurrent.PTExecutors; @@ -96,7 +97,8 @@ private AsyncTimelockService createRawAsyncTimelockService( maybeEnhancedLockLog, reaperExecutor, timeoutExecutor, - BufferMetrics.of(metricsManager.getTaggedRegistry())), + BufferMetrics.of(metricsManager.getTaggedRegistry()), + TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())), timestampServiceSupplier.get(), maybeEnhancedLockLog, RequestMetrics.of(metricsManager.getTaggedRegistry())); diff --git a/timelock-impl/build.gradle b/timelock-impl/build.gradle index 361bcd9ef18..bcaf63a584a 100644 --- a/timelock-impl/build.gradle +++ b/timelock-impl/build.gradle @@ -113,4 +113,5 @@ dependencies { license { exclude '**/RequestMetrics.java' exclude '**/BufferMetrics.java' + exclude '**/TimestampLeaseMetrics.java' } 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 967cb8f5abe..bc6fca41335 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 @@ -21,6 +21,7 @@ import com.palantir.atlasdb.timelock.lock.watch.LockWatchingService; import com.palantir.atlasdb.timelock.lock.watch.LockWatchingServiceImpl; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.lock.LockDescriptor; import com.palantir.lock.v2.LeaderTime; import com.palantir.lock.v2.LockToken; @@ -64,7 +65,8 @@ public static AsyncLockService createDefault( LockLog lockLog, ScheduledExecutorService reaperExecutor, ScheduledExecutorService timeoutExecutor, - BufferMetrics bufferMetrics) { + BufferMetrics bufferMetrics, + TimestampLeaseMetrics timestampLeaseMetrics) { LeaderClock clock = LeaderClock.create(); @@ -73,7 +75,7 @@ public static AsyncLockService createDefault( LockAcquirer lockAcquirer = new LockAcquirer(lockLog, timeoutExecutor, clock, lockWatchingService); return new AsyncLockService( - new LockManager(), + LockManager.create(timestampLeaseMetrics), lockAcquirer, heldLocks, new AwaitedLocksCollection(), diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java index 0b2aae7132d..bd3cd9e9a99 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java @@ -16,14 +16,24 @@ package com.palantir.atlasdb.timelock.lock; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.lock.LockDescriptor; import java.util.Optional; import java.util.Set; final class LockManager { - private final ExclusiveLockCollection exclusiveLocks = new ExclusiveLockCollection(); - private final NamedMinTimestampLockCollection namedMinTimestampLockCollection = - new NamedMinTimestampLockCollection(); + private final ExclusiveLockCollection exclusiveLocks; + private final NamedMinTimestampLockCollection namedMinTimestampLockCollection; + + private LockManager( + ExclusiveLockCollection exclusiveLocks, NamedMinTimestampLockCollection namedMinTimestampLockCollection) { + this.exclusiveLocks = exclusiveLocks; + this.namedMinTimestampLockCollection = namedMinTimestampLockCollection; + } + + static LockManager create(TimestampLeaseMetrics metrics) { + return new LockManager(new ExclusiveLockCollection(), NamedMinTimestampLockCollection.create(metrics)); + } OrderedLocks getAllExclusiveLocks(Set descriptors) { return exclusiveLocks.getAll(descriptors); diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java index 16e4681beb1..87bb4bc93a0 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java @@ -19,11 +19,21 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import java.util.Optional; final class NamedMinTimestampLockCollection { - private final LoadingCache namedMinTimestampTrackers = - Caffeine.newBuilder().build(NamedMinTimestampTrackerImpl::new); + private final LoadingCache namedMinTimestampTrackers; + + private NamedMinTimestampLockCollection(LoadingCache namedMinTimestampTrackers) { + this.namedMinTimestampTrackers = namedMinTimestampTrackers; + } + + static NamedMinTimestampLockCollection create(TimestampLeaseMetrics metrics) { + LoadingCache namedMinTimestampTrackers = + Caffeine.newBuilder().build(name -> NamedMinTimestampTrackerImpl.create(name, metrics)); + return new NamedMinTimestampLockCollection(namedMinTimestampTrackers); + } AsyncLock getImmutableTimestampLock(long timestamp) { return getNamedTimestampLockInternal(TimestampLeaseName.RESERVED_NAME_FOR_IMMUTABLE_TIMESTAMP, timestamp); diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java index ce648ed1ee5..48e28b6c14a 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java @@ -16,6 +16,7 @@ package com.palantir.atlasdb.timelock.lock; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.lock.LockDescriptor; import com.palantir.lock.StringLockDescriptor; import com.palantir.logsafe.SafeArg; @@ -24,16 +25,33 @@ import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import javax.annotation.concurrent.GuardedBy; final class NamedMinTimestampTrackerImpl implements NamedMinTimestampTracker { private final String timestampName; + private final AtomicInteger numLocksHeld; + private final AtomicLong approximateMinLocked; @GuardedBy("this") private final SortedMap holdersByTimestamp = new TreeMap<>(); - NamedMinTimestampTrackerImpl(String timestampName) { + private NamedMinTimestampTrackerImpl( + String timestampName, AtomicInteger numLocksHeld, AtomicLong approximateMinLocked) { this.timestampName = timestampName; + this.numLocksHeld = numLocksHeld; + this.approximateMinLocked = approximateMinLocked; + } + + static NamedMinTimestampTracker create(String timestampName, TimestampLeaseMetrics metrics) { + AtomicInteger numLocksHeld = new AtomicInteger(); + metrics.locksHeld().name(timestampName).build(numLocksHeld::get); + + AtomicLong approximateMinLeased = new AtomicLong(); + metrics.approximateSmallestLeased().name(timestampName).build(approximateMinLeased::get); + + return new NamedMinTimestampTrackerImpl(timestampName, numLocksHeld, approximateMinLeased); } @Override @@ -46,6 +64,7 @@ public synchronized void lock(long timestamp, UUID requestId) { SafeArg.of("requestId", requestId), SafeArg.of("currentHolder", holdersByTimestamp.get(timestamp))); } + numLocksHeld.incrementAndGet(); } @Override @@ -58,6 +77,7 @@ public synchronized void unlock(long timestamp, UUID requestId) { SafeArg.of("requestId", requestId), SafeArg.of("currentHolder", holdersByTimestamp.get(timestamp))); } + numLocksHeld.decrementAndGet(); } @Override @@ -65,7 +85,9 @@ public synchronized Optional getMinimumTimestamp() { if (holdersByTimestamp.isEmpty()) { return Optional.empty(); } - return Optional.of(holdersByTimestamp.firstKey()); + Long minimum = holdersByTimestamp.firstKey(); + approximateMinLocked.set(minimum); + return Optional.of(minimum); } @Override diff --git a/timelock-impl/src/main/metrics/timestampleases.yml b/timelock-impl/src/main/metrics/timestampleases.yml new file mode 100644 index 00000000000..4668031bd03 --- /dev/null +++ b/timelock-impl/src/main/metrics/timestampleases.yml @@ -0,0 +1,17 @@ +options: + javaPackage: 'com.palantir.atlasdb.timelock.timestampleases' + +namespaces: + timestampLease: + docs: Metrics tracking TimeLock's implementation of timestamp leases + metrics: + locksHeld: + docs: Number of locks held in timestamp trackers + type: gauge + tags: + - name + approximateSmallestLeased: + docs: Approximation of the smallest leased timestamp, notably this is updated when a request for it is made + type: gauge + tags: + - name diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java index d42cc2163f4..9a79ae90438 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java @@ -29,6 +29,7 @@ import com.palantir.atlasdb.timelock.lock.LockLog; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.lock.v2.LockToken; import com.palantir.timestamp.InMemoryTimestampService; import com.palantir.timestamp.ManagedTimestampService; @@ -261,7 +262,8 @@ private static AsyncLockService createLockService(ScheduledExecutorService execu new LockLog(new MetricRegistry(), () -> 100L), executor, executor, - BufferMetrics.of(new DefaultTaggedMetricRegistry())); + BufferMetrics.of(new DefaultTaggedMetricRegistry()), + TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); } private static AsyncTimelockService createAsyncTimelockService( diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java index bae17272c87..4482b2e956e 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java @@ -30,6 +30,7 @@ import com.palantir.atlasdb.timelock.lock.LockLog; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.timestamp.InMemoryTimestampService; import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry; import java.util.List; @@ -60,7 +61,8 @@ private AsyncTimelockService createTimelockService() { new LockLog(new MetricRegistry(), () -> 100L), executor, executor, - BufferMetrics.of(new DefaultTaggedMetricRegistry())); + BufferMetrics.of(new DefaultTaggedMetricRegistry()), + TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); return new AsyncTimelockServiceImpl( lockService, diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java index ee97facee0f..d8a400b8cdc 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java @@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.atlasdb.util.MetricsManager; import com.palantir.atlasdb.util.MetricsManagers; import com.palantir.common.concurrent.PTExecutors; @@ -36,7 +37,8 @@ public void executorsShutDownAfterClose() { new LockLog(metricsManager.getRegistry(), () -> 1L), reaperExecutor, timeoutExecutor, - BufferMetrics.of(metricsManager.getTaggedRegistry())); + BufferMetrics.of(metricsManager.getTaggedRegistry()), + TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())); asyncLockService.close(); assertThat(reaperExecutor.isShutdown()).isTrue(); diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java index b0962e3937c..0014ed9afcb 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java @@ -19,6 +19,8 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import com.palantir.atlasdb.timelock.api.TimestampLeaseName; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; +import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry; import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.Set; @@ -32,7 +34,8 @@ public final class NamedMinTimestampLockCollectionTest { private static final UUID REQUEST_ID_2 = UUID.randomUUID(); private static final UUID REQUEST_ID_3 = UUID.randomUUID(); - private final NamedMinTimestampLockCollection locks = new NamedMinTimestampLockCollection(); + private final NamedMinTimestampLockCollection locks = + NamedMinTimestampLockCollection.create(TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); @MethodSource("getTimestampLeaseNames") @ParameterizedTest diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java index 342ca6c4d06..14ce1dd7e94 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java @@ -19,8 +19,10 @@ import static com.palantir.logsafe.testing.Assertions.assertThatLoggableExceptionThrownBy; import static org.assertj.core.api.Assertions.assertThat; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeIllegalStateException; +import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry; import java.nio.charset.StandardCharsets; import java.util.UUID; import org.junit.jupiter.api.Test; @@ -31,7 +33,8 @@ public final class NamedMinTimestampTrackerTest { private static final long TIMESTAMP_1 = 5L; - private final NamedMinTimestampTracker tracker = new NamedMinTimestampTrackerImpl("ts"); + private final NamedMinTimestampTracker tracker = + NamedMinTimestampTrackerImpl.create("ts", TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); @Test public void registersTimestampWhenLocked() { diff --git a/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java b/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java index 70cefd07a3c..3694d38ed76 100644 --- a/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java +++ b/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java @@ -34,6 +34,7 @@ import com.palantir.atlasdb.timelock.lock.LockLog; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.atlasdb.util.MetricsManager; import com.palantir.atlasdb.util.MetricsManagers; import com.palantir.lock.AtlasRowLockDescriptor; @@ -78,7 +79,8 @@ public class AsyncTimeLockServiceMetadataTest { lockLog, scheduledExecutorService, scheduledExecutorService, - BufferMetrics.of(metricsManager.getTaggedRegistry())); + BufferMetrics.of(metricsManager.getTaggedRegistry()), + TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())); private final AsyncTimelockServiceImpl timeLockService = new AsyncTimelockServiceImpl(asyncLockService, new InMemoryTimestampService(), lockLog, requestMetrics); private final ConjureStartTransactionsRequest startTransactionsRequestWithInitialVersion = diff --git a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java index f578e11691d..3efbaab9a3c 100644 --- a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java +++ b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java @@ -23,6 +23,8 @@ import com.palantir.atlasdb.timelock.lock.watch.LockWatchingService; import com.palantir.atlasdb.timelock.lock.watch.LockWatchingServiceImpl; import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; +import com.palantir.atlasdb.util.MetricsManager; import com.palantir.atlasdb.util.MetricsManagers; import com.palantir.flake.FlakeRetryTest; import com.palantir.leader.NotCurrentLeaderException; @@ -62,12 +64,11 @@ public class AsyncLockServiceEteTest { private final LockLog lockLog = new LockLog(new MetricRegistry(), () -> 2L); private final HeldLocksCollection heldLocks = HeldLocksCollection.create(clock); - private final LockWatchingService lockWatchingService = new LockWatchingServiceImpl( - heldLocks, - clock.id(), - BufferMetrics.of(MetricsManagers.createForTests().getTaggedRegistry())); + private final MetricsManager metricsManager = MetricsManagers.createForTests(); + private final LockWatchingService lockWatchingService = + new LockWatchingServiceImpl(heldLocks, clock.id(), BufferMetrics.of(metricsManager.getTaggedRegistry())); private final AsyncLockService service = new AsyncLockService( - new LockManager(), + LockManager.create(TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())), new LockAcquirer( new LockLog(new MetricRegistry(), () -> 2L), Executors.newSingleThreadScheduledExecutor(), diff --git a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java index 9bf50d06b2a..7c1f8b362e7 100644 --- a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java +++ b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java @@ -18,8 +18,10 @@ import static org.assertj.core.api.Assertions.assertThat; import com.google.common.collect.ImmutableSet; +import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics; import com.palantir.lock.LockDescriptor; import com.palantir.lock.StringLockDescriptor; +import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -30,7 +32,8 @@ public class LockCollectionTest { - private final LockManager lockManager = new LockManager(); + private final LockManager lockManager = + LockManager.create(TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); @Test public void createsLocksOnDemand() { 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..263bad871ac 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,29 @@ 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.TimestampLeaseMetrics; +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; @@ -42,6 +56,7 @@ import com.palantir.timestamp.TimestampManagementRpcClient; import com.palantir.timestamp.TimestampManagementService; import com.palantir.timestamp.TimestampRange; +import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry; import java.util.Set; import org.immutables.value.Value; @@ -71,11 +86,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, TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry())); + + MinLeasedTimestampGetter minLeasedTimestampGetter = new MinLeasedTimestampGetterImpl(timestampLeaseService); + return RemoteTimelockServiceAdapter.create( Namespace.of(namespace()), namespacedTimelockRpcClient(), namespacedConjureTimelockService(), - lockWatchEventCache()); + lockWatchEventCache(), + lockLeaseService, + timestampLeaseAcquirer, + minLeasedTimestampGetter); } @Value.Default @@ -120,6 +153,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(); }