github.com/vicanso/pike@v1.0.1-0.20210630235453-9099e041f6ec/store/store.go (about) 1 // MIT License 2 3 // Copyright (c) 2021 Tree Xie 4 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 12 // The above copyright notice and this permission notice shall be included in all 13 // copies or substantial portions of the Software. 14 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 // SOFTWARE. 22 23 package store 24 25 import ( 26 "errors" 27 "net/url" 28 "sync" 29 "time" 30 31 "github.com/vicanso/hes" 32 "github.com/vicanso/pike/log" 33 "go.uber.org/zap" 34 ) 35 36 type Store interface { 37 // Get get data from store 38 Get(key []byte) (data []byte, err error) 39 // Set set data from store 40 Set(key []byte, data []byte, ttl time.Duration) (err error) 41 // Delete delete data from store 42 Delete(key []byte) (err error) 43 // Close close the store 44 Close() error 45 } 46 47 var ErrNotFound = errors.New("Not found") 48 49 var stores = sync.Map{} 50 51 var newStoreLock = sync.Mutex{} 52 53 // NewStore create a new store 54 func NewStore(storeURL string) (store Store, err error) { 55 // 保证new store只允许一个实例操作 56 newStoreLock.Lock() 57 defer newStoreLock.Unlock() 58 59 // 如果该store已存在,直接返回 60 store = GetStore(storeURL) 61 if store != nil { 62 return 63 } 64 65 // 初始化新的store 66 urlInfo, err := url.Parse(storeURL) 67 if err != nil { 68 return 69 } 70 switch urlInfo.Scheme { 71 case "badger": 72 store, err = newBadgerStore(urlInfo.Path) 73 if err != nil { 74 return 75 } 76 case "redis": 77 store, err = newRedisStore(storeURL) 78 if err != nil { 79 return 80 } 81 case "mongodb": 82 store, err = newMongoStore(storeURL) 83 if err != nil { 84 return 85 } 86 } 87 // 保存store 88 if store != nil { 89 stores.Store(storeURL, store) 90 } 91 return 92 } 93 94 // GetStore get store 95 func GetStore(storeURL string) Store { 96 value, ok := stores.Load(storeURL) 97 if !ok { 98 return nil 99 } 100 s, ok := value.(Store) 101 if !ok { 102 return nil 103 } 104 return s 105 } 106 107 // Close close stores 108 func Close() error { 109 he := &hes.Error{ 110 Message: "close stores fail", 111 } 112 stores.Range(func(_ interface{}, value interface{}) bool { 113 err := value.(Store).Close() 114 if err != nil { 115 he.Add(err) 116 } 117 return true 118 }) 119 if he.IsNotEmpty() { 120 // 由于close是在程序退出时调用,因此如果失败,则先输出出错日志再返回出错 121 log.Default().Error("close stores fail", 122 zap.Error(he), 123 ) 124 return he 125 } 126 return nil 127 }