ZDT Column Rename in a Distributed System
In order to deploy code to a highly available distributed system any two sequential versions of the code can be running at the same time. Therefore they need to be compatible.
- Add the new column, keep the columns in sync when updating.
- Migrate the data, start using the new column however fallback to the old column if the new column is blank, continue keeping the columns in sync.
- Remove all dependencies on the old column, only use the new column, do not sync them anymore.
- Drop the column.
When in Rails, Step #3 requires some special care as the column needs to be marked for removal:
module MarkColumnsForRemoval
def mark_columns_for_removal(*columns_marked_for_removal)
@columns_marked_for_removal = columns_marked_for_removal.map(&:to_s)
end
##
# Overrides ActiveRecord's list of the database columns in order to hide a column which we intend to delete
# This ensures that ActiveRecord does not try to read or write to the column
#
def columns
cols = super
cols.reject { |col| (@columns_marked_for_removal || []).include?(col.name.to_s) }
end
end
class SomeModel < ActiveRecord::Base
# Remove this as part of step 4 when dropping the old_column
extend MarkColumnsForRemoval
mark_columns_for_removal :old_column
end
Written on October 31, 2016 by adamkerr