Cassie provides versioned migrations similar to many existing adapters and frameworks.
Practically speaking, this gives your cluster Schema its own "version" and simplifies upgrading or rolling back the schema.
As such, Cassie uses semantic versioning, where a defined version describes the keyspace defined in the cluster configuration.
Major, minor, patch, and build versions are used, however semantic extensions are not recommended (prerelase or metadata, eg: 1.0.0.beta).
Schema version and migrations are managed through various cassie
tasks. See below for basic usage.
List command descriptions and advanced options:
cassie --help
If using Rails, and Rails needs to be initialized when loading cassandra.yml
or your migration files, remember to use the cassie-rails
commands.
If no schema has been defined yet (e.g. no keyspace, tables, or types), simply initialize Cassie versioning:
cassie schema:init
-- Initializing Cassie Versioning
-- done
-- Initializing 'my_app_development' Keyspace
-- done
If an existing schema (e.g. keyspace, tables, types) is alredy defined, see below on how to import it.
Import your existing cassandra_migrations
migration files with a single task:
cassie migrations:import
-- Initializing Cassie Versioning
-- done
-- Initializing 'my_app_development' Keyspace
-- done
-- Importing `cassandra_migrations` migration files
- Importing db/cassandra_migrate/20161206214301_initial_database.rb
> created /db/cassandra/migrations/0000_0000_0000_0001_initial_database.rb
> recorded version 0.0.0.1
- done
- Importing db/cassandra_migrate/20161212210447_add_username_to_users.rb
> created /db/cassandra/migrations/0000_0000_0001_0000_add_username_to_users.rb
> recorded version 0.0.1.0
- done
- Importing db/cassandra_migrate/20161213163201_add_reserved_to_users.rb
> created /db/cassandra/migrations/0000_0000_0002_0000_add_reserved_to_users.rb
> recorded version 0.0.2.0
- done
-- done
-- Dumping Cassandra schema (version 0.0.0.1)
- Writing to db/cassandra/schema.rb
- done
-- done
The original
cassandra_migrations
migration files and schema in the physical layer are not changed. Remove the old files when comfortable.
Import your existing schema held in Cassandra with a single task:
cassie schema:import
-- Initializing Cassie Versioning
-- done
-- Initializing 'my_app_development' Keyspace
> 'my_app_development' already exists
-- done
-- Importing Schema from Cassandra
- Creating initial version
> created db/cassandra/migrations/0000_0000_0001_0000_import_my_app_development.rb
> recorded version 0.0.1.0
- done
-- done
-- Dumping Cassandra schema (version 0.0.1.0)
- Writing to db/cassandra/schema.rb
- done
-- done
Locally, these import tasks will also initialiaze the local version tracking to have all migration versions recorded.
However, another developer's or environment's database does not have this schema metadata. Syncronize version tracking for these databases by initializing cassie schema with the version of the current in-database schema.
cassie schema:init -v 0.0.2.0
-- Initializing Cassie Versioning
-- done
-- Fast-forwarding to version 0.0.2.0
> Recorded version 0.0.0.1
> Recorded version 0.0.1.0
> Recorded version 0.0.2.0
-- done
-- Initializing 'my_app_development' Keyspace
-- done
This does not run any migrations, but rather updates schema version metadata, so future migrations begin after the provided version.
cassie migration:create that killer feature
-- Creating migration file for version 0.0.1.0
> created db/cassandra/migrations/0000_0000_0001_0000_that_killer_feature.rb
-- done
# db/cassandra/migrations/0000_0000_0001_0000_that_killer_feature.rb
class Migration_0_0_1_0 < Cassie::Schema::Migration
def up
# Code to execute when applying this migration
# Supports the excellent `cassandra_migrations` DSL
# or call `execute` to call `Cassandra::Session.execute`
end
def down
# Code to execute when rolling back this migration
# Supports the excellent `cassandra_migrations` DSL
# or call `execute` to call `Cassandra::Session.execute`
end
end
By default, the patch
version will be bumped. Use the --major
(-M
), --minor
(-m
), or --build
(-b
) switches to bump differently. Or, explicitly set the version with --version
(-v
): cassie migration:create that fixup -v 0.1.3.15
.
Note: The class name only needs to match the version in the filename. The description suffix can be changed without having to change the classname.
cassie migrate
cassie migrate 0.2.0
Use the same command to migrate up or down to a specific version.
cassie migrate 0.1.9
cassie schema:version
+-----------+----------------+-------------+---------------------------+
| Environment: development |
+-----------+----------------+-------------+---------------------------+
| Version | Description | Migrated by | Migrated at |
+-----------+----------------+-------------+---------------------------+
| * 0.2.0.0 | create users | serverbot | 2016-09-08 10:23:54 -0500 |
+-----------+----------------+-------------+---------------------------+
cassie schema:history
+-----------+----------------+-------------+---------------------------+
| Environment: development |
+-----------+----------------+-------------+---------------------------+
| Version | Description | Migrated by | Migrated at |
+-----------+----------------+-------------+---------------------------+
| * 0.2.0.0 | create users | serverbot | 2016-09-08 10:23:54 -0500 |
| 0.1.0.0 | initial schema | eprothro | 2016-09-08 09:23:54 -0500 |
+-----------+----------------+-------------+---------------------------+
Display all applied and unapplied migrations.
cassie schema:status
+-----------+----------------+--------+---------------------------------------------------------------+
| Environment: development |
+-----------+----------------+--------+---------------------------------------------------------------+
| Number | Description | Status | Migration File |
+-----------+----------------+--------+---------------------------------------------------------------+
| 0.0.3.0 | create friends | DOWN | db/cassandra/migrations/0000_0000_0003_0000_create_friends.rb |
| * 0.0.2.0 | create users | UP | db/cassandra/migrations/0000_0000_0002_0000_create_users.rb |
| 0.1.0.0 | initial schema | UP | db/cassandra/migrations/0000_0000_0001_0000_initial_schema.rb |
+-----------+----------------+--------+---------------------------------------------------------------+
The full schema is stored in schema.rb
, this is recommended to be checked into source control.
It is updated (with a full dump) after each migration, to maintain a truth-store for the schema when used with multiple developers.
cassie schema:dump
-- Dumping 'development' schema (version 0.2.0.0)
- Writing to db/cassandra/schema.rb
- done
-- done
cassie schema:drop
-- Dropping 'development' schema
- Dropping 'my_app_development'
- done
- Clearning schema version metadata
> removed 2 versions
- done
-- done
cassie schema:load
-- Loading 'development' schema from db/cassandra/schema.rb
> Schema is now at version 0.2.0.0
-- done
cassie schema:reset
-- Dropping 'development' schema
- Dropping 'my_app_development'
- done
- Clearning schema version metadata
> removed 2 versions
- done
-- done
-- Loading 'development' schema from db/cassandra/schema.rb
> Schema is now at version 0.2.0.0
-- done
This task reload the schema from the schema file, and then proceeds with incremental migrations up to the latest migration.
cassie migrate:reset
-- Dropping 'development' schema
- Dropping 'my_app_development'
- done
- Clearning schema version metadata
> removed 2 versions
- done
-- done
-- Loading 'development' schema from db/cassandra/schema.rb
> Schema is now at version 0.2.0.0
-- done
-- Migrating 'development' schema to version 0.2.1.0
- Migragting version 0.2.1.0 UP
- done (4.89 ms)
-- done
-- Dumping 'development' schema (version 0.2.1.0)
- Writing to db/cassandra/schema.rb
- done
-- done
Set the environment with RACK_ENV
, CASSANDRA_ENV
or the --env
(-e
) switch for cassie
commands:
RACK_ENV=test cassie migrate:reset
is equivalent to
cassie migrate:reset -e test
The schema.rb
file contains keyspace-agnostic DSL. When loading the schema, its commands will be run against the default keyspace for the environment.
A Version
is a container class for a migration
. A version may be applied in the current database's schema, or not.
There are multiple independent, but potentially related/overlapping collections of versions
.
One is Cassie::Schema.applied_versions
, which is the set of versions that have been applied, in the past, to a Cassandra database.
Another is Cassie::Schema.local_versions
, which the set of versions represented by migration files found in the migrations_directory
.
Versions are migrated up or down, and then recorded or forgotten, respectively, in the database's configurable <schema_keyspace>.<versions_table>
(cassie_schema.versions
by default).
Strictly speaking, the version is what is being migrated up or down. The Migration
is the class defining code to execute up
or down
. The version object delegates implementation of the migration to the Migration
object.
This class embeds the version number in it, but the Migration
object does not know about the concept of its version. A migration file is used to load a Version
, which contains the Migration
object.
Cassie only expects that the version number emedded in the class name match the one embedded in the file name.
This means you can change the description embedded in the migration file without having to rename the class.
Migrating down rolls back the state of the schema in the Cassandra database. The in-database schema history keeps track of what migrations have been applied and rolls them back in that order (as opposed to whatever order the files indicate). This ensures the following scenario is supported:
-
Given the following mirgations exist:
- 0.1.0.0
- 0.1.1.0
-
And both migrations have been executed.
-
When a migraiton is created for version
0.1.0.99
-
And the schema is migrated with
cassie migrate 0.1.0.0
-
Then the
down
method for0.1.0.99
is NOT executed -
And then when the schema is migrated with
cassie migrate
, theup
methods from the following migrations are executed:- 0.1.0.99
- 0.1.1.0