use of com.couchbase.connector.config.ConfigException in project couchbase-elasticsearch-connector by couchbase.
the class PauseCommand method consulBuilder.
protected Consul.Builder consulBuilder() {
try {
if (consulConfig == null) {
System.out.println("Consul config file not specified; will not override Consul agent ACL token.");
}
final ConsulConfig config = consulConfig == null ? null : ConsulConfig.from(consulConfig);
Consul.Builder builder = Consul.builder().withHostAndPort(HostAndPort.fromString(consulAgentAddress));
if (config != null && !config.aclToken().isEmpty()) {
System.out.println("Using Consul ACL token from " + consulConfig);
builder.withAclToken(config.aclToken());
}
return builder;
} catch (IOException e) {
throw new ConfigException(e.getMessage());
}
}
use of com.couchbase.connector.config.ConfigException in project couchbase-elasticsearch-connector by couchbase.
the class LeaderTask method rebalance.
private void rebalance() throws InterruptedException {
final String configLocation = ctx.keys().config();
LOGGER.info("Reading connector config from Consul key: {}", configLocation);
final String config = ctx.consul().keyValueClient().getValue(configLocation).orElseThrow(() -> new ConfigException("missing Consul config key: " + configLocation)).getValueAsString(UTF_8).orElseThrow(() -> new ConfigException("missing value for Consul key: " + configLocation));
// Sanity check, validate the config.
ConnectorConfig.from(config);
restartRebalance: while (true) {
LOGGER.info("Rebalancing the cluster");
// dumb strategy: shut everything down, then reassign vbuckets
stopStreaming();
final List<RpcEndpoint> endpoints = awaitReadyEndpoints();
for (int i = 0; i < endpoints.size(); i++) {
throwIfDone();
final int memberNumber = i + 1;
final int clusterSize = endpoints.size();
final Membership membership = Membership.of(memberNumber, clusterSize);
final RpcEndpoint endpoint = endpoints.get(i);
LOGGER.info("Assigning group membership {} to endpoint {}", membership, endpoint);
try {
endpoint.service(WorkerService.class).startStreaming(membership, config);
} catch (Throwable t) {
// todo what happens here? What if it fails due to timeout, and the worker is actually doing the work?
// For now, start the whole rebalance process over again. This is obviously not ideal.
LOGGER.warn("Failed to assign group membership {} to endpoint {}", membership, endpoint, t);
SECONDS.sleep(3);
continue restartRebalance;
}
}
// success!
return;
}
}
use of com.couchbase.connector.config.ConfigException in project couchbase-elasticsearch-connector by couchbase.
the class CouchbaseHelper method applyCustomEnvironmentProperties.
private static void applyCustomEnvironmentProperties(ClusterEnvironment.Builder envBuilder, CouchbaseConfig config) {
// Begin workaround for IoEnvironment config.
// Prior to Java client 3.1.5, IoEnvironment isn't configurable
// via system properties. Until then, handle it manually.
Map<String, String> envProps = new HashMap<>(config.env());
IoEnvironment.Builder ioEnvBuilder = IoEnvironment.builder();
String nativeIoEnabled = envProps.remove("ioEnvironment.enableNativeIo");
if (nativeIoEnabled != null) {
ioEnvBuilder.enableNativeIo(Boolean.parseBoolean(nativeIoEnabled));
}
String eventLoopThreadCount = envProps.remove("ioEnvironment.eventLoopThreadCount");
if (eventLoopThreadCount != null) {
ioEnvBuilder.eventLoopThreadCount(Integer.parseInt(eventLoopThreadCount));
}
envBuilder.ioEnvironment(ioEnvBuilder);
try {
envBuilder.load(new AbstractMapPropertyLoader<CoreEnvironment.Builder>() {
@Override
protected Map<String, String> propertyMap() {
return envProps;
}
});
} catch (Exception e) {
throw new ConfigException("Failed to apply Couchbase environment properties; " + e.getMessage());
}
}
use of com.couchbase.connector.config.ConfigException in project couchbase-elasticsearch-connector by couchbase.
the class TypeConfig method from.
static ImmutableTypeConfig from(ConfigTable config, ConfigPosition position, TypeConfig defaults) {
config.expectOnly("typeName", "index", "pipeline", "routing", "ignore", "ignoreDeletes", "prefix", "regex", "matchOnQualifiedKey");
final String index = Strings.emptyToNull(config.getString("index").orElseGet(defaults::index));
final String routing = Strings.emptyToNull(config.getString("routing").orElse(null));
final boolean qualifiedKey = config.getBoolean("matchOnQualifiedKey").orElseGet(defaults::matchOnQualifiedKey);
ImmutableTypeConfig.Builder builder = ImmutableTypeConfig.builder().position(position).type(config.getString("typeName").orElseGet(defaults::type)).index(index).matchOnQualifiedKey(qualifiedKey).routing(parseRouting(routing, config.inputPositionOf("routing"))).pipeline(Strings.emptyToNull(config.getString("pipeline").orElseGet(defaults::pipeline))).ignoreDeletes(config.getBoolean("ignoreDeletes").orElseGet(defaults::ignoreDeletes)).ignore(config.getBoolean("ignore").orElseGet(defaults::ignore));
final String idPrefix = config.getString("prefix").orElse(null);
final String idRegex = config.getString("regex").orElse(null);
if (idPrefix != null && idRegex != null) {
throw new ConfigException("Type at " + position + " can have 'prefix' or 'regex', but not both.");
}
if (idPrefix == null && idRegex == null) {
throw new ConfigException("Type at " + position + " must have 'prefix' or 'regex'.");
}
if (idPrefix != null) {
builder.matcher(new IdPrefixMatcher(index, idPrefix, qualifiedKey));
} else {
try {
if (idRegex.contains("(?<index>")) {
if (config.getString("index").isPresent()) {
throw new ConfigException("Type at " + position + " must not have 'index' because it's inferred from named capturing group in 'regex'.");
}
builder.matcher(new IdRegexInferredIndexMatcher(idRegex, qualifiedKey));
} else {
builder.matcher(new IdRegexMatcher(index, idRegex, qualifiedKey));
}
} catch (PatternSyntaxException e) {
throw new ConfigException("Invalid regex '" + idRegex + "' at " + config.inputPositionOf("regex") + " -- " + e.getMessage());
}
}
final ImmutableTypeConfig type = builder.build();
if (type.routing() != null && !type.ignoreDeletes()) {
throw new ConfigException("Custom 'routing' requires 'ignoreDeletes = true' for type at " + position + "." + " (Due to limitations in the current implementation, routing information is not available to the connector" + " when documents are deleted, so it's not possible to route the deletion request to the correct Elasticsearch shard.)");
}
return type;
}
use of com.couchbase.connector.config.ConfigException in project couchbase-elasticsearch-connector by couchbase.
the class GroupConfig method from.
static ImmutableGroupConfig from(ConfigTable config) {
config.expectOnly("name", "static");
final ConfigTable staticGroup = config.getTableOrEmpty("static");
staticGroup.expectOnly("memberNumber", "totalMembers");
final int totalMembers = staticGroup.getIntInRange("totalMembers", 1, 1024).orElseThrow((() -> new ConfigException("missing 'static.totalMembers' property")));
final int memberNumber = staticGroup.getInt("memberNumber").orElseThrow(() -> new ConfigException("missing 'static.memberNumber' property"));
try {
return ImmutableGroupConfig.builder().name(config.getString("name").orElseThrow(() -> new ConfigException("missing 'name' property"))).staticMembership(Membership.of(memberNumber, totalMembers)).build();
} catch (IllegalArgumentException e) {
throw new ConfigException(e.getMessage());
}
}
Aggregations