14
14
15
15
use std:: collections:: hash_map:: Entry ;
16
16
use std:: collections:: HashMap ;
17
+ use std:: collections:: HashSet ;
17
18
use std:: time:: Duration ;
18
19
19
20
use databend_common_base:: base:: escape_for_key;
@@ -139,7 +140,7 @@ fn map_condition(k: &str, seq: MatchSeq) -> TxnCondition {
139
140
}
140
141
}
141
142
142
- struct NodeInfoSnapshot {
143
+ pub struct NodeInfoSnapshot {
143
144
node_seq : u64 ,
144
145
cluster_seq : u64 ,
145
146
node_info : NodeInfo ,
@@ -1998,7 +1999,7 @@ impl WarehouseApi for WarehouseMgr {
1998
1999
}
1999
2000
2000
2001
for _idx in 0 ..10 {
2001
- let mut nodes = nodes . clone ( ) ;
2002
+ let mut removed_nodes = HashSet :: new ( ) ;
2002
2003
let mut drop_cluster_node_txn = TxnRequest :: default ( ) ;
2003
2004
2004
2005
let mut warehouse_snapshot = self . warehouse_snapshot ( warehouse) . await ?;
@@ -2009,11 +2010,11 @@ impl WarehouseApi for WarehouseMgr {
2009
2010
warehouse
2010
2011
) ) ) ,
2011
2012
WarehouseInfo :: SystemManaged ( mut info) => {
2012
- for ( cluster , nodes) in & nodes {
2013
- let Some ( cluster) = info. clusters . get_mut ( cluster ) else {
2013
+ for ( cluster_id , nodes) in & nodes {
2014
+ let Some ( cluster) = info. clusters . get_mut ( cluster_id ) else {
2014
2015
return Err ( ErrorCode :: WarehouseClusterNotExists ( format ! (
2015
2016
"Warehouse cluster {:?}.{:?} not exists" ,
2016
- warehouse, cluster
2017
+ warehouse, cluster_id
2017
2018
) ) ) ;
2018
2019
} ;
2019
2020
@@ -2024,14 +2025,7 @@ impl WarehouseApi for WarehouseMgr {
2024
2025
) ) ) ;
2025
2026
}
2026
2027
2027
- for remove_node in nodes {
2028
- if cluster. nodes . remove_first ( remove_node) . is_none ( ) {
2029
- return Err ( ErrorCode :: ClusterUnknownNode ( format ! (
2030
- "Warehouse cluster {:?}.{:?} unknown node {:?}" ,
2031
- warehouse, cluster, remove_node
2032
- ) ) ) ;
2033
- }
2034
- }
2028
+ removed_nodes = info. remove_nodes ( cluster_id, nodes, & warehouse_snapshot. snapshot_nodes ) ?;
2035
2029
}
2036
2030
2037
2031
@@ -2070,22 +2064,17 @@ impl WarehouseApi for WarehouseMgr {
2070
2064
MatchSeq :: Exact ( node_snapshot. cluster_seq ) ,
2071
2065
) ) ;
2072
2066
2073
- if let Some ( v) = nodes. get_mut ( & node_snapshot. node_info . cluster_id ) {
2074
- let runtime_node_group = node_snapshot. node_info . runtime_node_group . clone ( ) ;
2075
- if v. remove_first ( & SelectedNode :: Random ( runtime_node_group) )
2076
- . is_some ( )
2077
- {
2078
- let node = node_snapshot. node_info . leave_warehouse ( ) ;
2079
-
2080
- drop_cluster_node_txn
2081
- . if_then
2082
- . push ( TxnOp :: delete ( cluster_node_key) ) ;
2083
- drop_cluster_node_txn. if_then . push ( TxnOp :: put_with_ttl (
2084
- node_key,
2085
- serde_json:: to_vec ( & node) ?,
2086
- Some ( self . lift_time * 4 ) ,
2087
- ) ) ;
2088
- }
2067
+ if removed_nodes. contains ( & node_snapshot. node_info . id ) {
2068
+ let node = node_snapshot. node_info . leave_warehouse ( ) ;
2069
+
2070
+ drop_cluster_node_txn
2071
+ . if_then
2072
+ . push ( TxnOp :: delete ( cluster_node_key) ) ;
2073
+ drop_cluster_node_txn. if_then . push ( TxnOp :: put_with_ttl (
2074
+ node_key,
2075
+ serde_json:: to_vec ( & node) ?,
2076
+ Some ( self . lift_time * 4 ) ,
2077
+ ) ) ;
2089
2078
}
2090
2079
}
2091
2080
@@ -2211,6 +2200,110 @@ impl WarehouseApi for WarehouseMgr {
2211
2200
}
2212
2201
}
2213
2202
2203
+ impl SystemManagedWarehouse {
2204
+ pub fn remove_nodes (
2205
+ & mut self ,
2206
+ cluster_id : & String ,
2207
+ unassign : & [ SelectedNode ] ,
2208
+ nodes : & [ NodeInfoSnapshot ] ,
2209
+ ) -> Result < HashSet < String > > {
2210
+ let mut final_removed_nodes = HashSet :: new ( ) ;
2211
+ let mut match_any = Vec :: with_capacity ( unassign. len ( ) ) ;
2212
+ let mut match_node_group = Vec :: with_capacity ( unassign. len ( ) ) ;
2213
+
2214
+ let Some ( cluster) = self . clusters . get_mut ( cluster_id) else {
2215
+ unreachable ! ( )
2216
+ } ;
2217
+
2218
+ // 1. assign node group == unassign node group
2219
+ for node in unassign {
2220
+ if cluster. nodes . remove_first ( node) . is_none ( ) {
2221
+ match node {
2222
+ SelectedNode :: Random ( None ) => {
2223
+ match_any. push ( node) ;
2224
+ }
2225
+ SelectedNode :: Random ( Some ( node) ) => {
2226
+ match_node_group. push ( Some ( node. clone ( ) ) ) ;
2227
+ }
2228
+ }
2229
+
2230
+ continue ;
2231
+ }
2232
+
2233
+ for node_snapshot in nodes {
2234
+ if & node_snapshot. node_info . cluster_id != cluster_id {
2235
+ continue ;
2236
+ }
2237
+
2238
+ match ( & node, & node_snapshot. node_info . runtime_node_group ) {
2239
+ ( SelectedNode :: Random ( None ) , None ) => {
2240
+ if !final_removed_nodes. contains ( & node_snapshot. node_info . id ) {
2241
+ final_removed_nodes. insert ( node_snapshot. node_info . id . clone ( ) ) ;
2242
+ break ;
2243
+ }
2244
+ }
2245
+ ( SelectedNode :: Random ( Some ( left) ) , Some ( right) ) if left == right => {
2246
+ if !final_removed_nodes. contains ( & node_snapshot. node_info . id ) {
2247
+ final_removed_nodes. insert ( node_snapshot. node_info . id . clone ( ) ) ;
2248
+ break ;
2249
+ }
2250
+ }
2251
+ _ => {
2252
+ continue ;
2253
+ }
2254
+ }
2255
+ }
2256
+ }
2257
+
2258
+ // 2. unassign Some(node group), assign None
2259
+ ' match_node_group: for node_group in match_node_group {
2260
+ for node_snapshot in nodes {
2261
+ if & node_snapshot. node_info . cluster_id != cluster_id {
2262
+ continue ;
2263
+ }
2264
+
2265
+ if node_snapshot. node_info . node_group == node_group
2266
+ && !final_removed_nodes. contains ( & node_snapshot. node_info . id )
2267
+ {
2268
+ final_removed_nodes. insert ( node_snapshot. node_info . id . clone ( ) ) ;
2269
+ cluster. nodes . remove_first ( & SelectedNode :: Random (
2270
+ node_snapshot. node_info . runtime_node_group . clone ( ) ,
2271
+ ) ) ;
2272
+ continue ' match_node_group;
2273
+ }
2274
+ }
2275
+
2276
+ return Err ( ErrorCode :: ClusterUnknownNode ( format ! (
2277
+ "Cannot found {:?} node group node in {:?}" ,
2278
+ node_group, cluster
2279
+ ) ) ) ;
2280
+ }
2281
+
2282
+ // 3. assign Some(node group) and unassign None
2283
+ ' match_any: for _index in 0 ..match_any. len ( ) {
2284
+ for node_snapshot in nodes {
2285
+ if & node_snapshot. node_info . cluster_id != cluster_id {
2286
+ continue ;
2287
+ }
2288
+
2289
+ if !final_removed_nodes. contains ( & node_snapshot. node_info . id ) {
2290
+ final_removed_nodes. insert ( node_snapshot. node_info . id . clone ( ) ) ;
2291
+ cluster. nodes . remove_first ( & SelectedNode :: Random (
2292
+ node_snapshot. node_info . runtime_node_group . clone ( ) ,
2293
+ ) ) ;
2294
+ continue ' match_any;
2295
+ }
2296
+ }
2297
+
2298
+ return Err ( ErrorCode :: ClusterUnknownNode (
2299
+ "Cannot unassign empty warehouse cluster" ,
2300
+ ) ) ;
2301
+ }
2302
+
2303
+ Ok ( final_removed_nodes)
2304
+ }
2305
+ }
2306
+
2214
2307
/// Build an error indicating that databend-meta responded with an unexpected response,
2215
2308
/// while expecting a TxnGetResponse.
2216
2309
fn invalid_get_resp ( resp : Option < & TxnOpResponse > ) -> MetaError {
0 commit comments