Phalanx is a Cassandra Migration utility written in Swift, with ergonomics inspired by flyway.
There are other Cassandra migration tools written in Java and Python.
Phalanx is geared for developers already writing a Swift backend/microservice, who might like to stay within the scope of a familiar toolchain/ecosystem.
Phalanx is based on Apple's open source Cassandra client library.
Add Phalanx to your own Package.swift:
.package(url: "https://github.com/jmfieldman/phalanx.git", from: "1.0.0")
Swift PM will automatically detect the executable target, so you can now run the phalanx executable through your own package:
$ swift run phalanx ...
If Phalanx has dependency conflicts with your project, or you simply want a more streamlined execution experience, try installing Phalanx using the very nice Mint Package Manager.
Mint builds each Swift executable in its own environment, tracks versions, and supports localized version-pegging through a Mintfile. This avoids continuous, unnecessary rebuild-checks when your own project's Package.swift changes.
# Install mint on your system, e.g.
$ brew install mint
# Install Phalanx
$ mint install jmfieldman/phalanx
# Run Phalanx using Mint. This is the recommended method if you plan
# on using a Mintfile for version-pegging
$ mint run phalanx <..>
# Or run it directly if you have the Mint bin directory in your path
$ phalanx <..>
Phalanx offers two basic functions: clean
and migrate
.
# Phalanx will use the keyspace associated
# with the command to `DROP KEYSPACE <keyspace>`
$ phalanx clean
# Phalanx will use the detected migration files to bring your
# keyspace up to the most recent version.
$ phalanx migrate
Phalanx is typically configured using a config file. Details of the available configuration options, including all of the command-line overrides, are available in the Example Configuration
# Phalanx looks for phalanx.yml by default, but you can override
# that with the --config parameter, e.g.
$ phalanx --config conf/phalanx.yml migrate
All configuration can be set using command line options as well; use help for reference:
$ phalanx --help
Migration files should all be grouped into a single directory. Phalanx will look through the contents of the migration directory for any files that match the migration file pattern.
You can configure the file prefix, extension, and version-description separator that define a migration's file name structure.
An example file listing might look like:
# Prefix = null
# Separatpr = "-"
# Extension = "cql"
$ ls
000-create_keyspace.cql
001-create_user_table.cql
002-add_password_column_to_users.cql
003-create_device_table.cql
README.md # This file will be ignored as it does not match migration patterns
Migration files can contain their own unique metadata that affects just their specific invocation. This metadata must be included at the top of the migration file. It is formatted as CQL-commented YAML:
-- metadata:
-- description: This overrides the filename-based description
-- invocationDelay: <int> # Overrides the global invocation delay
-- consistency: <string> # Overrides the global consistency config
CREATE TABLE ...
Ensure that an empty line is present after the metadata to end YAML parsing.
One Keyspace Per Invocation
Any single Phalanx invocation will only operate on the one keyspace defined in the config or command line. If you want to setup migrations for multiple keyspaces they will need to be in isolated directories, and you will need to invoke Phalanx separately for each keyspace.
Migration 0 is Reserved for Keyspace Creation
Phalanx expects that initial migrations start with a blank slate, and that no keyspace is ready before migration 0. Since keyspace creation can involve complex custom parameters, Phalanx reserves migration 0 for keyspace creation.
This means that the migration tagged version 0 (e.g. 000-create_keyspace.cql
)
may only contain a command that starts with CREATE KEYSPACE
.
If you do not want Phalanx to be responsible for keyspace creation, you can create the keyspace yourself, and begin migration files with version 1.
Phalanx will throw an error if the keyspace does not exist and you are missing version 0.
Use the Keyspace Placeholder for Mirrored Keyspaces
In some cases, you may want the same migration chain to exist for multiple keyspaces. For example, you may use a single local Cassandra node for local development, unit tests, and a local CI agent.
To keep the data in these scopes properly siloed, you would use a different keyspace for each (e.g. project_local, project_tests, project_ci, etc)
In this case, you can use the placeholder $${{KEYSPACE}}$$
in your migration
files, and the migration engine will automatically replace it with the
currently-executing keyspace. This is especially useful for the zero-version
migration that creates the keyspace.
Migration Files can only Contain One Command Each
Because Cassandra doesn't have traditional multi-command transactions, it isn't safe to put multiple commands in a single migration version. If, say, a migration file contained 10 commands and the 5th one failed, there would be no clean way to record that a certain migration file was "half complete".
We can insure that individual commands are successful, and locked into the state table, by restricting migration files to one command each.
Phalanx has a suite of unit tests that can be run from the command line:
$ swift test
The tests expect a Cassandra node available at 127.0.0.1:9042, and will operate
on the phalanx_test_keyspace
keyspace (dropping and creating it several times.)