Skip to content

Commit 0fb42c7

Browse files
committed
MB-51458 do not truncate long dcp connection names if the version
...of the producer node is less than 6.6.5 or one of the following: 7.0.0, 7.0.1 Change-Id: I3f1c1ca63993c6e1f408a3ed9b76aa0d14efab85 Reviewed-on: https://review.couchbase.org/c/ns_server/+/172546 Well-Formed: Restriction Checker Well-Formed: Build Bot <[email protected]> Reviewed-by: Timofey Barmin <[email protected]> Tested-by: Artem Stemkovski <[email protected]>
1 parent e03a2c9 commit 0fb42c7

File tree

2 files changed

+136
-68
lines changed

2 files changed

+136
-68
lines changed

src/dcp_replicator.erl

Lines changed: 128 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -244,25 +244,43 @@ get_docs_estimate(Bucket, Partition, ConsumerNode) ->
244244
ns_memcached:get_dcp_docs_estimate(Bucket, Partition, Connection).
245245

246246
get_connection_name(ConsumerNode, ProducerNode, Bucket) ->
247-
ConsumerNodeList = atom_to_list(ConsumerNode),
248-
ProducerNodeList = atom_to_list(ProducerNode),
249-
CName = "replication:" ++ ProducerNodeList ++ "->" ++ ConsumerNodeList ++
250-
":" ++ Bucket,
247+
CName = "replication:" ++ atom_to_list(ProducerNode) ++ "->" ++
248+
atom_to_list(ConsumerNode) ++ ":" ++ Bucket,
251249

252250
case length(CName) =< ?MAX_DCP_CONNECTION_NAME of
253251
true ->
254252
CName;
255253
false ->
256-
%% Trim off the common prefix to shorten the names.
257-
{CNode, PNode} = trim_common_prefix(ConsumerNode, ProducerNode),
254+
case should_truncate_name(ProducerNode) of
255+
true ->
256+
get_truncated_connection_name(
257+
CName, ConsumerNode, ProducerNode, Bucket);
258+
false ->
259+
CName
260+
end
261+
end.
262+
263+
get_truncated_connection_name(LongName, ConsumerNode, ProducerNode, Bucket) ->
264+
%% Trim off the common prefix to shorten the names.
265+
{CNode, PNode} = trim_common_prefix(ConsumerNode, ProducerNode),
266+
267+
Hash = binary_to_list(base64:encode(crypto:hash(sha, LongName))),
268+
Bkt = string:slice(Bucket, 0, 60),
258269

259-
Hash = binary_to_list(base64:encode(crypto:hash(sha, CName))),
260-
Bkt = string:slice(Bucket, 0, 60),
270+
CName = "replication:" ++ PNode ++ "->" ++ CNode ++ ":" ++ Bkt ++
271+
":" ++ Hash,
272+
true = length(CName) =< ?MAX_DCP_CONNECTION_NAME,
273+
CName.
261274

262-
CName2 = "replication:" ++ PNode ++ "->" ++ CNode ++ ":" ++ Bkt ++
263-
":" ++ Hash,
264-
true = length(CName2) =< ?MAX_DCP_CONNECTION_NAME,
265-
CName2
275+
should_truncate_name(ProducerNode) ->
276+
case cluster_compat_mode:is_cluster_71() of
277+
true ->
278+
true;
279+
false ->
280+
Quirks = rebalance_quirks:get_quirks([ProducerNode]),
281+
not rebalance_quirks:is_enabled(
282+
dont_truncate_long_names,
283+
rebalance_quirks:get_node_quirks(ProducerNode, Quirks))
266284
end.
267285

268286
trim_common_prefix(Consumer, Producer) ->
@@ -347,59 +365,103 @@ maybe_shut_consumer(Reason, Consumer) ->
347365
end.
348366

349367
-ifdef(TEST).
350-
get_connection_name_test() ->
351-
352-
%% Connection name fits into the maximum allowed
353-
354-
NodeA = 'nodeA.eng.couchbase.com',
355-
NodeB = 'nodeB.eng.couchbase.com',
356-
BucketAB = "bucket1",
357-
ConnAB = get_connection_name(NodeA, NodeB, BucketAB),
358-
?assertEqual("replication:nodeB.eng.couchbase.com->"
359-
"nodeA.eng.couchbase.com:bucket1", ConnAB),
360-
?assertEqual(true, length(ConnAB) =< ?MAX_DCP_CONNECTION_NAME),
361-
362-
%% Test where the connection name, using the previous method, won't
363-
%% fit into the maximum allowed.
364-
365-
Node1 = "[email protected]."
366-
"couchbase-new-pxxxxxxx.svc",
367-
Node2 = "[email protected]."
368-
"couchbase-new-pxxxxxxx.svc",
369-
Bucket12 = "com.yyyyyy.digital.ms.shoppingcart.shoppingcart.1234567890"
370-
"12345678901234567890",
371-
Conn12 = get_connection_name(list_to_atom(Node1), list_to_atom(Node2),
372-
Bucket12),
373-
?assertEqual("replication:1.platform-couchbase-cluster.couchb->"
374-
"0.platform-couchbase-cluster.couchb:com.yyyyyy.digital.ms."
375-
"shoppingcart.shoppingcart.123456789012:"
376-
"TYFMH5ZD2gPLOaLgcuA2VijsZvc=", Conn12),
377-
378-
%% Test that the node names aren't shortened too much (note the only
379-
%% difference is the last character).
380-
381-
Node3 = "ManyManyManyManyCommonCharacters_ns_1@platform-couchbase-cluster"
382-
"-0000",
383-
Node4 = "ManyManyManyManyCommonCharacters_ns_1@platform-couchbase-cluster"
384-
"-0001",
368+
get_connection_name_test_() ->
385369
LongBucket = "travel-sample-with-a-very-very-very-very-long-bucket-name",
386-
Conn34 = get_connection_name(list_to_atom(Node3), list_to_atom(Node4),
387-
LongBucket),
388-
?assertEqual("replication:s_1@platform-couchbase-cluster-0001->"
389-
"s_1@platform-couchbase-cluster-0000:travel-sample-with-a-"
390-
"very-very-very-very-long-bucket-name:"
391-
"D/D56MpAKsDt/0yqg6IXKBEaIcY=", Conn34),
392-
393-
%% Test with unique node names but one is much longer than the other.
394-
395-
Node5 = "AShortNodeName",
396-
Node6 = "ManyManyManyManyCommonCharacters_ns_1@platform-couchbase-cluster"
397-
"-AndEvenMoreCharactersToMakeThisNodeNameLongEnoughToRequireIt"
398-
"ToBeShortened",
399-
Conn56 = get_connection_name(list_to_atom(Node5), list_to_atom(Node6),
400-
LongBucket),
401-
?assertEqual("replication:ManyManyManyManyCommonCharacters_ns->"
402-
"AShortNodeName:travel-sample-with-a-very-very-very-very-"
403-
"long-bucket-name:A3aPD1Sik+5ZIz43M6NNTGn9XFw=", Conn56).
404-
370+
ConsumerNode = list_to_atom(
371+
"ns_1@platform-couchbase-cluster-0000."
372+
"platform-couchbase-cluster.couchbase-new-pxxxxxxx.svc"),
373+
ProducerNode = list_to_atom(
374+
"ns_1@platform-couchbase-cluster-0001."
375+
"platform-couchbase-cluster.couchbase-new-pxxxxxxx.svc"),
376+
VeryLongBucket = "com.yyyyyy.digital.ms.shoppingcart."
377+
"shoppingcart.123456789012345678901234567890",
378+
TrimmedName =
379+
"replication:1.platform-couchbase-cluster.couchb->0.platform-couchbase"
380+
"-cluster.couchb:com.yyyyyy.digital.ms.shoppingcart.shoppingcart."
381+
"123456789012:TYFMH5ZD2gPLOaLgcuA2VijsZvc=",
382+
{foreach,
383+
fun () ->
384+
meck:new(cluster_compat_mode, [passthrough]),
385+
meck:new(rebalance_quirks, [passthrough]),
386+
meck:expect(cluster_compat_mode, is_cluster_71,
387+
fun () -> true end)
388+
end,
389+
fun (_) ->
390+
meck:unload(cluster_compat_mode),
391+
meck:unload(rebalance_quirks)
392+
end,
393+
[{"Connection name fits into the maximum allowed",
394+
fun () ->
395+
Conn = get_connection_name(
396+
'nodeA.eng.couchbase.com', 'nodeB.eng.couchbase.com',
397+
"bucket1"),
398+
?assertEqual("replication:nodeB.eng.couchbase.com->"
399+
"nodeA.eng.couchbase.com:bucket1", Conn),
400+
?assertEqual(true, length(Conn) =< ?MAX_DCP_CONNECTION_NAME)
401+
end},
402+
{"Connection name won't fit into the maximum allowed.",
403+
fun () ->
404+
?assertEqual(
405+
TrimmedName,
406+
get_connection_name(ConsumerNode, ProducerNode,
407+
VeryLongBucket))
408+
end},
409+
{"Connection name won't fit into the maximum allowed. Pre 7.1 "
410+
"Against the node that supports trimming",
411+
fun () ->
412+
meck:expect(cluster_compat_mode, is_cluster_71,
413+
fun () -> false end),
414+
meck:expect(rebalance_quirks, get_quirks,
415+
fun (_) -> [{ProducerNode, []}] end),
416+
?assertEqual(
417+
TrimmedName,
418+
get_connection_name(ConsumerNode, ProducerNode,
419+
VeryLongBucket))
420+
end},
421+
{"Connection name won't fit into the maximum allowed, but name trimming "
422+
"is not supported",
423+
fun () ->
424+
meck:expect(cluster_compat_mode, is_cluster_71,
425+
fun () -> false end),
426+
meck:expect(rebalance_quirks, get_quirks,
427+
fun (_) ->
428+
[{ProducerNode, [dont_truncate_long_names]}]
429+
end),
430+
Conn = get_connection_name(ConsumerNode, ProducerNode,
431+
VeryLongBucket),
432+
?assertEqual(
433+
"replication:[email protected]"
434+
"-couchbase-cluster.couchbase-new-pxxxxxxx.svc->ns_1@platform"
435+
"-couchbase-cluster-0000.platform-couchbase-cluster.couchbase"
436+
"-new-pxxxxxxx.svc:com.yyyyyy.digital.ms.shoppingcart."
437+
"shoppingcart.123456789012345678901234567890", Conn)
438+
end},
439+
{"Test that the node names aren't shortened too much (note the only "
440+
"difference is the last character).",
441+
fun () ->
442+
Node1 = "ManyManyManyManyCommonCharacters_ns_1@platform-"
443+
"couchbase-cluster-0000",
444+
Node2 = "ManyManyManyManyCommonCharacters_ns_1@platform-"
445+
"couchbase-cluster-0001",
446+
Conn = get_connection_name(
447+
list_to_atom(Node1), list_to_atom(Node2), LongBucket),
448+
?assertEqual(
449+
"replication:s_1@platform-couchbase-cluster-0001->"
450+
"s_1@platform-couchbase-cluster-0000:travel-sample-with-a-"
451+
"very-very-very-very-long-bucket-name:"
452+
"D/D56MpAKsDt/0yqg6IXKBEaIcY=", Conn)
453+
end},
454+
{"Test with unique node names but one is much longer than the other.",
455+
fun () ->
456+
Node1 = "AShortNodeName",
457+
Node2 = "ManyManyManyManyCommonCharacters_ns_1@platform-"
458+
"couchbase-cluster-AndEvenMoreCharactersToMakeThisNodeName"
459+
"LongEnoughToRequireItToBeShortened",
460+
Conn = get_connection_name(
461+
list_to_atom(Node1), list_to_atom(Node2), LongBucket),
462+
?assertEqual(
463+
"replication:ManyManyManyManyCommonCharacters_ns->"
464+
"AShortNodeName:travel-sample-with-a-very-very-very-very-"
465+
"long-bucket-name:A3aPD1Sik+5ZIz43M6NNTGn9XFw=", Conn)
466+
end}]}.
405467
-endif.

src/rebalance_quirks.erl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
-type quirk() :: takeover_via_orchestrator |
2020
disable_old_master |
2121
reset_replicas |
22-
trivial_moves.
22+
trivial_moves |
23+
dont_truncate_long_names.
2324

2425
%% APIs
2526
get_quirks(Nodes) ->
@@ -120,12 +121,17 @@ all_quirks() ->
120121
[takeover_via_orchestrator,
121122
disable_old_master,
122123
reset_replicas,
123-
trivial_moves].
124+
trivial_moves,
125+
dont_truncate_long_names].
124126

125127
quirks_for_version(Version) ->
126128
[Quirk || Quirk <- all_quirks(),
127129
is_quirk_required(Quirk, Version)].
128130

131+
is_quirk_required(dont_truncate_long_names, [7, 0, X]) when X < 2 ->
132+
true;
133+
is_quirk_required(dont_truncate_long_names, Version) ->
134+
Version < [6, 6, 5];
129135
is_quirk_required(takeover_via_orchestrator, Version) ->
130136
Version < [5, 1, 0];
131137
is_quirk_required(_, _) ->

0 commit comments

Comments
 (0)