|
| 1 | +-- Helper module for 200_to_210 migration operations. |
| 2 | +-- |
| 3 | +-- Operations are versioned and specific to a migration so they remain |
| 4 | +-- fixed in time and are not modified for use in future migrations. |
| 5 | +-- |
| 6 | +-- If you want to reuse these operations in a future migration, |
| 7 | +-- copy the functions over to a new versioned module. |
| 8 | + |
| 9 | + |
| 10 | +local ngx = ngx |
| 11 | +local uuid = require "resty.jit-uuid" |
| 12 | +local cassandra = require "cassandra" |
| 13 | + |
| 14 | + |
| 15 | +local default_ws_id = uuid.generate_v4() |
| 16 | + |
| 17 | + |
| 18 | +local function render(template, keys) |
| 19 | + return (template:gsub("$%(([A-Z_]+)%)", keys)) |
| 20 | +end |
| 21 | + |
| 22 | + |
| 23 | +local function cassandra_get_default_ws(connector) |
| 24 | + local rows, err = connector:query("SELECT id FROM workspaces WHERE name='default'") |
| 25 | + if err then |
| 26 | + return nil, err |
| 27 | + end |
| 28 | + |
| 29 | + if not rows |
| 30 | + or not rows[1] |
| 31 | + or not rows[1].id |
| 32 | + then |
| 33 | + return nil |
| 34 | + end |
| 35 | + |
| 36 | + return rows[1].id |
| 37 | +end |
| 38 | + |
| 39 | + |
| 40 | +local function cassandra_create_default_ws(connector) |
| 41 | + local created_at = ngx.time() * 1000 |
| 42 | + |
| 43 | + local _, err = connector:query("INSERT INTO workspaces(id, name, created_at) VALUES (?, 'default', ?)", { |
| 44 | + cassandra.uuid(default_ws_id), |
| 45 | + cassandra.timestamp(created_at) |
| 46 | + }) |
| 47 | + if err then |
| 48 | + return nil, err |
| 49 | + end |
| 50 | + |
| 51 | + return cassandra_get_default_ws(connector) or default_ws_id |
| 52 | +end |
| 53 | + |
| 54 | + |
| 55 | +local function cassandra_ensure_default_ws(connector) |
| 56 | + |
| 57 | + local default_ws, err = cassandra_get_default_ws(connector) |
| 58 | + if err then |
| 59 | + return nil, err |
| 60 | + end |
| 61 | + |
| 62 | + if default_ws then |
| 63 | + return default_ws |
| 64 | + end |
| 65 | + |
| 66 | + return cassandra_create_default_ws(connector) |
| 67 | +end |
| 68 | + |
| 69 | + |
| 70 | +-------------------------------------------------------------------------------- |
| 71 | +-- Postgres operations for Workspace migration |
| 72 | +-------------------------------------------------------------------------------- |
| 73 | + |
| 74 | + |
| 75 | +local postgres = { |
| 76 | + |
| 77 | + up = [[ |
| 78 | + ]], |
| 79 | + |
| 80 | + teardown = { |
| 81 | + |
| 82 | + ------------------------------------------------------------------------------ |
| 83 | + -- Update composite cache keys to workspace-aware formats |
| 84 | + ws_update_composite_cache_key = function(_, connector, table_name, is_partitioned) |
| 85 | + local sql = render([[ |
| 86 | + UPDATE "$(TABLE)" |
| 87 | + SET cache_key = CONCAT(cache_key, ':', |
| 88 | + (SELECT id FROM workspaces WHERE name = 'default')) |
| 89 | + WHERE cache_key LIKE '%:'; |
| 90 | + ]], { |
| 91 | + TABLE = table_name, |
| 92 | + }) |
| 93 | + |
| 94 | + print(sql) |
| 95 | + |
| 96 | + local _, err = connector:query(render([[ |
| 97 | + UPDATE "$(TABLE)" |
| 98 | + SET cache_key = CONCAT(cache_key, ':', |
| 99 | + (SELECT id FROM workspaces WHERE name = 'default')) |
| 100 | + WHERE cache_key LIKE '%:'; |
| 101 | + ]], { |
| 102 | + TABLE = table_name, |
| 103 | + })) |
| 104 | + if err then |
| 105 | + return nil, err |
| 106 | + end |
| 107 | + |
| 108 | + return true |
| 109 | + end, |
| 110 | + }, |
| 111 | + |
| 112 | +} |
| 113 | + |
| 114 | + |
| 115 | +-------------------------------------------------------------------------------- |
| 116 | +-- Cassandra operations for Workspace migration |
| 117 | +-------------------------------------------------------------------------------- |
| 118 | + |
| 119 | + |
| 120 | +local cassandra = { |
| 121 | + |
| 122 | + up = [[ |
| 123 | + ]], |
| 124 | + |
| 125 | + teardown = { |
| 126 | + |
| 127 | + ------------------------------------------------------------------------------ |
| 128 | + -- Update composite cache keys to workspace-aware formats |
| 129 | + ws_update_composite_cache_key = function(_, connector, table_name, is_partitioned) |
| 130 | + local coordinator = assert(connector:connect_migrations()) |
| 131 | + local default_ws, err = cassandra_ensure_default_ws(connector) |
| 132 | + if err then |
| 133 | + return nil, err |
| 134 | + end |
| 135 | + |
| 136 | + if not default_ws then |
| 137 | + return nil, "unable to find a default workspace" |
| 138 | + end |
| 139 | + |
| 140 | + for rows, err in coordinator:iterate("SELECT id, cache_key FROM " .. table_name) do |
| 141 | + if err then |
| 142 | + return nil, err |
| 143 | + end |
| 144 | + |
| 145 | + for i = 1, #rows do |
| 146 | + local row = rows[i] |
| 147 | + if row.cache_key:match(":$") then |
| 148 | + local cql = render([[ |
| 149 | + UPDATE $(TABLE) SET cache_key = '$(CACHE_KEY)' WHERE $(PARTITION) id = $(ID) |
| 150 | + ]], { |
| 151 | + TABLE = table_name, |
| 152 | + CACHE_KEY = row.cache_key .. ":" .. default_ws, |
| 153 | + PARTITION = is_partitioned |
| 154 | + and "partition = '" .. table_name .. "' AND" |
| 155 | + or "", |
| 156 | + ID = row.id, |
| 157 | + }) |
| 158 | + |
| 159 | + local _, err = connector:query(cql) |
| 160 | + if err then |
| 161 | + return nil, err |
| 162 | + end |
| 163 | + end |
| 164 | + end |
| 165 | + end |
| 166 | + |
| 167 | + return true |
| 168 | + end, |
| 169 | + |
| 170 | + } |
| 171 | + |
| 172 | +} |
| 173 | + |
| 174 | + |
| 175 | +-------------------------------------------------------------------------------- |
| 176 | +-- Higher-level operations for Workspace migration |
| 177 | +-------------------------------------------------------------------------------- |
| 178 | + |
| 179 | +local function ws_adjust_data(ops, connector, entities) |
| 180 | + for _, entity in ipairs(entities) do |
| 181 | + |
| 182 | + if entity.cache_key and #entity.cache_key > 1 then |
| 183 | + local _, err = ops:ws_update_composite_cache_key(connector, entity.name, entity.partitioned) |
| 184 | + if err then |
| 185 | + return nil, err |
| 186 | + end |
| 187 | + end |
| 188 | + end |
| 189 | + |
| 190 | + return true |
| 191 | +end |
| 192 | + |
| 193 | +postgres.teardown.ws_adjust_data = ws_adjust_data |
| 194 | +cassandra.teardown.ws_adjust_data = ws_adjust_data |
| 195 | + |
| 196 | + |
| 197 | +-------------------------------------------------------------------------------- |
| 198 | + |
| 199 | + |
| 200 | +return { |
| 201 | + postgres = postgres, |
| 202 | + cassandra = cassandra, |
| 203 | +} |
0 commit comments