Cassandra Persistor¶
The Cassandra persistor connects Quine to Cassandra and Cassandra compatible solutions like ScyllaDB, Astra DB, and Amazon Keyspaces.
Quine Configuration¶
To use Cassandra as the persistence backend for Quine, you’ll need to set the quine.store
section to type = cassandra
in the config.
quine.store {
# store data in an Apache Cassandra instance
type = cassandra
# "host:port" strings at which Cassandra nodes can be accessed from
# the application
endpoints = [
"localhost:9042"
]
# the keyspace to use
keyspace = quine
# whether the application should create the keyspace if it does not
# yet exist
should-create-keyspace = true
# whether the application should create tables in the keyspace if
# they do not yet exist
should-create-tables = true
# how many copies of each datum the Cassandra cluster should retain
replication-factor = 1
# how many hosts must agree on a datum for Quine to consider that
# datum written/read
write-consistency = LOCAL_QUORUM
read-consistency = LOCAL_QUORUM
# Which Cassandra cluster datacenter is considered local to this deployment of Quine (e.g. us-west-2)
local-datacenter = "datacenter1"
# how long to wait before considering a write operation failed
write-timeout = "10s"
# how long to wait before considering a read operation failed
read-timeout = "10s"
# if set, the number of nodes for which to optimize node creation
# latency
# bloom-filter-size =
}
Where endpoints
is a list of the address(es) of one or more Cassandra hosts in the cluster. If you need to specify a port other than 9042 (the default), you can use host:portNum
.
Alternatively, you may specify the environment variable CASSANDRA_ENDPOINTS
as a comma-separated list of hostnames, or host:ports, to be used if endpoints
is not set in the config file.
Cassandra Authentication¶
Quine communicates with Cassandra via the DataStax Java Driver for Apache Cassandra. You can configure authentication by adding datastax-java-driver
configuration to your local config file file as described on the driver's Authentication page.
For example, adding the following into a quine.conf
file will set up basic authentication.
quine.store {
type = cassandra
}
datastax-java-driver {
advanced {
auth-provider {
class = PlainTextAuthProvider
username = user
password = pass
}
}
}
Then launch Quine with the following command line:
java -Dconfig.file=quine.conf -jar quine.jar
Automatic Creation of Keyspace and Tables¶
Quine has settings in the Cassandra section of the config, should-create-keyspace
and should-create-tables
. When enabled, Quine automatically creates the keyspace and/or tables at startup if they don’t already exist.
Note
Auto creation of the keyspace and tables is included as a development convenience and should never be used in production.
Cassandra Schema¶
CREATE KEYSPACE quine WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'};
USE quine;
CREATE TABLE domain_graph_nodes (
dgn_id bigint PRIMARY KEY,
data blob
);
CREATE TABLE domain_index_events (
quine_id blob,
timestamp bigint,
data blob,
dgn_id bigint,
PRIMARY KEY (quine_id, timestamp)
) WITH CLUSTERING ORDER BY (timestamp ASC)
AND compaction = {'class': 'TimeWindowCompactionStrategy'};
CREATE TABLE journals (
quine_id blob,
timestamp bigint,
data blob,
PRIMARY KEY (quine_id, timestamp)
) WITH CLUSTERING ORDER BY (timestamp ASC)
AND compaction = {'class': 'TimeWindowCompactionStrategy'};
CREATE TABLE meta_data (
key text PRIMARY KEY,
value blob
);
CREATE TABLE snapshots (
quine_id blob,
timestamp bigint,
multipart_index int,
data blob,
multipart_count int,
PRIMARY KEY (quine_id, timestamp, multipart_index)
) WITH CLUSTERING ORDER BY (timestamp DESC, multipart_index ASC);
CREATE TABLE standing_queries (
query_id uuid PRIMARY KEY,
queries blob
);
CREATE TABLE standing_query_states (
quine_id blob,
standing_query_id uuid,
standing_query_part_id uuid,
data blob,
PRIMARY KEY (quine_id, standing_query_id, standing_query_part_id)
) WITH CLUSTERING ORDER BY (standing_query_id ASC, standing_query_part_id ASC);
AstraDB Configuration¶
Astra DB is a fully Cassandra compatible and serverless DbaaS that simplifies the development and deployment of high-growth applications.
It doesn't support setting compaction strategies other than UnifiedCompactionStrategy
, so you'll need to remove the AND compaction = {'class': 'TimeWindowCompactionStrategy'}
from the above schema.
It also requires setting a token from Astra DB, as well as the path to a secure connect bundle .zip file from them.
An example config for this is as follows:
quine.store {
# store data in Cassandra
type = cassandra
# the keyspace to use
keyspace = quine
should-create-keyspace = false
replication-factor = 3
local-datacenter = ${ASTRA_DB_REGION}
}
datastax-java-driver {
advanced {
auth-provider {
class = PlainTextAuthProvider
username = token
password = "${ASTRA_DB_APP_TOKEN}"
}
}
basic {
cloud {
secure-connect-bundle = "${SECURE-CONNECT-BUNDLE}.zip"
}
}
}
Astra DB Relevant Settings¶
type = cassandra
- Use the Cassandra persistor to connect to AstraDB
should-create-keyspace = false
- Keyspaces can only be created in Astra via the dashboard.
replication-factor = 3
- Defaults to 1 if not set.
write-consistency = LOCAL_QUORUM
- Minimum consistency level required by Astra.
read-consistency = LOCAL_QUORUM
- Any level is supported, though with replication-factor=3 and QUORUM writes, you'll want reads to be QUORUM as well if you want them to be immediately reflect writes.
local-datacenter = "us-east1"
- Set your Astra DB cloud region as the local DC.
username = "token"
- Leave it as the literal word "token."
password
- A valid token for an Astra DB cluster.
secure-connect-bundle
- A valid, local file location of a downloaded Astra secure connect bundle. The driver gets the Astra DB hostname from the secure bundle, so there is no need to specify endpoints separately.
Amazon Keyspaces Configuration¶
Keyspaces is a service provided by AWS that is mostly compatible with Cassandra. It has a higher latency for responding to queries, which translates into higher latencies for many Quine operations. Because it doesn't support everything Cassanrda does, and its configuration is a bit different, we have a different persistor type for it: keypaces
. At a minimum, setting quine.store.type = keyspaces
should be all you need to use it.
The rest of the config options are the same as that for Cassandra, with the following differences:
Removals¶
replication-factor
- Fixed to 3, not modifiable.
write-consistency
- Fixed to LOCAL_QUORUM
, not modifiable.
local-datacenter
- Set to the same value as the AWS region.
Additions¶
aws-region
- The AWS region to connect to Keyspaces in (e.g. "us-west-2". If unspecified, the region sourced from one of the mechanisms on the AWS SDK's DefaultAwsRegionProviderChain.
aws-role-arn
- The ARN of an IAM role to assume. It must have read / write access to the desired keyspace, as well as select
access to the system keyspaces system
, system_schema
, and system_schema_mcs
.
AWS credentials are required, which should provided in the environment using one of the mechanisms on https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials-chain.html
The full default config for Keyspaces is as follows:
quine.store {
# store data in Cassandra
type = keyspaces
# the keyspace to use
keyspace = quine
# If unspecified, sourced from one of the mechanisms on https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/regions/providers/DefaultAwsRegionProviderChain.html.
# aws-region =
# The ARN of an IAM role to assume. It must have read / write access to the desired keyspace, as well as `select` access to the system keyspaces `system`, `system_schema`, and `system_schema_mcs`.
# aws-role-arn =
# whether the application should create the keyspace if it does not
# yet exist
should-create-keyspace = true
# whether the application should create tables in the keyspace if
# they do not yet exist
should-create-tables = true
read-consistency = LOCAL_QUORUM
# how long to wait before considering a write operation failed
write-timeout = "10s"
# how long to wait before considering a read operation failed
read-timeout = "10s"
# if set, the number of nodes for which to optimize node creation
# latency
# bloom-filter-size =
}