github.com/dbernstein1/tyk@v2.9.0-beta9-dl-apic+incompatible/gateway/rpc_storage_handler.go (about) 1 package gateway 2 3 import ( 4 "strconv" 5 "strings" 6 "time" 7 8 cache "github.com/pmylund/go-cache" 9 10 "github.com/TykTechnologies/tyk/rpc" 11 12 "github.com/garyburd/redigo/redis" 13 14 "github.com/TykTechnologies/tyk/config" 15 "github.com/TykTechnologies/tyk/storage" 16 17 "github.com/sirupsen/logrus" 18 ) 19 20 type InboundData struct { 21 KeyName string 22 Value string 23 SessionState string 24 Timeout int64 25 Per int64 26 Expire int64 27 } 28 29 type DefRequest struct { 30 OrgId string 31 Tags []string 32 } 33 34 type KeysValuesPair struct { 35 Keys []string 36 Values []string 37 } 38 39 type GroupLoginRequest struct { 40 UserKey string 41 GroupID string 42 } 43 44 type GroupKeySpaceRequest struct { 45 OrgID string 46 GroupID string 47 } 48 49 var ( 50 dispatcherFuncs = map[string]interface{}{ 51 "Login": func(clientAddr, userKey string) bool { 52 return false 53 }, 54 "LoginWithGroup": func(clientAddr string, groupData *GroupLoginRequest) bool { 55 return false 56 }, 57 "GetKey": func(keyName string) (string, error) { 58 return "", nil 59 }, 60 "SetKey": func(ibd *InboundData) error { 61 return nil 62 }, 63 "GetExp": func(keyName string) (int64, error) { 64 return 0, nil 65 }, 66 "GetKeys": func(keyName string) ([]string, error) { 67 return nil, nil 68 }, 69 "DeleteKey": func(keyName string) (bool, error) { 70 return true, nil 71 }, 72 "DeleteRawKey": func(keyName string) (bool, error) { 73 return true, nil 74 }, 75 "GetKeysAndValues": func(searchString string) (*KeysValuesPair, error) { 76 return nil, nil 77 }, 78 "GetKeysAndValuesWithFilter": func(searchString string) (*KeysValuesPair, error) { 79 return nil, nil 80 }, 81 "DeleteKeys": func(keys []string) (bool, error) { 82 return true, nil 83 }, 84 "Decrement": func(keyName string) error { 85 return nil 86 }, 87 "IncrememntWithExpire": func(ibd *InboundData) (int64, error) { 88 return 0, nil 89 }, 90 "AppendToSet": func(ibd *InboundData) error { 91 return nil 92 }, 93 "SetRollingWindow": func(ibd *InboundData) (int, error) { 94 return 0, nil 95 }, 96 "GetApiDefinitions": func(dr *DefRequest) (string, error) { 97 return "", nil 98 }, 99 "GetPolicies": func(orgId string) (string, error) { 100 return "", nil 101 }, 102 "PurgeAnalyticsData": func(data string) error { 103 return nil 104 }, 105 "CheckReload": func(clientAddr, orgId string) (bool, error) { 106 return false, nil 107 }, 108 "GetKeySpaceUpdate": func(clientAddr, orgId string) ([]string, error) { 109 return nil, nil 110 }, 111 "GetGroupKeySpaceUpdate": func(clientAddr string, groupData *GroupKeySpaceRequest) ([]string, error) { 112 return nil, nil 113 }, 114 "Ping": func() bool { 115 return false 116 }, 117 } 118 ) 119 120 // RPCStorageHandler is a storage manager that uses the redis database. 121 type RPCStorageHandler struct { 122 KeyPrefix string 123 HashKeys bool 124 SuppressRegister bool 125 } 126 127 var RPCGlobalCache = cache.New(30*time.Second, 15*time.Second) 128 129 // Connect will establish a connection to the RPC 130 func (r *RPCStorageHandler) Connect() bool { 131 slaveOptions := config.Global().SlaveOptions 132 rpcConfig := rpc.Config{ 133 UseSSL: slaveOptions.UseSSL, 134 SSLInsecureSkipVerify: slaveOptions.SSLInsecureSkipVerify, 135 ConnectionString: slaveOptions.ConnectionString, 136 RPCKey: slaveOptions.RPCKey, 137 APIKey: slaveOptions.APIKey, 138 GroupID: slaveOptions.GroupID, 139 CallTimeout: slaveOptions.CallTimeout, 140 PingTimeout: slaveOptions.PingTimeout, 141 RPCPoolSize: slaveOptions.RPCPoolSize, 142 } 143 144 return rpc.Connect( 145 rpcConfig, 146 r.SuppressRegister, 147 dispatcherFuncs, 148 func(userKey string, groupID string) interface{} { 149 return GroupLoginRequest{ 150 UserKey: userKey, 151 GroupID: groupID, 152 } 153 }, 154 func() { 155 reloadURLStructure(nil) 156 }, 157 doReload, 158 ) 159 } 160 161 func (r *RPCStorageHandler) hashKey(in string) string { 162 if !r.HashKeys { 163 // Not hashing? Return the raw key 164 return in 165 } 166 return storage.HashStr(in) 167 } 168 169 func (r *RPCStorageHandler) fixKey(keyName string) string { 170 setKeyName := r.KeyPrefix + r.hashKey(keyName) 171 172 log.Debug("Input key was: ", setKeyName) 173 174 return setKeyName 175 } 176 177 func (r *RPCStorageHandler) cleanKey(keyName string) string { 178 setKeyName := strings.Replace(keyName, r.KeyPrefix, "", 1) 179 return setKeyName 180 } 181 182 // GetKey will retrieve a key from the database 183 func (r *RPCStorageHandler) GetKey(keyName string) (string, error) { 184 start := time.Now() // get current time 185 log.Debug("[STORE] Getting WAS: ", keyName) 186 log.Debug("[STORE] Getting: ", r.fixKey(keyName)) 187 188 value, err := r.GetRawKey(r.fixKey(keyName)) 189 190 elapsed := time.Since(start) 191 log.Debug("GetKey took ", elapsed) 192 193 return value, err 194 } 195 196 func (r *RPCStorageHandler) GetRawKey(keyName string) (string, error) { 197 // Check the cache first 198 if config.Global().SlaveOptions.EnableRPCCache { 199 log.Debug("Using cache for: ", keyName) 200 cachedVal, found := RPCGlobalCache.Get(keyName) 201 log.Debug("--> Found? ", found) 202 if found { 203 return cachedVal.(string), nil 204 } 205 } 206 207 value, err := rpc.FuncClientSingleton("GetKey", keyName) 208 if err != nil { 209 rpc.EmitErrorEventKv( 210 rpc.FuncClientSingletonCall, 211 "GetKey", 212 err, 213 map[string]string{ 214 "keyName": keyName, 215 }, 216 ) 217 if r.IsAccessError(err) { 218 if rpc.Login() { 219 return r.GetRawKey(keyName) 220 } 221 } 222 log.Debug("Error trying to get value:", err) 223 return "", storage.ErrKeyNotFound 224 } 225 if config.Global().SlaveOptions.EnableRPCCache { 226 // Cache key 227 RPCGlobalCache.Set(keyName, value, cache.DefaultExpiration) 228 } 229 //return hash key without prefix so it doesnt get double prefixed in redis 230 return value.(string), nil 231 } 232 233 func (r *RPCStorageHandler) GetExp(keyName string) (int64, error) { 234 log.Debug("GetExp called") 235 value, err := rpc.FuncClientSingleton("GetExp", r.fixKey(keyName)) 236 if err != nil { 237 rpc.EmitErrorEventKv( 238 rpc.FuncClientSingletonCall, 239 "GetExp", 240 err, 241 map[string]string{ 242 "keyName": keyName, 243 "fixedKeyName": r.fixKey(keyName), 244 }, 245 ) 246 if r.IsAccessError(err) { 247 if rpc.Login() { 248 return r.GetExp(keyName) 249 } 250 } 251 log.Error("Error trying to get TTL: ", err) 252 return 0, storage.ErrKeyNotFound 253 } 254 return value.(int64), nil 255 } 256 257 func (r *RPCStorageHandler) SetExp(keyName string, timeout int64) error { 258 log.Error("RPCStorageHandler.SetExp - Not Implemented") 259 return nil 260 } 261 262 // SetKey will create (or update) a key value in the store 263 func (r *RPCStorageHandler) SetKey(keyName, session string, timeout int64) error { 264 start := time.Now() // get current time 265 ibd := InboundData{ 266 KeyName: r.fixKey(keyName), 267 SessionState: session, 268 Timeout: timeout, 269 } 270 271 _, err := rpc.FuncClientSingleton("SetKey", ibd) 272 if err != nil { 273 rpc.EmitErrorEventKv( 274 rpc.FuncClientSingletonCall, 275 "SetKey", 276 err, 277 map[string]string{ 278 "keyName": keyName, 279 "fixedKeyName": ibd.KeyName, 280 }, 281 ) 282 283 if r.IsAccessError(err) { 284 if rpc.Login() { 285 return r.SetKey(keyName, session, timeout) 286 } 287 } 288 289 log.Debug("Error trying to set value:", err) 290 return err 291 } 292 293 elapsed := time.Since(start) 294 log.Debug("SetKey took ", elapsed) 295 return nil 296 297 } 298 299 func (r *RPCStorageHandler) SetRawKey(keyName, session string, timeout int64) error { 300 return nil 301 } 302 303 // Decrement will decrement a key in redis 304 func (r *RPCStorageHandler) Decrement(keyName string) { 305 log.Warning("Decrement called") 306 _, err := rpc.FuncClientSingleton("Decrement", keyName) 307 if err != nil { 308 rpc.EmitErrorEventKv( 309 rpc.FuncClientSingletonCall, 310 "Decrement", 311 err, 312 map[string]string{ 313 "keyName": keyName, 314 }, 315 ) 316 } 317 if r.IsAccessError(err) { 318 if rpc.Login() { 319 r.Decrement(keyName) 320 return 321 } 322 } 323 } 324 325 // IncrementWithExpire will increment a key in redis 326 func (r *RPCStorageHandler) IncrememntWithExpire(keyName string, expire int64) int64 { 327 328 ibd := InboundData{ 329 KeyName: keyName, 330 Expire: expire, 331 } 332 333 val, err := rpc.FuncClientSingleton("IncrememntWithExpire", ibd) 334 if err != nil { 335 rpc.EmitErrorEventKv( 336 rpc.FuncClientSingletonCall, 337 "IncrememntWithExpire", 338 err, 339 map[string]string{ 340 "keyName": keyName, 341 }, 342 ) 343 } 344 if r.IsAccessError(err) { 345 if rpc.Login() { 346 return r.IncrememntWithExpire(keyName, expire) 347 } 348 } 349 350 if val == nil { 351 log.Warning("RPC increment returned nil value, returning 0") 352 return 0 353 } 354 355 return val.(int64) 356 357 } 358 359 // GetKeys will return all keys according to the filter (filter is a prefix - e.g. tyk.keys.*) 360 func (r *RPCStorageHandler) GetKeys(filter string) []string { 361 log.Error("RPCStorageHandler.GetKeys - Not Implemented") 362 return nil 363 } 364 365 // GetKeysAndValuesWithFilter will return all keys and their values with a filter 366 func (r *RPCStorageHandler) GetKeysAndValuesWithFilter(filter string) map[string]string { 367 368 searchStr := r.KeyPrefix + r.hashKey(filter) + "*" 369 log.Debug("[STORE] Getting list by: ", searchStr) 370 371 kvPair, err := rpc.FuncClientSingleton("GetKeysAndValuesWithFilter", searchStr) 372 if err != nil { 373 rpc.EmitErrorEventKv( 374 rpc.FuncClientSingletonCall, 375 "GetKeysAndValuesWithFilter", 376 err, 377 map[string]string{ 378 "searchStr": searchStr, 379 }, 380 ) 381 382 if r.IsAccessError(err) { 383 if rpc.Login() { 384 return r.GetKeysAndValuesWithFilter(filter) 385 } 386 } 387 388 return nil 389 } 390 391 returnValues := make(map[string]string) 392 393 for i, v := range kvPair.(*KeysValuesPair).Keys { 394 returnValues[r.cleanKey(v)] = kvPair.(*KeysValuesPair).Values[i] 395 } 396 397 return returnValues 398 } 399 400 // GetKeysAndValues will return all keys and their values - not to be used lightly 401 func (r *RPCStorageHandler) GetKeysAndValues() map[string]string { 402 403 searchStr := r.KeyPrefix + "*" 404 405 kvPair, err := rpc.FuncClientSingleton("GetKeysAndValues", searchStr) 406 if err != nil { 407 rpc.EmitErrorEvent(rpc.FuncClientSingletonCall, "GetKeysAndValues", err) 408 409 if r.IsAccessError(err) { 410 if rpc.Login() { 411 return r.GetKeysAndValues() 412 } 413 } 414 415 return nil 416 } 417 418 returnValues := make(map[string]string) 419 for i, v := range kvPair.(*KeysValuesPair).Keys { 420 returnValues[r.cleanKey(v)] = kvPair.(*KeysValuesPair).Values[i] 421 } 422 423 return returnValues 424 425 } 426 427 // DeleteKey will remove a key from the database 428 func (r *RPCStorageHandler) DeleteKey(keyName string) bool { 429 430 log.Debug("DEL Key was: ", keyName) 431 log.Debug("DEL Key became: ", r.fixKey(keyName)) 432 ok, err := rpc.FuncClientSingleton("DeleteKey", r.fixKey(keyName)) 433 if err != nil { 434 rpc.EmitErrorEventKv( 435 rpc.FuncClientSingletonCall, 436 "DeleteKey", 437 err, 438 map[string]string{ 439 "keyName": keyName, 440 "fixedKeyName": r.fixKey(keyName), 441 }, 442 ) 443 444 if r.IsAccessError(err) { 445 if rpc.Login() { 446 return r.DeleteKey(keyName) 447 } 448 } 449 } 450 451 return ok == true 452 } 453 454 // DeleteKey will remove a key from the database without prefixing, assumes user knows what they are doing 455 func (r *RPCStorageHandler) DeleteRawKey(keyName string) bool { 456 ok, err := rpc.FuncClientSingleton("DeleteRawKey", keyName) 457 if err != nil { 458 rpc.EmitErrorEventKv( 459 rpc.FuncClientSingletonCall, 460 "DeleteRawKey", 461 err, 462 map[string]string{ 463 "keyName": keyName, 464 }, 465 ) 466 467 if r.IsAccessError(err) { 468 if rpc.Login() { 469 return r.DeleteRawKey(keyName) 470 } 471 } 472 } 473 474 return ok == true 475 } 476 477 // DeleteKeys will remove a group of keys in bulk 478 func (r *RPCStorageHandler) DeleteKeys(keys []string) bool { 479 if len(keys) > 0 { 480 asInterface := make([]string, len(keys)) 481 for i, v := range keys { 482 asInterface[i] = r.fixKey(v) 483 } 484 485 log.Debug("Deleting: ", asInterface) 486 ok, err := rpc.FuncClientSingleton("DeleteKeys", asInterface) 487 if err != nil { 488 rpc.EmitErrorEventKv( 489 rpc.FuncClientSingletonCall, 490 "DeleteKeys", 491 err, 492 map[string]string{ 493 "keys": strings.Join(keys, ","), 494 "asInterface": strings.Join(asInterface, ","), 495 }, 496 ) 497 498 if r.IsAccessError(err) { 499 if rpc.Login() { 500 return r.DeleteKeys(keys) 501 } 502 } 503 } 504 505 return ok == true 506 } 507 log.Debug("RPCStorageHandler called DEL - Nothing to delete") 508 return true 509 } 510 511 // StartPubSubHandler will listen for a signal and run the callback with the message 512 func (r *RPCStorageHandler) StartPubSubHandler(channel string, callback func(redis.Message)) error { 513 log.Warning("RPCStorageHandler.StartPubSubHandler - NO PUBSUB DEFINED") 514 return nil 515 } 516 517 func (r *RPCStorageHandler) Publish(channel, message string) error { 518 log.Warning("RPCStorageHandler.Publish - NO PUBSUB DEFINED") 519 return nil 520 } 521 522 func (r *RPCStorageHandler) GetAndDeleteSet(keyName string) []interface{} { 523 log.Error("RPCStorageHandler.GetAndDeleteSet - Not implemented, please disable your purger") 524 return nil 525 } 526 527 func (r *RPCStorageHandler) AppendToSet(keyName, value string) { 528 ibd := InboundData{ 529 KeyName: keyName, 530 Value: value, 531 } 532 533 _, err := rpc.FuncClientSingleton("AppendToSet", ibd) 534 if err != nil { 535 rpc.EmitErrorEventKv( 536 rpc.FuncClientSingletonCall, 537 "AppendToSet", 538 err, 539 map[string]string{ 540 "keyName": keyName, 541 }, 542 ) 543 } 544 if r.IsAccessError(err) { 545 if rpc.Login() { 546 r.AppendToSet(keyName, value) 547 } 548 } 549 } 550 551 func (r *RPCStorageHandler) AppendToSetPipelined(key string, values []string) { 552 // just falls back to AppendToSet 553 // TODO: introduce new RPC method for pipelined operation 554 for _, val := range values { 555 r.AppendToSet(key, val) 556 } 557 } 558 559 // SetScrollingWindow is used in the rate limiter to handle rate limits fairly. 560 func (r *RPCStorageHandler) SetRollingWindow(keyName string, per int64, val string, pipeline bool) (int, []interface{}) { 561 start := time.Now() // get current time 562 ibd := InboundData{ 563 KeyName: keyName, 564 Per: per, 565 Expire: -1, 566 } 567 568 intVal, err := rpc.FuncClientSingleton("SetRollingWindow", ibd) 569 if err != nil { 570 rpc.EmitErrorEventKv( 571 rpc.FuncClientSingletonCall, 572 "SetRollingWindow", 573 err, 574 map[string]string{ 575 "keyName": keyName, 576 "per": strconv.Itoa(int(per)), 577 }, 578 ) 579 580 if r.IsAccessError(err) { 581 if rpc.Login() { 582 return r.SetRollingWindow(keyName, per, val, false) 583 } 584 } 585 } 586 587 elapsed := time.Since(start) 588 log.Debug("SetRollingWindow took ", elapsed) 589 590 if intVal == nil { 591 log.Warning("RPC Handler: SetRollingWindow() returned nil, returning 0") 592 return 0, nil 593 } 594 595 return intVal.(int), nil 596 597 } 598 599 func (r *RPCStorageHandler) GetRollingWindow(keyName string, per int64, pipeline bool) (int, []interface{}) { 600 log.Warning("Not Implemented!") 601 return 0, nil 602 } 603 604 func (r RPCStorageHandler) GetSet(keyName string) (map[string]string, error) { 605 log.Error("RPCStorageHandler.GetSet - Not implemented") 606 return nil, nil 607 } 608 609 func (r RPCStorageHandler) AddToSet(keyName, value string) { 610 log.Error("RPCStorageHandler.AddToSet - Not implemented") 611 } 612 613 func (r RPCStorageHandler) RemoveFromSet(keyName, value string) { 614 log.Error("RPCStorageHandler.RemoveFromSet - Not implemented") 615 } 616 617 func (r RPCStorageHandler) IsAccessError(err error) bool { 618 if err != nil { 619 return err.Error() == "Access Denied" 620 } 621 return false 622 } 623 624 // GetAPIDefinitions will pull API definitions from the RPC server 625 func (r *RPCStorageHandler) GetApiDefinitions(orgId string, tags []string) string { 626 dr := DefRequest{ 627 OrgId: orgId, 628 Tags: tags, 629 } 630 631 defString, err := rpc.FuncClientSingleton("GetApiDefinitions", dr) 632 if err != nil { 633 rpc.EmitErrorEventKv( 634 rpc.FuncClientSingletonCall, 635 "GetApiDefinitions", 636 err, 637 map[string]string{ 638 "orgId": orgId, 639 "tags": strings.Join(tags, ","), 640 }, 641 ) 642 643 if r.IsAccessError(err) { 644 if rpc.Login() { 645 return r.GetApiDefinitions(orgId, tags) 646 } 647 } 648 649 return "" 650 } 651 log.Debug("API Definitions retrieved") 652 653 if defString == nil { 654 log.Warning("RPC Handler: GetApiDefinitions() returned nil, returning empty string") 655 return "" 656 } 657 return defString.(string) 658 } 659 660 // GetPolicies will pull Policies from the RPC server 661 func (r *RPCStorageHandler) GetPolicies(orgId string) string { 662 defString, err := rpc.FuncClientSingleton("GetPolicies", orgId) 663 if err != nil { 664 rpc.EmitErrorEventKv( 665 rpc.FuncClientSingletonCall, 666 "GetPolicies", 667 err, 668 map[string]string{ 669 "orgId": orgId, 670 }, 671 ) 672 673 if r.IsAccessError(err) { 674 if rpc.Login() { 675 return r.GetPolicies(orgId) 676 } 677 } 678 679 return "" 680 } 681 682 if defString != nil { 683 return defString.(string) 684 } 685 return "" 686 } 687 688 // CheckForReload will start a long poll 689 func (r *RPCStorageHandler) CheckForReload(orgId string) { 690 log.Debug("[RPC STORE] Check Reload called...") 691 reload, err := rpc.FuncClientSingleton("CheckReload", orgId) 692 if err != nil { 693 rpc.EmitErrorEventKv( 694 rpc.FuncClientSingletonCall, 695 "CheckReload", 696 err, 697 map[string]string{ 698 "orgId": orgId, 699 }, 700 ) 701 if r.IsAccessError(err) { 702 log.Warning("[RPC STORE] CheckReload: Not logged in") 703 if rpc.Login() { 704 r.CheckForReload(orgId) 705 } 706 } else if !strings.Contains(err.Error(), "Cannot obtain response during") { 707 log.Warning("[RPC STORE] RPC Reload Checker encountered unexpected error: ", err) 708 } 709 710 time.Sleep(1 * time.Second) 711 } else if reload == true { 712 // Do the reload! 713 log.Warning("[RPC STORE] Received Reload instruction!") 714 go func() { 715 MainNotifier.Notify(Notification{Command: NoticeGroupReload}) 716 }() 717 } 718 } 719 720 func (r *RPCStorageHandler) StartRPCLoopCheck(orgId string) { 721 if config.Global().SlaveOptions.DisableKeySpaceSync { 722 return 723 } 724 725 log.Info("[RPC] Starting keyspace poller") 726 727 for { 728 r.CheckForKeyspaceChanges(orgId) 729 time.Sleep(10 * time.Second) 730 } 731 } 732 733 func (r *RPCStorageHandler) StartRPCKeepaliveWatcher() { 734 log.WithFields(logrus.Fields{ 735 "prefix": "RPC Conn Mgr", 736 }).Info("[RPC Conn Mgr] Starting keepalive watcher...") 737 for { 738 739 if err := r.SetKey("0000", "0000", 10); err != nil { 740 log.WithError(err).WithFields(logrus.Fields{ 741 "prefix": "RPC Conn Mgr", 742 }).Info("Can't connect to RPC layer") 743 744 if r.IsAccessError(err) { 745 if rpc.Login() { 746 continue 747 } 748 } 749 750 if strings.Contains(err.Error(), "Cannot obtain response during timeout") { 751 continue 752 } 753 } 754 755 time.Sleep(10 * time.Second) 756 } 757 } 758 759 // CheckForKeyspaceChanges will poll for keysace changes 760 func (r *RPCStorageHandler) CheckForKeyspaceChanges(orgId string) { 761 log.Debug("Checking for keyspace changes...") 762 763 var keys interface{} 764 var err error 765 var funcName string 766 var req interface{} 767 768 reqData := map[string]string{} 769 if groupID := config.Global().SlaveOptions.GroupID; groupID == "" { 770 funcName = "GetKeySpaceUpdate" 771 req = orgId 772 reqData["orgId"] = orgId 773 } else { 774 funcName = "GetGroupKeySpaceUpdate" 775 req = GroupKeySpaceRequest{ 776 OrgID: orgId, 777 GroupID: groupID, 778 } 779 reqData["orgId"] = orgId 780 reqData["GroupID"] = groupID 781 } 782 783 keys, err = rpc.FuncClientSingleton(funcName, req) 784 if err != nil { 785 rpc.EmitErrorEventKv( 786 rpc.FuncClientSingletonCall, 787 funcName, 788 err, 789 reqData, 790 ) 791 if r.IsAccessError(err) { 792 if rpc.Login() { 793 r.CheckForKeyspaceChanges(orgId) 794 } 795 } 796 log.Warning("Keyspace warning: ", err) 797 return 798 } 799 800 if keys == nil { 801 log.Info("Keys returned nil object, skipping check") 802 return 803 } 804 805 if len(keys.([]string)) > 0 { 806 log.Info("Keyspace changes detected, updating local cache") 807 go r.ProcessKeySpaceChanges(keys.([]string)) 808 } 809 } 810 811 func getSessionAndCreate(keyName string, r *RPCStorageHandler) { 812 newKeyName := "apikey-" + storage.HashStr(keyName) 813 sessionString, err := r.GetRawKey(keyName) 814 if err != nil { 815 log.Error("Key not found in master - skipping") 816 } else { 817 handleAddKey(keyName, newKeyName[7:], sessionString, "-1") 818 } 819 } 820 821 func (r *RPCStorageHandler) ProcessKeySpaceChanges(keys []string) { 822 keysToReset := map[string]bool{} 823 824 for _, key := range keys { 825 splitKeys := strings.Split(key, ":") 826 if len(splitKeys) > 1 && splitKeys[1] == "resetQuota" { 827 keysToReset[splitKeys[0]] = true 828 } 829 } 830 831 for _, key := range keys { 832 splitKeys := strings.Split(key, ":") 833 _, resetQuota := keysToReset[splitKeys[0]] 834 if len(splitKeys) > 1 && splitKeys[1] == "hashed" { 835 key = splitKeys[0] 836 log.Info("--> removing cached (hashed) key: ", splitKeys[0]) 837 handleDeleteHashedKey(splitKeys[0], "", resetQuota) 838 getSessionAndCreate(splitKeys[0], r) 839 } else { 840 log.Info("--> removing cached key: ", key) 841 handleDeleteKey(key, "-1", resetQuota) 842 getSessionAndCreate(splitKeys[0], r) 843 } 844 SessionCache.Delete(key) 845 RPCGlobalCache.Delete(r.KeyPrefix + key) 846 } 847 // Notify rest of gateways in cluster to flush cache 848 n := Notification{ 849 Command: KeySpaceUpdateNotification, 850 Payload: strings.Join(keys, ","), 851 } 852 MainNotifier.Notify(n) 853 } 854 855 func (r *RPCStorageHandler) DeleteScanMatch(pattern string) bool { 856 log.Error("RPCStorageHandler.DeleteScanMatch - Not implemented") 857 return false 858 } 859 860 func (r *RPCStorageHandler) GetKeyPrefix() string { 861 log.Error("RPCStorageHandler.GetKeyPrefix - Not implemented") 862 return "" 863 } 864 865 func (r *RPCStorageHandler) AddToSortedSet(keyName, value string, score float64) { 866 log.Error("RPCStorageHandler.AddToSortedSet - Not implemented") 867 } 868 869 func (r *RPCStorageHandler) GetSortedSetRange(keyName, scoreFrom, scoreTo string) ([]string, []float64, error) { 870 log.Error("RPCStorageHandler.GetSortedSetRange - Not implemented") 871 return nil, nil, nil 872 } 873 874 func (r *RPCStorageHandler) RemoveSortedSetRange(keyName, scoreFrom, scoreTo string) error { 875 log.Error("RPCStorageHandler.RemoveSortedSetRange - Not implemented") 876 return nil 877 }