fix(dsstore): ensure backward compatibility

This commit is contained in:
Andrew Mayorov 2024-06-14 14:16:05 +02:00
parent 8538a5a5b6
commit 5fd5fc76e5
No known key found for this signature in database
GPG Key ID: 2837C62ACFBFED5D
1 changed files with 91 additions and 8 deletions

View File

@ -1133,23 +1133,106 @@ erase_schema_runtime(Shard) ->
-undef(PERSISTENT_TERM).
-define(ROCKSDB_SCHEMA_KEY, <<"schema_v1">>).
-define(ROCKSDB_SCHEMA_KEY(V), <<"schema_", V>>).
-define(ROCKSDB_SCHEMA_KEY, ?ROCKSDB_SCHEMA_KEY("v2")).
-define(ROCKSDB_SCHEMA_KEYS, [
?ROCKSDB_SCHEMA_KEY,
?ROCKSDB_SCHEMA_KEY("v1")
]).
-spec get_schema_persistent(rocksdb:db_handle()) -> shard_schema() | not_found.
get_schema_persistent(DB) ->
case rocksdb:get(DB, ?ROCKSDB_SCHEMA_KEY, []) of
get_schema_persistent(DB, ?ROCKSDB_SCHEMA_KEYS).
get_schema_persistent(DB, [Key | Rest]) ->
case rocksdb:get(DB, Key, []) of
{ok, Blob} ->
Schema = binary_to_term(Blob),
%% Sanity check:
#{current_generation := _, prototype := _} = Schema,
Schema;
deserialize_schema(Key, Blob);
not_found ->
not_found
end.
get_schema_persistent(DB, Rest)
end;
get_schema_persistent(_DB, []) ->
not_found.
-spec put_schema_persistent(rocksdb:db_handle(), shard_schema()) -> ok.
put_schema_persistent(DB, Schema) ->
Blob = term_to_binary(Schema),
rocksdb:put(DB, ?ROCKSDB_SCHEMA_KEY, Blob, []).
-spec deserialize_schema(_SchemaVsn :: binary(), binary()) -> shard_schema().
deserialize_schema(SchemaVsn, Blob) ->
%% Sanity check:
Schema = #{current_generation := _, prototype := _} = binary_to_term(Blob),
decode_schema(SchemaVsn, Schema).
decode_schema(?ROCKSDB_SCHEMA_KEY, Schema) ->
Schema;
decode_schema(?ROCKSDB_SCHEMA_KEY("v1"), Schema) ->
maps:map(fun decode_schema_v1/2, Schema).
decode_schema_v1(?GEN_KEY(_), Generation = #{}) ->
decode_generation_schema_v1(Generation);
decode_schema_v1(_, V) ->
V.
decode_generation_schema_v1(SchemaV1 = #{cf_refs := CFRefs}) ->
%% Drop potentially dead CF references from the time generation was created.
Schema = maps:remove(cf_refs, SchemaV1),
Schema#{cf_names => cf_names(CFRefs)};
decode_generation_schema_v1(Schema = #{}) ->
Schema.
%%--------------------------------------------------------------------------------
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
decode_schema_v1_test() ->
SchemaV1 = #{
current_generation => 42,
prototype => {emqx_ds_storage_reference, #{}},
?GEN_KEY(41) => #{
module => emqx_ds_storage_reference,
data => {schema},
cf_refs => [{"emqx_ds_storage_reference41", erlang:make_ref()}],
created_at => 12345,
since => 0,
until => 123456
},
?GEN_KEY(42) => #{
module => emqx_ds_storage_reference,
data => {schema},
cf_refs => [{"emqx_ds_storage_reference42", erlang:make_ref()}],
created_at => 54321,
since => 123456,
until => undefined
}
},
?assertEqual(
#{
current_generation => 42,
prototype => {emqx_ds_storage_reference, #{}},
?GEN_KEY(41) => #{
module => emqx_ds_storage_reference,
data => {schema},
cf_names => ["emqx_ds_storage_reference41"],
created_at => 12345,
since => 0,
until => 123456
},
?GEN_KEY(42) => #{
module => emqx_ds_storage_reference,
data => {schema},
cf_names => ["emqx_ds_storage_reference42"],
created_at => 54321,
since => 123456,
until => undefined
}
},
deserialize_schema(?ROCKSDB_SCHEMA_KEY("v1"), term_to_binary(SchemaV1))
).
-endif.
-undef(ROCKSDB_SCHEMA_KEY).