Skip to content
This repository has been archived by the owner on Nov 14, 2024. It is now read-only.

Commit

Permalink
Live Reloading the TimeLock Block, Part 2: TransactionManagers Plumbi…
Browse files Browse the repository at this point in the history
…ng (#2622)

* ServiceCreator.applyDynamic()

* Propagate config through TMs

* Json Serialization fixes

* Some refactoring

* lock/lock

* Fixed checkstyle

* CR comments part 1

* Switch to RPIH

* add test

* [no release notes] forthcoming in part 4

* checkstyle
  • Loading branch information
jeremyk-91 authored Nov 10, 2017
1 parent 18d35b6 commit a953328
Show file tree
Hide file tree
Showing 36 changed files with 628 additions and 130 deletions.
6 changes: 4 additions & 2 deletions atlasdb-cli-distribution/versions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,8 @@
"com.palantir.remoting-api:service-config": {
"locked": "1.4.0",
"transitive": [
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"com.palantir.remoting-api:ssl-config": {
Expand Down Expand Up @@ -847,7 +848,8 @@
"locked": "1.1.0.Final",
"transitive": [
"com.palantir.atlasdb:atlasdb-api",
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"javax.ws.rs:javax.ws.rs-api": {
Expand Down
12 changes: 8 additions & 4 deletions atlasdb-cli/versions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@
"com.palantir.remoting-api:service-config": {
"locked": "1.4.0",
"transitive": [
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"com.palantir.remoting-api:ssl-config": {
Expand Down Expand Up @@ -748,7 +749,8 @@
"locked": "1.1.0.Final",
"transitive": [
"com.palantir.atlasdb:atlasdb-api",
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"javax.ws.rs:javax.ws.rs-api": {
Expand Down Expand Up @@ -1374,7 +1376,8 @@
"com.palantir.remoting-api:service-config": {
"locked": "1.4.0",
"transitive": [
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"com.palantir.remoting-api:ssl-config": {
Expand Down Expand Up @@ -1636,7 +1639,8 @@
"locked": "1.1.0.Final",
"transitive": [
"com.palantir.atlasdb:atlasdb-api",
"com.palantir.atlasdb:atlasdb-config"
"com.palantir.atlasdb:atlasdb-config",
"com.palantir.atlasdb:atlasdb-feign"
]
},
"javax.ws.rs:javax.ws.rs-api": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.palantir.atlasdb.config;

import java.util.Optional;

import org.immutables.value.Value;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
Expand Down Expand Up @@ -58,6 +60,14 @@ public long getTimestampCacheSize() {
return AtlasDbConstants.DEFAULT_TIMESTAMP_CACHE_SIZE;
}

/**
* Runtime live-reloadable parameters for communicating with TimeLock.
*
* This value is ignored if the install config does not specify usage of TimeLock.
* We do not currently support live reloading from a leader block or using embedded services to using TimeLock.
*/
public abstract Optional<TimeLockRuntimeConfig> timelockRuntime();

public static ImmutableAtlasDbRuntimeConfig defaultRuntimeConfig() {
return ImmutableAtlasDbRuntimeConfig.builder().build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the BSD-3 License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/BSD-3-Clause
*
* 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.atlasdb.config;

import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public final class ServerListConfigs {
private ServerListConfigs() {
// utilities
}

public static ServerListConfig parseInstallAndRuntimeConfigs(TimeLockClientConfig installClientConfig,
Supplier<Optional<TimeLockRuntimeConfig>> runtimeConfig,
String namespace) {
ServerListConfig nonNamespacedConfig = runtimeConfig.get()
.map(TimeLockRuntimeConfig::serversList)
.orElse(installClientConfig.serversList());
return namespaceUris(nonNamespacedConfig, namespace);
}

public static ServerListConfig namespaceUris(ServerListConfig config, String namespace) {
Set<String> serversWithNamespaces = config
.servers()
.stream()
.map(serverAddress -> serverAddress.replaceAll("/$", "") + "/" + namespace)
.collect(Collectors.toSet());
return ImmutableServerListConfig.builder()
.from(config)
.servers(serversWithNamespaces)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
package com.palantir.atlasdb.config;

import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.immutables.value.Value;

Expand Down Expand Up @@ -45,16 +43,15 @@ public String getClientOrThrow() {
"Tried to read a client from a TimeLockClientConfig, but it hadn't been initialised."));
}

/**
* @deprecated Please use {@link TimeLockRuntimeConfig} to specify the {@link ServerListConfig} to be used
* for connecting to TimeLock.
*/
@Deprecated
public abstract ServerListConfig serversList();

public ServerListConfig toNamespacedServerList() {
Set<String> serversWithNamespaces = serversList()
.servers()
.stream()
.map(serverAddress -> serverAddress.replaceAll("/$", "") + "/" + getClientOrThrow())
.collect(Collectors.toSet());
return ImmutableServerListConfig.copyOf(serversList())
.withServers(serversWithNamespaces);
return ServerListConfigs.namespaceUris(serversList(), getClientOrThrow());
}

@Value.Check
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the BSD-3 License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/BSD-3-Clause
*
* 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.atlasdb.config;

import org.immutables.value.Value;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonSerialize(as = ImmutableTimeLockRuntimeConfig.class)
@JsonDeserialize(as = ImmutableTimeLockRuntimeConfig.class)
@Value.Immutable
public abstract class TimeLockRuntimeConfig {
public abstract ServerListConfig serversList();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import java.net.URI;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;

import javax.net.ssl.SSLSocketFactory;

Expand All @@ -49,9 +49,18 @@ public ServiceCreator(Class<T> serviceClass, String userAgent) {

@Override
public T apply(ServerListConfig input) {
Optional<SSLSocketFactory> sslSocketFactory = createSslSocketFactory(input.sslConfiguration());
Optional<ProxySelector> proxySelector = input.proxyConfiguration().map(ServiceCreator::createProxySelector);
return createService(sslSocketFactory, proxySelector, input.servers(), serviceClass, userAgent);
return applyDynamic(() -> input);
}

// Semi-horrible, but given that we create ServiceCreators explicitly and I'd rather not API break our
// implementation of Function, leaving this here for now.
public T applyDynamic(Supplier<ServerListConfig> input) {
return createService(
input,
SslSocketFactories::createSslSocketFactory,
ServiceCreator::createProxySelector,
serviceClass,
userAgent);
}

/**
Expand All @@ -62,13 +71,13 @@ public static Optional<SSLSocketFactory> createSslSocketFactory(Optional<SslConf
}

private static <T> T createService(
Optional<SSLSocketFactory> sslSocketFactory,
Optional<ProxySelector> proxySelector,
Set<String> uris,
Class<T> serviceClass,
Supplier<ServerListConfig> serverListConfigSupplier,
java.util.function.Function<SslConfiguration, SSLSocketFactory> sslSocketFactoryCreator,
java.util.function.Function<ProxyConfiguration, ProxySelector> proxySelectorCreator,
Class<T> type,
String userAgent) {
return AtlasDbHttpClients.createProxyWithFailover(
sslSocketFactory, proxySelector, uris, serviceClass, userAgent);
return AtlasDbHttpClients.createLiveReloadingProxyWithFailover(
serverListConfigSupplier, sslSocketFactoryCreator, proxySelectorCreator, type, userAgent);
}

public static <T> T createInstrumentedService(T service, Class<T> serviceClass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@
import com.palantir.atlasdb.config.AtlasDbConfig;
import com.palantir.atlasdb.config.AtlasDbRuntimeConfig;
import com.palantir.atlasdb.config.ImmutableAtlasDbConfig;
import com.palantir.atlasdb.config.ImmutableAtlasDbRuntimeConfig;
import com.palantir.atlasdb.config.ImmutableServerListConfig;
import com.palantir.atlasdb.config.LeaderConfig;
import com.palantir.atlasdb.config.ServerListConfig;
import com.palantir.atlasdb.config.ServerListConfigs;
import com.palantir.atlasdb.config.SweepConfig;
import com.palantir.atlasdb.config.TimeLockClientConfig;
import com.palantir.atlasdb.config.TimeLockClientConfigs;
import com.palantir.atlasdb.config.TimestampClientConfig;
import com.palantir.atlasdb.factory.Leaders.LocalPaxosServices;
import com.palantir.atlasdb.factory.startup.TimeLockMigrator;
Expand Down Expand Up @@ -313,7 +314,7 @@ SerializableTransactionManager serializable() {
SimpleTimeDuration.of(config.getDefaultLockTimeoutSeconds(), TimeUnit.SECONDS));
LockAndTimestampServices lockAndTimestampServices = createLockAndTimestampServices(
config,
() -> runtimeConfigSupplier.get().timestampClient(),
runtimeConfigSupplier,
registrar(),
() -> LockServiceImpl.create(lockServerOptions()),
atlasFactory::getTimestampService,
Expand Down Expand Up @@ -521,6 +522,7 @@ public static LockAndTimestampServices createLockAndTimestampServices(
com.google.common.base.Supplier<TimestampService> time) {
LockAndTimestampServices lockAndTimestampServices =
createRawInstrumentedServices(config,
() -> ImmutableAtlasDbRuntimeConfig.builder().build(),
env,
lock,
time,
Expand All @@ -535,16 +537,16 @@ public static LockAndTimestampServices createLockAndTimestampServices(
@VisibleForTesting
static LockAndTimestampServices createLockAndTimestampServices(
AtlasDbConfig config,
java.util.function.Supplier<TimestampClientConfig> runtimeConfigSupplier,
java.util.function.Supplier<AtlasDbRuntimeConfig> runtimeConfigSupplier,
Consumer<Object> env,
com.google.common.base.Supplier<LockService> lock,
com.google.common.base.Supplier<TimestampService> time,
TimestampStoreInvalidator invalidator,
String userAgent) {
LockAndTimestampServices lockAndTimestampServices =
createRawInstrumentedServices(config, env, lock, time, invalidator, userAgent);
createRawInstrumentedServices(config, runtimeConfigSupplier, env, lock, time, invalidator, userAgent);
return withRequestBatchingTimestampService(
runtimeConfigSupplier,
() -> runtimeConfigSupplier.get().timestampClient(),
withRefreshingLockService(lockAndTimestampServices));
}

Expand Down Expand Up @@ -575,6 +577,7 @@ private static LockAndTimestampServices withRequestBatchingTimestampService(
@VisibleForTesting
static LockAndTimestampServices createRawInstrumentedServices(
AtlasDbConfig config,
Supplier<AtlasDbRuntimeConfig> runtimeConfigSupplier,
Consumer<Object> env,
com.google.common.base.Supplier<LockService> lock,
com.google.common.base.Supplier<TimestampService> time,
Expand All @@ -585,44 +588,47 @@ static LockAndTimestampServices createRawInstrumentedServices(
} else if (config.timestamp().isPresent() && config.lock().isPresent()) {
return createRawRemoteServices(config, userAgent);
} else if (config.timelock().isPresent()) {
return createRawServicesFromTimeLock(config, invalidator, userAgent);
return createRawServicesFromTimeLock(config, runtimeConfigSupplier, invalidator, userAgent);
} else {
return createRawEmbeddedServices(env, lock, time);
}
}

private static LockAndTimestampServices createRawServicesFromTimeLock(
AtlasDbConfig config,
Supplier<AtlasDbRuntimeConfig> runtimeConfigSupplier,
TimestampStoreInvalidator invalidator,
String userAgent) {
Preconditions.checkState(config.timelock().isPresent(),
"Cannot create raw services from timelock without a timelock block!");
TimeLockClientConfig clientConfig = config.timelock().get();
String resolvedClient = OptionalResolver.resolve(clientConfig.client(), config.namespace());
TimeLockClientConfig timeLockClientConfig =
TimeLockClientConfigs.copyWithClient(config.timelock().get(), resolvedClient);
Supplier<ServerListConfig> serverListConfigSupplier =
getServerListConfigSupplierForTimeLock(config, runtimeConfigSupplier);
TimeLockMigrator migrator =
TimeLockMigrator.create(timeLockClientConfig, invalidator, userAgent, config.initializeAsync());
TimeLockMigrator.create(serverListConfigSupplier, invalidator, userAgent, config.initializeAsync());
migrator.migrate(); // This can proceed async if config.initializeAsync() was set
return ImmutableLockAndTimestampServices.copyOf(
createNamespacedRawRemoteServices(timeLockClientConfig, userAgent))
getLockAndTimestampServices(serverListConfigSupplier, userAgent))
.withMigrator(migrator);
}

private static LockAndTimestampServices createNamespacedRawRemoteServices(
TimeLockClientConfig config,
String userAgent) {
ServerListConfig namespacedServerListConfig = config.toNamespacedServerList();
return getLockAndTimestampServices(namespacedServerListConfig, userAgent);
private static Supplier<ServerListConfig> getServerListConfigSupplierForTimeLock(
AtlasDbConfig config,
Supplier<AtlasDbRuntimeConfig> runtimeConfigSupplier) {
Preconditions.checkState(config.timelock().isPresent(),
"Cannot create raw services from timelock without a timelock block!");
TimeLockClientConfig clientConfig = config.timelock().get();
String resolvedClient = OptionalResolver.resolve(clientConfig.client(), config.namespace());
return () -> ServerListConfigs.parseInstallAndRuntimeConfigs(
clientConfig,
() -> runtimeConfigSupplier.get().timelockRuntime(),
resolvedClient);
}

private static LockAndTimestampServices getLockAndTimestampServices(
ServerListConfig timelockServerListConfig,
Supplier<ServerListConfig> timelockServerListConfig,
String userAgent) {
LockService lockService = new ServiceCreator<>(LockService.class, userAgent)
.apply(timelockServerListConfig);
.applyDynamic(timelockServerListConfig);
TimelockService timelockService = new ServiceCreator<>(TimelockService.class, userAgent)
.apply(timelockServerListConfig);
.applyDynamic(timelockServerListConfig);

return ImmutableLockAndTimestampServices.builder()
.lock(lockService)
Expand Down
Loading

0 comments on commit a953328

Please sign in to comment.