Giter VIP home page Giter VIP logo

cqlmigrate's Introduction

Build Status

Cassandra CQL migration tool

cqlmigrate is a library for performing schema migrations on a cassandra cluster including:

It is best used as an application dependency, but can also be used standalone.

Adding as a Gradle dependency

repositories {
    mavenCentral()
}

compile 'uk.sky:cqlmigrate:0.13.0'

Adding as a Maven dependency

<dependency>
  <groupId>uk.sky</groupId>
  <artifactId>cqlmigrate</artifactId>
  <version>0.13.0</version>
</dependency>

Cassandra Prerequisites

The locks keyspace and table needs to be created before running any migrations.

CREATE KEYSPACE IF NOT EXISTS cqlmigrate WITH replication = {'class': 'REPLICATION_CLASS', 'replication_factor': REPLICATION_FACTOR };
CREATE TABLE IF NOT EXISTS cqlmigrate.locks (name text PRIMARY KEY, client text);

Library usage

To apply all .cql files located in /cql in the classpath:

import com.datastax.oss.driver.api.core.*;

// Configure locking for coordination of multiple nodes
CassandraLockConfig lockConfig = CassandraLockConfig.builder()
        .withTimeout(Duration.ofSeconds(3))
        .withPollingInterval(Duration.ofMillis(500))
        .withConsistencyLevel(ConsistencyLevel.ALL)
        .withLockKeyspace("cqlmigrate")
        .build();

// Configure cql migrator
CqlMigratorConfig cqlMigratorConfig = CqlMigratorConfig.builder()
        .withLockConfig(lockConfig)
        .withReadConsistencyLevel(ConsistencyLevel.LOCAL_ONE)
        .withWriteConsistencyLevel(ConsistencyLevel.ALL)
        .withTableCheckerInitDelay(Duration.ofSeconds(5))
        .withTableCheckerTimeout(Duration.ofMinutes(1))
        .build()

// Create a Cassandra session for cassandra driver 4.x
CqlSession session = CqlSession.builder()
        .addContactPoints(cassandraHosts)
        .withLocalDatacenter("datacenter1")
        .withAuthProvider(new ProgrammaticPlainTextAuthProvider("username", "password"))
        .build();

// Create a migrator and run it
CqlMigrator migrator = CqlMigratorFactory.create(lockConfig);
Path schemas = Paths.get(ClassLoader.getSystemResource("/cql").toURI());
migrator.migrate(session, "my_keyspace", asList(schemas));

The migrator will look for a bootstrap.cql file for setting up the keyspace.

Standalone usage

$ java -Dhosts=localhost,192.168.1.1 -Dport=9042 -DlocalDC=DC1 -Dkeyspace=my_keyspace -Ddirectories=cql-common,cql-local -jar cqlmigrate.jar

Specify credentials, if required, using -Dusername=<username> and -Dpassword=<password>.

Specify optional properties, if required, using

  • -Dprecheck=<true/false> default false
  • -DtableCheckerTimeout=<duration> default PT1M (This was introduced for AWS Keyspaces as when new table is created it might take time to allocate resources and if additional changes or data are inserted while table is in CREATING state, it will fail. If cluster is no AWS Keyspaces it will not wait.)
  • -DtableCheckerInitDelay=<duration> default PT5S (Supplement previous option as it might take time AWs Keyspaces update their system so we need to wait before we check first time.)
  • -DreadCL default LOCAL_ONE
  • -DwriteCL default ALL

What it does

  1. Checks all nodes are up and their schemas are in agreement.

  2. Tries to acquire a lock for the keyspace. If it can't initially be acquired it will continue to retry at a set polling time until the timeout is reached.

  3. Looks for a bootstrap.cql file and runs it first. This file should contain the keyspace definition:

    CREATE KEYSPACE my_keyspace
     WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1 };
    
  4. Applies .cql files one by one, sorted by filename in ascending order. It is suggested to prefix the files with a datetime to order them:

    /cql/2015-05-02-19:20-create-airplanes-table.cql
    /cql/2015-05-03-14:19-add-manufacturer-column.cql
    

    Any previously applied files will be skipped. For AWS Keyspaces, it will wait after each successfully applied file for tables to get into ACTIVE state for initial and maximum duration.

  5. Releases the lock.

schema_updates table

This table is used to determine what has been previously applied.

SELECT * FROM schema_updates;

 filename                         | applied_on               | checksum
----------------------------------+--------------------------+------------------------------------------
           0001-create-tables.cql | 2015-04-08 12:10:04+0100 | ec19dfac7ede62b2a40c0f39706b237cd5c30da6
                 0002-dataset.cql | 2015-04-08 12:10:04+0100 | 4fa2d6c4fae9950f0c9140ae2eb57fe689192b4a
            0003-initial-date.cql | 2015-04-08 12:10:04+0100 | 19d0c9522b6464a06b18192c6e04233f83e78a84

(3 rows)

It also maintains a checksum to ensure the script hasn't changed since it was last applied.

locks keyspace and table

The locks keyspace replication class and factor can be configured using the LocksConfig. This table is used to keep track of what locks are currently in place, and relies on Cassandra's lightweight transactions.

SELECT * FROM locks;

 name                                | client
-------------------------------------+--------------------------------------
 airplanes_keyspace.schema_migration | 2a4ec2ae-d3d1-4b33-86a9-eb844e35eeeb

(1 rows)

Each lock will be deleted by cqlmigrate once the migration is complete.

Supported Cassandra versions

This project has been tested against the following versions:

  • DSE 5.1.18 (3.11.3)
  • Apache Cassandra 3.11.5
  • AWS Keyspaces

Caveats

Cassandra is an eventually consistent, AP database, and so applying schema updates are not as simple as a traditional relational database.

  • Certain schema changes can cause data corruption on cassandra. Be very careful changing a schema for a table that is being actively written to. Generally, adding columns is safe (but be careful with collection types). Test the migration before rolling out to production.

  • AP properties of Cassandra also apply to schema updates - so it is possible for a cluster to have an inconsistent schema across nodes in case of split brain or other situation. cqlmigrate tries to alleviate this with appropriate consistency levels.

Cql File Comments

There are a number of ways to add comments to your cql files.

For inline comments prepend -- to your comment, e.g:

-- Select Queries
SELECT * FROM schema_updates;

For multiline comments wrap them with /* and */, e.g:

/*
    Added by John Smith
    19th September 2017
*/
SELECT * FROM schema_updates;

Contributors

Originally developed by the Cirrus team at Sky.

  • Adam Dougal
  • James Booth
  • James Ravn
  • Adrian Ng
  • Malinda Rajapakse
  • Ashutosh Gawande
  • Dominic Mullings
  • Yoseph Sultan
  • David Sale
  • Supreeth Rao
  • Jose Taboada

cqlmigrate's People

Contributors

adamdougal avatar adrianmkng avatar baddapuri9 avatar balooo avatar bitsetd4d avatar chbatey avatar chuckydev avatar davidh87 avatar dogan-sky avatar howardburgess avatar jameskerrybarnard avatar janssk1 avatar joseblas avatar josh-jones-sky avatar jsravn avatar lw346 avatar marktickner avatar mkobit avatar oliverlockwood avatar rauligsky avatar razvanth avatar remusbaciu avatar sebduff avatar sethishi avatar ssserj avatar stevewink avatar supreethrao avatar tjuszczyk avatar totahuanocotl avatar zdenotubel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cqlmigrate's Issues

Trailing comments break parsing

If you have comments after the last CQL statements, you are presented with this lovely stacktrace.

java.lang.IllegalStateException: File had a non-terminated cql line
  at com.google.common.base.Preconditions.checkState(Preconditions.java:176)
  at uk.sky.cqlmigrate.CqlFileParser$LineProcessor.check(CqlFileParser.java:170)
  at uk.sky.cqlmigrate.CqlFileParser$LineProcessor.access$100(CqlFileParser.java:42)
  at uk.sky.cqlmigrate.CqlFileParser.getCqlStatementsFrom(CqlFileParser.java:37)

Allow user to specify CL for read/writes

When running CqlMigrate, allow the user to provide configuration to allow them to override the consistency levels for reads and writes to whatever they deem to be appropriate for their context. Currently the CL defaults are LOCAL_ONE and ALL for reads and writes respectively.

Enhancement: Encryption support for CQL files which may contain sensitive information

Use case: With authentication on cassandra and creating users for applications with relevant access on their keyspace. The CQL files may contains sensitive information such as the password for the user e.g.

// Change default user password
ALTER ROLE cassandra WITH PASSWORD='somePassDev'

CREATE ROLE someApp WITH PASSWORD = 'somePasswordForDev' AND LOGIN = true;
GRANT ALL ON KEYSPACE someAppKeyspace TO someApp;

Possible approach, allow for the password to be some cipher text and cqlmigrate is able to decrypt the cipher text given the key to the actual password at runtime and apply the CQL. It would be great useful feature for teams who also manage their own infra. Possible encryption library: Jasypt

Library does not release the lock if cluster is unhealthy

What happens:

Node acquires the lock
Starts SchemaLoader to do the migration
Schema loader checks cluster health which says "unhealthy"
Library throws an error and lock hangs there forever
Logs:

[2016-12-21 11:37:18,003] INFO  [main] u.s.c.Lock - [] Attempting to acquire lock for 'app.schema_migration', using client id '047b5b3c-ee9e-4059-b083-3a6bcd7e9259'
[2016-12-21 11:37:18,079] INFO  [main] u.s.c.CqlMigratorImpl - [] Loading cql files from [/tmp/cqlmigrate5345071027669587170]
[2016-12-21 11:37:18,093] INFO  [main] u.s.c.KeyspaceBootstrapper - [] Keyspace found, not applying bootstrap.cql
Exception in thread "main" uk.sky.cqlmigrate.exception.ClusterUnhealthyException: Cluster not healthy, the following hosts are down: [***]
        at uk.sky.cqlmigrate.ClusterHealth.check(ClusterHealth.java:28)
        at uk.sky.cqlmigrate.SessionContext.checkClusterHealth(SessionContext.java:35)
        at uk.sky.cqlmigrate.CqlLoader.load(CqlLoader.java:18)
        at uk.sky.cqlmigrate.SchemaLoader$Loader.apply(SchemaLoader.java:45)
        at uk.sky.cqlmigrate.CqlPaths.lambda$applyInSortedOrder$7(CqlPaths.java:49)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
        at java.util.Iterator.forEachRemaining(Iterator.java:116)
        at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
        at uk.sky.cqlmigrate.CqlPaths.applyInSortedOrder(CqlPaths.java:49)
        at uk.sky.cqlmigrate.SchemaLoader.load(SchemaLoader.java:28)
        at uk.sky.cqlmigrate.CqlMigratorImpl.migrate(CqlMigratorImpl.java:90)
        at uk.sky.cqlmigrate.initializer.CqlMigrateInitializer.migrate(CqlMigrateInitializer.java:80)
        at uk.sky.cqlmigrate.initializer.CqlMigrateBundle.cqlMigrate(CqlMigrateBundle.java:62)
        at uk.sky.cqlmigrate.initializer.CqlMigrateBundle.run(CqlMigrateBundle.java:39)
        at uk.sky.cqlmigrate.initializer.CqlMigrateBundle.run(CqlMigrateBundle.java:15)
        at io.dropwizard.setup.Bootstrap.run(Bootstrap.java:200)
        at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:42)
        at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:85)
        at io.dropwizard.cli.Cli.run(Cli.java:75)
        at io.dropwizard.Application.run(Application.java:79)
        at com.bskyb.App.main(App.java:54)
Registered app server agent with Node ID[9579] Component ID[1980] Application ID [68]

CQL migrate fails due to race condition of updating schema metadata after acquiring lock

When deploying to 2 nodes, the first gets the lock, runs migrate successfully, happy days.
The second then got the acquired the lock, skips the bootstrap but doesn't seem to have the updated schema metadata so it tries to apply the "create schema updates table".
This fails with an exception as it already exists.
[2017-01-06 11:58:09,563] lcm INFO [main] u.s.c.Lock - [] Attempting to acquire lock for 'channel_metadata.schema_migration', using client id '93155931-75b4-4fae-8be9-3dc51c111f4c' [2017-01-06 11:58:09,584] lcm INFO [main] u.s.c.CassandraLockingMechanism - [] Lock currently held by Row[false, channel_metadata.schema_migration, 948f2e5f-8447-4093-bd7f-cf32be7289f1] [2017-01-06 11:58:10,095] lcm INFO [main] u.s.c.CassandraLockingMechanism - [] Lock currently held by Row[false, channel_metadata.schema_migration, 948f2e5f-8447-4093-bd7f-cf32be7289f1] [2017-01-06 11:58:10,644] lcm INFO [main] u.s.c.CassandraLockingMechanism - [] Lock currently held by Row[false, channel_metadata.schema_migration, 948f2e5f-8447-4093-bd7f-cf32be7289f1] [2017-01-06 11:58:11,171] lcm INFO [main] u.s.c.CqlMigratorImpl - [] Loading cql files from [/tmp/cqlmigrate7688832900537474535] [2017-01-06 11:58:11,180] lcm INFO [main] u.s.c.KeyspaceBootstrapper - [] Keyspace found, not applying bootstrap.cql [2017-01-06 11:58:11,206] lcm ERROR [main] u.s.c.CqlLoader - [] Failed to execute cql statements [CREATE TABLE schema_updates (filename text primary key, checksum text, applied_on timestamp);]: Table channel_metadata.schema_updates already exists

Add fixed delay in between DDL changes to accommodate node time drift

Each DDL change should be separated by a fixed delay to ensure we cater for time drift between the nodes: delay >= max node time drift

When performing DDL changes, cassandra is always using the node timestamp when announcing alter table statements or other DDL changes regardless of whether a custom timestamp generator is provided when creating the session. As each DDL change can be executed on a different node, we need to wait long enough to ensure upgrades are timestamp ordered across all nodes.

Add regression tests for Cassandra 2.x and 3.x

CqlMigrate should work in both versions, and should be able to be tested within both versions.
Could be done by creating three modules: one for CqlMigrate and two other for tests. The latter should share the tests meanwhile is possible (no break changes)

Add a sensible default for the lock configuration

Using cqlmigrate requires too many steps out of the box. We should provide sensible defaults for the lock configuration and not require a user to provide it.

Similarly the migrator api could be a bit nicer, by not requiring asList.

File Descriptor Resource not released on creating CqlPaths.

On running cqlmigrate a new DirectoryStream object is created for each directory.

This is not closed, leading to the file descriptor resource being held for the duration of the run.

This is not so much an issue when cqlmigrate is being run once with the odd directory, but is a much larger issue when running cqlmigrate thousands of times. This results in the JVM's resources being filled up. We experienced this when running functional tests.

Current Implementation CqlPaths:

        directories.stream()
                .map(CqlPaths::directoryStreamFromPath)
                .flatMap(directoryStream -> StreamSupport.stream(directoryStream.spliterator(), false))
                .forEach(path -> addPathToMap(cqlPathsMap, path));

Proposed Solution:

    directories.stream()
                .forEach( directory -> {
                    try( DirectoryStream<Path> directoryStream = directoryStreamFromPath(directory)) {
                        StreamSupport.stream(directoryStream.spliterator(), false)
                                .forEach(path -> addPathToMap(cqlPathsMap, path));
                    } catch(IOException e){
                        throw new UncheckedIOException(e);
                    }
                });

Trailing empty lines in cql files no longer allowed

After upgrade from 0.9.6 to 0.9.8, previously working cql files no longer parse.

If a CQL files as more than one 'empty' line at the end, parsing fails with:

File had a non-terminated cql line
java.lang.IllegalStateException: File had a non-terminated cql line
at uk.sky.cqlmigrate.CqlFileParser$LineProcessor.check(CqlFileParser.java:179)
at uk.sky.cqlmigrate.CqlFileParser$LineProcessor.access$100(CqlFileParser.java:39)
at uk.sky.cqlmigrate.CqlFileParser.getCqlStatementsFrom(CqlFileParser.java:34)
at uk.sky.cqlmigrate.CqlFileParserTest.trailingEmptyLinesAreAllowed(CqlFileParserTest.java:102)

This breaks backward compatibility. Changing old changelogs to remove the 'redundant' trailing empty lines is not an option, since that breaks SHA1's.

Split up into modules

  • core - contains the library only
  • cli - contains a standalone jar that can be run at the command line
  • dw - dropwizard plugin to add cqlMigrate task

Locking

Is there currently a way of using this tool without locking? I would like to use it with scylla db, but scylla does not currently allow for LWT. If not, I can work on adding a configuration to allow for use without locking.

Consider updating to support metrics 4.x

Cassandra driver 3.7.x doesn't work with metrics 4.x - the JMXReporter class has moved in metrics making it incompatible.

https://docs.datastax.com/en/developer/java-driver/3.5/manual/metrics/ details how to address this; disabling the JMX reporter when constructing the cluster and then optionally, explicitly setting up JMX reporting if desired.

I'm unsure if users of this library rely on the JMXReporter behaviour, so unsure whether to simply disable it always, or if there is a need to add support to optionally enable it.

Unable to get the /cql folder path from the fat JAR

I am using below code line to execute my Java App which is simply using cqlmigrate as maven dependency.
schemas = Paths.get(cqlmigrateApp.class.getResource("/cql/").toURI());
When I run the java program as a stand alone it works fine , keyspace gets created and .cql files run successfully. But when using same code I build a fat jar and run it. Then it seems the code is unable to obtain the /cql folder path from within the jar. And exception is thrown java.nio.file.FileSystemNotFoundException.
The program stops here and the lock is held on schema and I can not do anything.
Could anyone help here please ?
Regards
Chandan

Cluster check should be configurable with an expected number of nodes

We ran into a problem where we replaced some cassandra nodes. The cluster was perfectly fine, but the old nodes were still in the system.peers table. So the migration failed, since it saw the old dead node as unhealthy.

I'd prefer if:

  • Cqlmigrate took the number of expected nodes in the cluster
  • Ensure that a quorum is healthy (rather than all)

I think that should be sufficient to give us confidence that a schema change is safe to apply. The drawback is it adds more configuration - perhaps a simplification is to just check that a quorum of getAllHosts is available, rather than all of them.

Cluster is considered unhealthy if some nodes are unreachable

The ClusterHealth check is considered unhealthy if some nodes are unreachable even if the configured consistencyLevel can be satisfied.

Our app can is healthy and able to serve clients, but cqlmigrate prevents it from starting if the cluster is considered unhealthy.

Fail gracefully if lock quorum is not met at start of run

We've run into this problem a few times in our dev environments. When the cluster is in a state that quorum will not be met for the CQL updates, CQLMigrate executes as follows:

  • Obtain lock (via insert if not exists)
  • Attempt to execute CQL updates
  • Fail to achieve write consistency, and fail the CQLMigrate run
  • Do not release lock

While this behaviour is great, it means that if the cluster recovers itself (eg, an unavailable node is restarted) then it requires manual intervention to release locks explicitly before re-running the jobs. Recently the ability to specify lock consistency levels was added, but that has effectively the same behaviour, since the create-lock call will fail but the lock will still be inserted on nodes.

We'd like to suggest the following behaviour change to try and make cqlmigrate recover more gracefully:

  • Attempt to read locks table at specified locks consistency
  • Obtain lock (via insert if not exists)
  • Attempt to execute CQL updates
  • ... as before

In this scenario, if the locks consistency cannot be met then the locks read will fail, causing cqlmigrate to fail but no lock to be held, and the whole process to be very easily retryable. Should an error occur when obtaining locks or executing cql updates, the lock continues to be held in the same way today.

I'm unsure if this would be considered a breaking change, it's a change in behaviour such that a run may fail but no lock would be held, but from our perspective that would be an improved feature rather than fundamental behaviour change.

Assuming this is acceptable we're happy to raise a PR for the changes, but wanted to open it up to discussions first.

Example results in Keyspace cqlmigrate does not exist

Followed example in the README, and fails with the following.

uk.sky.cqlmigrate.exception.CannotAcquireLockException: Query to prepare locks queries failed
[info]   at uk.sky.cqlmigrate.CassandraLockingMechanism.init(CassandraLockingMechanism.java:43)
[info]   at uk.sky.cqlmigrate.Lock.lock(Lock.java:38)
[info]   at uk.sky.cqlmigrate.CqlMigratorImpl.migrate(CqlMigratorImpl.java:77)
[info]   ...

[info]   Cause: com.datastax.driver.core.exceptions.InvalidQueryException: Keyspace cqlmigrate does not exist
[info]   at com.datastax.driver.core.exceptions.InvalidQueryException.copy(InvalidQueryException.java:50)
[info]   at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)
[info]   at com.datastax.driver.core.AbstractSession.prepare(AbstractSession.java:98)
[info]   at uk.sky.cqlmigrate.CassandraLockingMechanism.init(CassandraLockingMechanism.java:39)
[info]   at uk.sky.cqlmigrate.Lock.lock(Lock.java:38)
[info]   at uk.sky.cqlmigrate.CqlMigratorImpl.migrate(CqlMigratorImpl.java:77)

Code:

import java.io.{FileNotFoundException, File}
import java.nio.file.{Paths, Path}
import java.time.Duration

import com.datastax.driver.core.Session
import uk.sky.cqlmigrate.{CqlMigratorFactory, CqlMigrator, CassandraLockConfig}
import scala.collection.JavaConversions._

...

val lockConfig: CassandraLockConfig =
      CassandraLockConfig.builder()
      .withTimeout(Duration.ofSeconds(3))
      .withPollingInterval(Duration.ofMillis(100))
      .build()

    val migrator: CqlMigrator = CqlMigratorFactory.create(lockConfig)
    val schemas: Path = Paths.get(
      Option(ClassLoader.getSystemResource(toSchemaResourcePath.stripPrefix("/")))
      .getOrElse(throw new FileNotFoundException(toSchemaResourcePath))
      .toURI())
    migrator.migrate(session, keyspace, List(schemas))

CassandraLockConfig.withClientId() method is prone to accidental misuse

In order for the locking mechanism to work, each application instance has to use a unique client ID.

The CassandraLockConfig.withClientId() method is potentially misleading - if a client application uses a static value for this, instead of a UUID, then multiple instances can share the same lock and schema chaos may result.

@adamdougal and I believe this method should be either:

  • removed entirely, or
  • at least renamed to make it clear that the value provided should be a unique ID.

Produce a cqlmigrate Docker image

The typical model for using cqlmigrate is for it to run at application startup, but for applications deployed to Kubernetes an alternative approach is to run it as a Kubernetes job before rolling out a new version of the application.

It would be helpful if there was a prebuilt cqlmigrate Docker image for this purpose.

Question: What possible problems there are with collection types?

The caveats section of the README says this about schema change safety:

Generally, adding columns is safe (but be careful with collection types).

Might it be possible to add some more information about the possible problems with adding collection columns or perhaps link to documentation or some relevant issue(s) if any?

`CqlPaths` file operation doesn't appear to support files embedded in a JAR

Trying to run from within a jar on files contained within that jar, the following exception is hit.

[2015-12-17 17:04:55,095] umv-service INFO [main] u.s.c.CqlMigratorImpl - [request=] [client=] [x-skyint-requestid=] [] [] [] [] Loading cql files from [cqlschema/common, cqlschema/local] Exception in thread "main" java.lang.UnsupportedOperationException at com.sun.nio.zipfs.ZipPath.toFile(ZipPath.java:597) at uk.sky.cqlmigrate.CqlPaths.lambda$create$4(CqlPaths.java:28) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at uk.sky.cqlmigrate.CqlPaths.create(CqlPaths.java:32) at uk.sky.cqlmigrate.CqlMigratorImpl.migrate(CqlMigratorImpl.java:83) at uk.sky.cqlmigrate.CqlMigratorImpl.migrate(CqlMigratorImpl.java:65)

I gather from @adamdougal that there's been a fair amount of refactoring from the legacy CqlMigrate to update to Java 8 - and I'm guessing that thus far this (mainline) use case has not been tested?

This suggests to me that we probably need the following:

  • Integration tests to prove running CqlMigrate from within a JAR
  • This issue to be fixed.

Standalone usage

Hi,

Is it possible to use clqmigrate 0.9.6 version jar as standalone app like here I just realized, that it doesn't contains dependencies.

Are you really meant to be a public repository?

We have noticed this repository was marked as public. There are certain standards required before a repository in the sky-uk org can be made public, including the presence of valid LICENSE.md, README.md, and CONTRIBUTING.md files.

  • Repos without license information are immediately made private.
  • Repos failing the other criteria will be made private after 30 days.

Please resolve these problems ASAP and close this GitHub issue when you have done so.

If you have any questions, please ask them on the #github Slack channel.

How can we increase the wait time in case of lock scenario

There is an internal locking mechanism which enables multiple application make changes to the same database on one on one basis so that they do not step on each others feet.
What is the waiting timeout duration currently set in the tool ?
How can we increase this duration ?

Release 0.9.7 (key-space locking).

Hi,

I can see some changes in master that include No op locking.
It is possible to release new version of cqlmigrate that include these?

Thanks

Allow cluster health check to be optional

At the moment cqlmigrate requires that all nodes in all datacentres are up before it will run. We would like to make this check optional so that it will still run if a node is down so that the migration will be attempted with the supplied consistency level - which we will plan to set to LOCAL_QUORUM for read and EACH_QUORUM for write for our migrations.

Support Cassandra 4.x Driver

From here:

Version 4 is major redesign of the internal architecture. As such, it is not binary compatible with previous versions. However, most of the concepts remain unchanged, and the new API will look very familiar to 2.x and 3.x users.

The "not binary compatible" will require changes in this library as well as existing testing tools (like scassandra).

References

Set differing read and write consistency levels

Currently in 0.9.0, the consistency level is defaulted to ALL for both reads and writes when performing migrations. Enforcing ConsistencyLevel.ALL for both might be a little stringent, and has been known to cause read timeouts when attempting to read the schema_updates table when looking to see which files have already been applied. Allowing the user to define what they want as the read/write consistency level would allow more flexibility.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.