blob: f595fb1a9b4c56c1d50626cb5aa8608eb88c57d6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.cassandra.sidecar.client;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.cassandra.sidecar.client.request.CassandraHealthRequest;
import org.apache.cassandra.sidecar.client.request.CleanSSTableUploadSessionRequest;
import org.apache.cassandra.sidecar.client.request.ClearSnapshotRequest;
import org.apache.cassandra.sidecar.client.request.CreateSnapshotRequest;
import org.apache.cassandra.sidecar.client.request.GossipInfoRequest;
import org.apache.cassandra.sidecar.client.request.ImportSSTableRequest;
import org.apache.cassandra.sidecar.client.request.ListSnapshotFilesRequest;
import org.apache.cassandra.sidecar.client.request.NodeSettingsRequest;
import org.apache.cassandra.sidecar.client.request.Request;
import org.apache.cassandra.sidecar.client.request.RingRequest;
import org.apache.cassandra.sidecar.client.request.SSTableComponentRequest;
import org.apache.cassandra.sidecar.client.request.SchemaRequest;
import org.apache.cassandra.sidecar.client.request.SidecarHealthRequest;
import org.apache.cassandra.sidecar.client.request.TimeSkewRequest;
import org.apache.cassandra.sidecar.client.request.TokenRangeReplicasRequest;
import org.apache.cassandra.sidecar.client.request.UploadSSTableRequest;
import org.apache.cassandra.sidecar.client.retry.ExponentialBackoffRetryPolicy;
import org.apache.cassandra.sidecar.client.retry.NoRetryPolicy;
import org.apache.cassandra.sidecar.client.retry.RetryPolicy;
import org.apache.cassandra.sidecar.client.selection.InstanceSelectionPolicy;
import org.apache.cassandra.sidecar.client.selection.SingleInstanceSelectionPolicy;
import org.apache.cassandra.sidecar.common.utils.HttpRange;
/**
* The context for a given request that include the {@link InstanceSelectionPolicy}, the {@link RetryPolicy}, and
* the {@link Request}
*/
public class RequestContext
{
protected static final SidecarHealthRequest SIDECAR_HEALTH_REQUEST = new SidecarHealthRequest();
protected static final CassandraHealthRequest CASSANDRA_HEALTH_REQUEST = new CassandraHealthRequest();
protected static final SchemaRequest FULL_SCHEMA_REQUEST = new SchemaRequest();
protected static final TimeSkewRequest TIME_SKEW_REQUEST = new TimeSkewRequest();
protected static final NodeSettingsRequest NODE_SETTINGS_REQUEST = new NodeSettingsRequest();
protected static final RingRequest RING_REQUEST = new RingRequest();
protected static final GossipInfoRequest GOSSIP_INFO_REQUEST = new GossipInfoRequest();
protected static final RetryPolicy DEFAULT_RETRY_POLICY = new NoRetryPolicy();
protected static final RetryPolicy DEFAULT_EXPONENTIAL_BACKOFF_RETRY_POLICY =
new ExponentialBackoffRetryPolicy(10, 500L, 60_000L);
private final InstanceSelectionPolicy instanceSelectionPolicy;
private final Request request;
private final RetryPolicy retryPolicy;
private final Map<String, String> customHeaders;
private RequestContext(Builder builder)
{
instanceSelectionPolicy = builder.instanceSelectionPolicy;
request = builder.request;
retryPolicy = builder.retryPolicy;
customHeaders = Collections.unmodifiableMap(builder.customHeaders);
}
/**
* @return the instance selection policy for the request
*/
public InstanceSelectionPolicy instanceSelectionPolicy()
{
return instanceSelectionPolicy;
}
/**
* @return the retry policy associated to the request
*/
public RetryPolicy retryPolicy()
{
return retryPolicy;
}
/**
* @return the request for the Sidecar service
*/
public Request request()
{
return request;
}
/**
* @return the custom headers for the request
*/
public Map<String, String> customHeaders()
{
return customHeaders;
}
/**
* {@code RequestContext} builder static inner class.
*/
public static final class Builder
{
private InstanceSelectionPolicy instanceSelectionPolicy;
private Request request;
private RetryPolicy retryPolicy = DEFAULT_RETRY_POLICY;
private final Map<String, String> customHeaders;
public Builder()
{
customHeaders = new HashMap<>();
}
private Builder(Builder builder)
{
request = builder.request;
instanceSelectionPolicy = builder.instanceSelectionPolicy;
retryPolicy = builder.retryPolicy;
customHeaders = new HashMap<>(builder.customHeaders);
}
/**
* Sets the {@code instanceSelectionPolicy} and returns a reference to this Builder enabling method chaining.
*
* @param instanceSelectionPolicy the {@code instanceSelectionPolicy} to set
* @return a reference to this Builder
*/
public Builder instanceSelectionPolicy(InstanceSelectionPolicy instanceSelectionPolicy)
{
this.instanceSelectionPolicy = instanceSelectionPolicy;
return this;
}
/**
* Sets the {@code instanceSelectionPolicy} to the {@link SingleInstanceSelectionPolicy} for the provided
* {@code sidecarInstance} and returns a reference to this Builder enabling method chaining.
*
* @param sidecarInstance the Sidecar instance where the request will be performed
* @return a reference to this Builder
*/
public Builder singleInstanceSelectionPolicy(SidecarInstance sidecarInstance)
{
return instanceSelectionPolicy(new SingleInstanceSelectionPolicy(sidecarInstance));
}
/**
* Sets the {@code request} and returns a reference to this Builder enabling method chaining.
*
* @param request the {@code request} to set
* @return a reference to this Builder
*/
public Builder request(Request request)
{
this.request = request;
return this;
}
/**
* Sets the {@code retryPolicy} and returns a reference to this Builder enabling method chaining.
*
* @param retryPolicy the {@code retryPolicy} to set
* @return a reference to this Builder
*/
public Builder retryPolicy(RetryPolicy retryPolicy)
{
this.retryPolicy = retryPolicy;
return this;
}
/**
* Sets the {@code request} to be a {@link SidecarHealthRequest}
* and returns a reference to this Builder enabling method chaining
*
* @return a reference to this Builder
*/
public Builder sidecarHealthRequest()
{
return request(SIDECAR_HEALTH_REQUEST);
}
/**
* Sets the {@code request} to be a {@link CassandraHealthRequest}
* and returns a reference to this Builder enabling method chaining
*
* @return a reference to this Builder
*/
public Builder cassandraHealthRequest()
{
return request(CASSANDRA_HEALTH_REQUEST);
}
/**
* Sets the {@code request} to be a {@link SchemaRequest} for the full schema and returns a reference to
* this Builder enabling method chaining.
*
* @return a reference to this Builder
*/
public Builder schemaRequest()
{
return request(FULL_SCHEMA_REQUEST);
}
/**
* Sets the {@code request} to be a {@link SchemaRequest} for the specified {@code keyspace} and returns a
* reference to this Builder enabling method chaining
*
* @param keyspace the keyspace in Cassandra
* @return a reference to this Builder
*/
public Builder schemaRequest(String keyspace)
{
return request(new SchemaRequest(keyspace));
}
/**
* Sets the {@code request} to be a {@link TimeSkewRequest} and returns a reference to this Builder enabling
* method chaining.
*
* @return a reference to this Builder
*/
public Builder timeSkewRequest()
{
return request(TIME_SKEW_REQUEST);
}
/**
* Sets the {@code request} to be a {@link TokenRangeReplicasRequest} and returns a reference to this Builder
* enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @return a reference to this Builder
*/
public Builder tokenRangeReplicasRequest(String keyspace)
{
return request(new TokenRangeReplicasRequest(keyspace));
}
/**
* Sets the {@code request} to be a {@link NodeSettingsRequest} and returns a reference to this Builder
* enabling method chaining.
*
* @return a reference to this Builder
*/
public Builder nodeSettingsRequest()
{
return request(NODE_SETTINGS_REQUEST);
}
/**
* Sets the {@code request} to be a {@link RingRequest} and returns a reference to this Builder enabling
* method chaining.
*
* @return a reference to this Builder
*/
public Builder ringRequest()
{
return request(RING_REQUEST);
}
/**
* Sets the {@code request} to be a {@link RingRequest} for the given {@code keyspace} and returns a reference
* to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @return a reference to this Builder
*/
public Builder ringRequest(String keyspace)
{
return request(new RingRequest(keyspace));
}
/**
* Sets the {@code request} to be a {@link GossipInfoRequest} and returns a reference to this Builder enabling
* method chaining.
*
* @return a reference to this Builder
*/
public Builder gossipInfoRequest()
{
return request(GOSSIP_INFO_REQUEST);
}
/**
* Sets the {@code request} to be a {@link SSTableComponentRequest} for the given {@code keyspace},
* {@code tableName}, {@code snapshotName}, {@code componentName}, requesting the specified {@code range} and
* returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param snapshotName the name of the snapshot
* @param componentName the name of the SSTable component
* @param range the HTTP range for the request
* @return a reference to this Builder
*/
public Builder ssTableComponentRequest(String keyspace,
String tableName,
String snapshotName,
String componentName,
HttpRange range)
{
return request(new SSTableComponentRequest(keyspace, tableName, snapshotName, componentName, range));
}
/**
* Sets the {@code request} to be a {@link ListSnapshotFilesRequest} for the given {@code keyspace},
* {@code tableName}, and {@code snapshotName} and returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param snapshotName the name of the snapshot
* @return a reference to this Builder
*/
public Builder listSnapshotFilesRequest(String keyspace, String tableName, String snapshotName)
{
return listSnapshotFilesRequest(keyspace, tableName, snapshotName, false);
}
/**
* Sets the {@code request} to be a {@link CreateSnapshotRequest} for the given {@code keyspace},
* {@code tableName}, and {@code snapshotName} and returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param snapshotName the name of the snapshot
* @return a reference to this Builder
*/
public Builder createSnapshotRequest(String keyspace, String tableName, String snapshotName)
{
return request(new CreateSnapshotRequest(keyspace, tableName, snapshotName));
}
/**
* Sets the {@code request} to be a {@link ListSnapshotFilesRequest} for the given {@code keyspace},
* {@code tableName}, and {@code snapshotName} and returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param snapshotName the name of the snapshot
* @param includeSecondaryIndexFiles whether to include secondary index files
* @return a reference to this Builder
*/
public Builder listSnapshotFilesRequest(String keyspace, String tableName, String snapshotName,
boolean includeSecondaryIndexFiles)
{
return request(new ListSnapshotFilesRequest(keyspace, tableName, snapshotName, includeSecondaryIndexFiles));
}
/**
* Sets the {@code request} to be a {@link ClearSnapshotRequest} for the given {@code keyspace},
* {@code tableName}, and {@code snapshotName} and returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param snapshotName the name of the snapshot
* @return a reference to this Builder
*/
public Builder clearSnapshotRequest(String keyspace, String tableName, String snapshotName)
{
return request(new ClearSnapshotRequest(keyspace, tableName, snapshotName));
}
/**
* Sets the {@code request} to be a {@link CleanSSTableUploadSessionRequest} for the given {@code uploadId}
* and returns a reference to this Builder enabling method chaining.
*
* @param uploadId the unique identifier for the upload
* @return a reference to this Builder
*/
public Builder cleanSSTableUploadSessionRequest(String uploadId)
{
return request(new CleanSSTableUploadSessionRequest(uploadId));
}
/**
* Sets the {@code request} to be a {@link ImportSSTableRequest} for the given {@code keyspace},
* {@code tableName}, {@code uploadId}, and selected {@link ImportSSTableRequest.ImportOptions importOptions}
* and returns a reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param uploadId an identifier for the upload
* @param importOptions additional options for the import process
* @return a reference to this Builder
*/
public Builder importSSTableRequest(String keyspace, String tableName, String uploadId,
ImportSSTableRequest.ImportOptions importOptions)
{
return request(new ImportSSTableRequest(keyspace, tableName, uploadId, importOptions));
}
/**
* Sets the {@code} request to be a {@link UploadSSTableRequest} for the given {@code keyspace},
* {@code tableName}, {@code uploadId}, {@code component}, and returns a
* reference to this Builder enabling method chaining.
*
* @param keyspace the keyspace in Cassandra
* @param tableName the table name in Cassandra
* @param uploadId an identifier for the upload
* @param component SSTable component being uploaded
* @param checksum hash value to check integrity of SSTable component uploaded
* @param filename the path to the file to be uploaded
* @return a reference to this Builder
*/
public Builder uploadSSTableRequest(String keyspace, String tableName, String uploadId, String component,
String checksum, String filename)
{
return request(new UploadSSTableRequest(keyspace, tableName, uploadId, component, checksum, filename));
}
/**
* Sets the {@code retryPolicy} to be an
* {@link org.apache.cassandra.sidecar.client.retry.ExponentialBackoffRetryPolicy} configured with
* {@code 10} {@code maxRetries}, {@code 500} {@code retryDelayMillis}, and {@code 60,000}
* {@code maxRetryDelayMillis}; and returns a reference to this Builder enabling method chaining.
*
* @return a reference to this Builder
*/
public Builder exponentialBackoffRetryPolicy()
{
return retryPolicy(DEFAULT_EXPONENTIAL_BACKOFF_RETRY_POLICY);
}
/**
* Sets the {@code retryPolicy} to be an
* {@link org.apache.cassandra.sidecar.client.retry.ExponentialBackoffRetryPolicy} configured with the provided
* {@code maxRetries}, {@code retryDelayMillis}, and {@code maxRetryDelayMillis}; and returns a reference to
* this Builder enabling method chaining.
*
* @param maxRetries the maximum number of retries
* @param retryDelayMillis the delay between retries in milliseconds
* @param maxRetryDelayMillis the maximum retry delay in milliseconds
* @return a reference to this Builder
*/
public Builder exponentialBackoffRetryPolicy(int maxRetries, long retryDelayMillis, long maxRetryDelayMillis)
{
return retryPolicy(new ExponentialBackoffRetryPolicy(maxRetries, retryDelayMillis, maxRetryDelayMillis));
}
/**
* Adds a custom header for the request and returns a reference to this Builder enabling method chaining.
*
* @param name the header name
* @param value the header value
* @return a reference to this Builder
*/
public Builder addCustomHeader(String name, String value)
{
customHeaders.put(name, value);
return this;
}
/**
* @return a new Builder with references to the parameters previously set in this Builder
*/
public Builder copy()
{
return new Builder(this);
}
/**
* Returns a {@code RequestContext} built from the parameters previously set.
*
* @return a {@code RequestContext} built with parameters of this {@code RequestContext.Builder}
*/
public RequestContext build()
{
return new RequestContext(this);
}
}
}