github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/ctl/service/r2/store/kv/store.go (about) 1 // Copyright (c) 2017 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE 20 21 package kv 22 23 import ( 24 "errors" 25 "fmt" 26 27 "github.com/m3db/m3/src/ctl/service/r2" 28 r2store "github.com/m3db/m3/src/ctl/service/r2/store" 29 merrors "github.com/m3db/m3/src/metrics/errors" 30 "github.com/m3db/m3/src/metrics/rules" 31 "github.com/m3db/m3/src/metrics/rules/view" 32 "github.com/m3db/m3/src/metrics/rules/view/changes" 33 "github.com/m3db/m3/src/x/clock" 34 xerrors "github.com/m3db/m3/src/x/errors" 35 ) 36 37 type store struct { 38 nowFn clock.NowFn 39 opts StoreOptions 40 ruleStore rules.Store 41 updateHelper rules.RuleSetUpdateHelper 42 } 43 44 var errNilValidator = errors.New("no validator set on StoreOptions so validation is not applicable") 45 46 // NewStore returns a new service that knows how to talk to a kv backed r2 store. 47 func NewStore(rs rules.Store, opts StoreOptions) r2store.Store { 48 clockOpts := opts.ClockOptions() 49 updateHelper := rules.NewRuleSetUpdateHelper(opts.RuleUpdatePropagationDelay()) 50 return &store{ 51 nowFn: clockOpts.NowFn(), 52 opts: opts, 53 ruleStore: rs, 54 updateHelper: updateHelper, 55 } 56 } 57 58 func (s *store) FetchNamespaces() (view.Namespaces, error) { 59 nss, err := s.ruleStore.ReadNamespaces() 60 if err != nil { 61 return view.Namespaces{}, handleUpstreamError(err) 62 } 63 64 namespaces, err := nss.NamespacesView() 65 if err != nil { 66 return view.Namespaces{}, handleUpstreamError(err) 67 } 68 69 liveNss := make([]view.Namespace, 0, len(namespaces.Namespaces)) 70 for _, ns := range namespaces.Namespaces { 71 if !ns.Tombstoned { 72 liveNss = append(liveNss, ns) 73 } 74 } 75 76 return view.Namespaces{ 77 Version: namespaces.Version, 78 Namespaces: liveNss, 79 }, nil 80 } 81 82 func (s *store) ValidateRuleSet(rs view.RuleSet) error { 83 validator := s.opts.Validator() 84 // If no validator is set, then the validation functionality is not applicable. 85 if validator == nil { 86 return errNilValidator 87 } 88 89 return handleUpstreamError(validator.ValidateSnapshot(rs)) 90 } 91 92 func (s *store) UpdateRuleSet( 93 rsChanges changes.RuleSetChanges, 94 version int, 95 uOpts r2store.UpdateOptions, 96 ) (view.RuleSet, error) { 97 rs, err := s.ruleStore.ReadRuleSet(rsChanges.Namespace) 98 if err != nil { 99 return view.RuleSet{}, handleUpstreamError(err) 100 } 101 // If ruleset version fetched from KV matches the change set version, 102 // the check and set operation will succeed if the underlying 103 // KV version remains the same before the change is committed and fail otherwise. 104 // If the fetched version doesn't match, we will fail fast. 105 if version != rs.Version() { 106 return view.RuleSet{}, r2.NewConflictError(fmt.Sprintf( 107 "ruleset version mismatch: current version=%d, expected version=%d", 108 rs.Version(), 109 version, 110 )) 111 } 112 113 mutable := rs.ToMutableRuleSet().Clone() 114 err = mutable.ApplyRuleSetChanges(rsChanges, s.newUpdateMeta(uOpts)) 115 if err != nil { 116 return view.RuleSet{}, handleUpstreamError(err) 117 } 118 err = s.ruleStore.WriteRuleSet(mutable) 119 if err != nil { 120 return view.RuleSet{}, handleUpstreamError(err) 121 } 122 123 return s.FetchRuleSetSnapshot(rsChanges.Namespace) 124 } 125 126 func (s *store) CreateNamespace( 127 namespaceID string, 128 uOpts r2store.UpdateOptions, 129 ) (view.Namespace, error) { 130 nss, err := s.ruleStore.ReadNamespaces() 131 if err != nil { 132 return view.Namespace{}, handleUpstreamError(err) 133 } 134 135 meta := s.newUpdateMeta(uOpts) 136 revived, err := nss.AddNamespace(namespaceID, meta) 137 if err != nil { 138 return view.Namespace{}, handleUpstreamError(err) 139 } 140 141 rs := rules.NewEmptyRuleSet(namespaceID, meta) 142 if revived { 143 rawRs, err := s.ruleStore.ReadRuleSet(namespaceID) 144 if err != nil { 145 return view.Namespace{}, handleUpstreamError(err) 146 } 147 rs = rawRs.ToMutableRuleSet().Clone() 148 if err = rs.Revive(meta); err != nil { 149 return view.Namespace{}, handleUpstreamError(err) 150 } 151 } 152 153 if err = s.ruleStore.WriteAll(nss, rs); err != nil { 154 return view.Namespace{}, handleUpstreamError(err) 155 } 156 157 nss, err = s.ruleStore.ReadNamespaces() 158 if err != nil { 159 return view.Namespace{}, handleUpstreamError(err) 160 } 161 162 ns, err := nss.Namespace(namespaceID) 163 if err != nil { 164 return view.Namespace{}, r2.NewNotFoundError(fmt.Sprintf("namespace: %s does not exist", namespaceID)) 165 } 166 167 // Get the latest view of the namespace. 168 nsView, err := ns.NamespaceView(len(ns.Snapshots()) - 1) 169 if err != nil { 170 return view.Namespace{}, handleUpstreamError(err) 171 } 172 173 return nsView, nil 174 } 175 176 func (s *store) DeleteNamespace(namespaceID string, uOpts r2store.UpdateOptions) error { 177 nss, err := s.ruleStore.ReadNamespaces() 178 if err != nil { 179 return handleUpstreamError(err) 180 } 181 182 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 183 if err != nil { 184 return handleUpstreamError(err) 185 } 186 187 meta := s.newUpdateMeta(uOpts) 188 err = nss.DeleteNamespace(namespaceID, rs.Version(), meta) 189 if err != nil { 190 return handleUpstreamError(err) 191 } 192 193 mutable := rs.ToMutableRuleSet().Clone() 194 err = mutable.Delete(meta) 195 if err != nil { 196 return handleUpstreamError(err) 197 } 198 199 if err = s.ruleStore.WriteAll(nss, mutable); err != nil { 200 return handleUpstreamError(err) 201 } 202 203 return nil 204 } 205 206 func (s *store) FetchRuleSetSnapshot(namespaceID string) (view.RuleSet, error) { 207 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 208 if err != nil { 209 return view.RuleSet{}, handleUpstreamError(err) 210 } 211 return rs.Latest() 212 } 213 214 func (s *store) FetchMappingRule( 215 namespaceID string, 216 mappingRuleID string, 217 ) (view.MappingRule, error) { 218 ruleset, err := s.FetchRuleSetSnapshot(namespaceID) 219 if err != nil { 220 return view.MappingRule{}, err 221 } 222 223 for _, mr := range ruleset.MappingRules { 224 if mr.ID == mappingRuleID { 225 return mr, nil 226 } 227 } 228 229 return view.MappingRule{}, mappingRuleNotFoundError(namespaceID, mappingRuleID) 230 } 231 232 func (s *store) CreateMappingRule( 233 namespaceID string, 234 mrv view.MappingRule, 235 uOpts r2store.UpdateOptions, 236 ) (view.MappingRule, error) { 237 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 238 if err != nil { 239 return view.MappingRule{}, handleUpstreamError(err) 240 } 241 242 mutable := rs.ToMutableRuleSet().Clone() 243 newID, err := mutable.AddMappingRule(mrv, s.newUpdateMeta(uOpts)) 244 if err != nil { 245 return view.MappingRule{}, handleUpstreamError(err) 246 } 247 248 err = s.ruleStore.WriteRuleSet(mutable) 249 if err != nil { 250 return view.MappingRule{}, handleUpstreamError(err) 251 } 252 253 return s.FetchMappingRule(namespaceID, newID) 254 } 255 256 func (s *store) UpdateMappingRule( 257 namespaceID string, 258 mappingRuleID string, 259 mrv view.MappingRule, 260 uOpts r2store.UpdateOptions, 261 ) (view.MappingRule, error) { 262 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 263 if err != nil { 264 return view.MappingRule{}, handleUpstreamError(err) 265 } 266 267 mutable := rs.ToMutableRuleSet().Clone() 268 err = mutable.UpdateMappingRule(mrv, s.newUpdateMeta(uOpts)) 269 if err != nil { 270 return view.MappingRule{}, handleUpstreamError(err) 271 } 272 273 err = s.ruleStore.WriteRuleSet(mutable) 274 if err != nil { 275 return view.MappingRule{}, handleUpstreamError(err) 276 } 277 278 return s.FetchMappingRule(namespaceID, mappingRuleID) 279 } 280 281 func (s *store) DeleteMappingRule( 282 namespaceID string, 283 mappingRuleID string, 284 uOpts r2store.UpdateOptions, 285 ) error { 286 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 287 if err != nil { 288 return handleUpstreamError(err) 289 } 290 291 mutable := rs.ToMutableRuleSet().Clone() 292 err = mutable.DeleteMappingRule(mappingRuleID, s.newUpdateMeta(uOpts)) 293 if err != nil { 294 return handleUpstreamError(err) 295 } 296 297 err = s.ruleStore.WriteRuleSet(mutable) 298 if err != nil { 299 return handleUpstreamError(err) 300 } 301 302 return nil 303 } 304 305 func (s *store) FetchMappingRuleHistory( 306 namespaceID string, 307 mappingRuleID string, 308 ) ([]view.MappingRule, error) { 309 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 310 if err != nil { 311 return nil, handleUpstreamError(err) 312 } 313 314 mrs, err := rs.MappingRules() 315 if err != nil { 316 return nil, handleUpstreamError(err) 317 } 318 319 for _, mappings := range mrs { 320 if len(mappings) > 0 && mappings[0].ID == mappingRuleID { 321 return mappings, nil 322 } 323 } 324 325 return nil, mappingRuleNotFoundError(namespaceID, mappingRuleID) 326 } 327 328 func (s *store) FetchRollupRule( 329 namespaceID string, 330 rollupRuleID string, 331 ) (view.RollupRule, error) { 332 ruleset, err := s.FetchRuleSetSnapshot(namespaceID) 333 if err != nil { 334 return view.RollupRule{}, handleUpstreamError(err) 335 } 336 337 for _, rr := range ruleset.RollupRules { 338 if rr.ID == rollupRuleID { 339 return rr, nil 340 } 341 } 342 343 return view.RollupRule{}, rollupRuleNotFoundError(namespaceID, rollupRuleID) 344 } 345 346 func (s *store) CreateRollupRule( 347 namespaceID string, 348 rrv view.RollupRule, 349 uOpts r2store.UpdateOptions, 350 ) (view.RollupRule, error) { 351 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 352 if err != nil { 353 return view.RollupRule{}, handleUpstreamError(err) 354 } 355 356 mutable := rs.ToMutableRuleSet().Clone() 357 newID, err := mutable.AddRollupRule(rrv, s.newUpdateMeta(uOpts)) 358 if err != nil { 359 return view.RollupRule{}, handleUpstreamError(err) 360 } 361 362 err = s.ruleStore.WriteRuleSet(mutable) 363 if err != nil { 364 return view.RollupRule{}, handleUpstreamError(err) 365 } 366 367 return s.FetchRollupRule(namespaceID, newID) 368 } 369 370 func (s *store) UpdateRollupRule( 371 namespaceID, 372 rollupRuleID string, 373 rrv view.RollupRule, 374 uOpts r2store.UpdateOptions, 375 ) (view.RollupRule, error) { 376 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 377 if err != nil { 378 return view.RollupRule{}, handleUpstreamError(err) 379 } 380 381 mutable := rs.ToMutableRuleSet().Clone() 382 err = mutable.UpdateRollupRule(rrv, s.newUpdateMeta(uOpts)) 383 if err != nil { 384 return view.RollupRule{}, handleUpstreamError(err) 385 } 386 387 err = s.ruleStore.WriteRuleSet(mutable) 388 if err != nil { 389 return view.RollupRule{}, handleUpstreamError(err) 390 } 391 392 return s.FetchRollupRule(namespaceID, rollupRuleID) 393 } 394 395 func (s *store) DeleteRollupRule( 396 namespaceID string, 397 rollupRuleID string, 398 uOpts r2store.UpdateOptions, 399 ) error { 400 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 401 if err != nil { 402 return handleUpstreamError(err) 403 } 404 405 mutable := rs.ToMutableRuleSet().Clone() 406 err = mutable.DeleteRollupRule(rollupRuleID, s.newUpdateMeta(uOpts)) 407 if err != nil { 408 return handleUpstreamError(err) 409 } 410 411 err = s.ruleStore.WriteRuleSet(mutable) 412 if err != nil { 413 return handleUpstreamError(err) 414 } 415 416 return nil 417 } 418 419 func (s *store) FetchRollupRuleHistory( 420 namespaceID string, 421 rollupRuleID string, 422 ) ([]view.RollupRule, error) { 423 rs, err := s.ruleStore.ReadRuleSet(namespaceID) 424 if err != nil { 425 return nil, handleUpstreamError(err) 426 } 427 428 rrs, err := rs.RollupRules() 429 if err != nil { 430 return nil, handleUpstreamError(err) 431 } 432 433 for _, rollups := range rrs { 434 if len(rollups) > 0 && rollups[0].ID == rollupRuleID { 435 return rollups, nil 436 } 437 } 438 439 return nil, rollupRuleNotFoundError(namespaceID, rollupRuleID) 440 } 441 442 func (s *store) Close() { s.ruleStore.Close() } 443 444 func (s *store) newUpdateMeta(uOpts r2store.UpdateOptions) rules.UpdateMetadata { 445 return s.updateHelper.NewUpdateMetadata(s.nowFn().UnixNano(), uOpts.Author()) 446 } 447 448 func mappingRuleNotFoundError(namespaceID, mappingRuleID string) error { 449 return r2.NewNotFoundError( 450 fmt.Sprintf("mapping rule: %s doesn't exist in Namespace: %s", 451 mappingRuleID, 452 namespaceID, 453 ), 454 ) 455 } 456 457 func rollupRuleNotFoundError(namespaceID, rollupRuleID string) error { 458 return r2.NewNotFoundError( 459 fmt.Sprintf("rollup rule: %s doesn't exist in Namespace: %s", 460 rollupRuleID, 461 namespaceID, 462 ), 463 ) 464 } 465 466 func handleUpstreamError(err error) error { 467 if err == nil { 468 return nil 469 } 470 471 // If this is a contained error, extracts the inner error. 472 if e := xerrors.InnerError(err); e != nil { 473 err = e 474 } 475 476 switch err.(type) { 477 case merrors.InvalidInputError, merrors.StaleDataError: 478 return r2.NewConflictError(err.Error()) 479 case merrors.ValidationError: 480 return r2.NewBadInputError(err.Error()) 481 case merrors.NotFoundError: 482 return r2.NewNotFoundError(err.Error()) 483 default: 484 return r2.NewInternalError(err.Error()) 485 } 486 }