go.temporal.io/server@v1.23.0/common/archiver/provider/provider.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 //go:generate mockgen -copyright_file ../../../LICENSE -package $GOPACKAGE -source $GOFILE -destination provider_mock.go 26 27 package provider 28 29 import ( 30 "errors" 31 "sync" 32 33 "go.temporal.io/server/common/archiver/gcloud" 34 35 "go.temporal.io/server/common/archiver" 36 "go.temporal.io/server/common/archiver/filestore" 37 "go.temporal.io/server/common/archiver/s3store" 38 "go.temporal.io/server/common/config" 39 ) 40 41 var ( 42 // ErrUnknownScheme is the error for unknown archiver scheme 43 ErrUnknownScheme = errors.New("unknown archiver scheme") 44 // ErrNotSupported is the error for not supported archiver implementation 45 ErrNotSupported = errors.New("archiver provider not supported") 46 // ErrBootstrapContainerNotFound is the error for unable to find the bootstrap container given serviceName 47 ErrBootstrapContainerNotFound = errors.New("unable to find bootstrap container for the given service name") 48 // ErrArchiverConfigNotFound is the error for unable to find the config for an archiver given scheme 49 ErrArchiverConfigNotFound = errors.New("unable to find archiver config for the given scheme") 50 // ErrBootstrapContainerAlreadyRegistered is the error for registering multiple containers for the same serviceName 51 ErrBootstrapContainerAlreadyRegistered = errors.New("bootstrap container has already been registered") 52 ) 53 54 type ( 55 // ArchiverProvider returns history or visibility archiver based on the scheme and serviceName. 56 // The archiver for each combination of scheme and serviceName will be created only once and cached. 57 ArchiverProvider interface { 58 RegisterBootstrapContainer( 59 serviceName string, 60 historyContainer *archiver.HistoryBootstrapContainer, 61 visibilityContainter *archiver.VisibilityBootstrapContainer, 62 ) error 63 GetHistoryArchiver(scheme, serviceName string) (archiver.HistoryArchiver, error) 64 GetVisibilityArchiver(scheme, serviceName string) (archiver.VisibilityArchiver, error) 65 } 66 67 archiverProvider struct { 68 sync.RWMutex 69 70 historyArchiverConfigs *config.HistoryArchiverProvider 71 visibilityArchiverConfigs *config.VisibilityArchiverProvider 72 73 // Key for the container is just serviceName 74 historyContainers map[string]*archiver.HistoryBootstrapContainer 75 visibilityContainers map[string]*archiver.VisibilityBootstrapContainer 76 77 // Key for the archiver is scheme + serviceName 78 historyArchivers map[string]archiver.HistoryArchiver 79 visibilityArchivers map[string]archiver.VisibilityArchiver 80 } 81 ) 82 83 // NewArchiverProvider returns a new Archiver provider 84 func NewArchiverProvider( 85 historyArchiverConfigs *config.HistoryArchiverProvider, 86 visibilityArchiverConfigs *config.VisibilityArchiverProvider, 87 ) ArchiverProvider { 88 return &archiverProvider{ 89 historyArchiverConfigs: historyArchiverConfigs, 90 visibilityArchiverConfigs: visibilityArchiverConfigs, 91 historyContainers: make(map[string]*archiver.HistoryBootstrapContainer), 92 visibilityContainers: make(map[string]*archiver.VisibilityBootstrapContainer), 93 historyArchivers: make(map[string]archiver.HistoryArchiver), 94 visibilityArchivers: make(map[string]archiver.VisibilityArchiver), 95 } 96 } 97 98 // RegisterBootstrapContainer stores the given bootstrap container given the serviceName 99 // The container should be registered when a service starts up and before GetArchiver() is ever called. 100 // Later calls to GetArchiver() will used the registered container to initialize new archivers. 101 // If the container for a service has already registered, and this method is invoked for that service again 102 // with an non-nil container, an error will be returned. 103 func (p *archiverProvider) RegisterBootstrapContainer( 104 serviceName string, 105 historyContainer *archiver.HistoryBootstrapContainer, 106 visibilityContainter *archiver.VisibilityBootstrapContainer, 107 ) error { 108 p.Lock() 109 defer p.Unlock() 110 111 if _, ok := p.historyContainers[serviceName]; ok && historyContainer != nil { 112 return ErrBootstrapContainerAlreadyRegistered 113 } 114 if _, ok := p.visibilityContainers[serviceName]; ok && visibilityContainter != nil { 115 return ErrBootstrapContainerAlreadyRegistered 116 } 117 118 if historyContainer != nil { 119 p.historyContainers[serviceName] = historyContainer 120 } 121 if visibilityContainter != nil { 122 p.visibilityContainers[serviceName] = visibilityContainter 123 } 124 return nil 125 } 126 127 func (p *archiverProvider) GetHistoryArchiver(scheme, serviceName string) (historyArchiver archiver.HistoryArchiver, err error) { 128 archiverKey := p.getArchiverKey(scheme, serviceName) 129 p.RLock() 130 if historyArchiver, ok := p.historyArchivers[archiverKey]; ok { 131 p.RUnlock() 132 return historyArchiver, nil 133 } 134 p.RUnlock() 135 136 container, ok := p.historyContainers[serviceName] 137 if !ok { 138 return nil, ErrBootstrapContainerNotFound 139 } 140 141 switch scheme { 142 case filestore.URIScheme: 143 if p.historyArchiverConfigs.Filestore == nil { 144 return nil, ErrArchiverConfigNotFound 145 } 146 historyArchiver, err = filestore.NewHistoryArchiver(container, p.historyArchiverConfigs.Filestore) 147 148 case gcloud.URIScheme: 149 if p.historyArchiverConfigs.Gstorage == nil { 150 return nil, ErrArchiverConfigNotFound 151 } 152 153 historyArchiver, err = gcloud.NewHistoryArchiver(container, p.historyArchiverConfigs.Gstorage) 154 155 case s3store.URIScheme: 156 if p.historyArchiverConfigs.S3store == nil { 157 return nil, ErrArchiverConfigNotFound 158 } 159 historyArchiver, err = s3store.NewHistoryArchiver(container, p.historyArchiverConfigs.S3store) 160 default: 161 return nil, ErrUnknownScheme 162 } 163 164 if err != nil { 165 return nil, err 166 } 167 168 p.Lock() 169 defer p.Unlock() 170 if existingHistoryArchiver, ok := p.historyArchivers[archiverKey]; ok { 171 return existingHistoryArchiver, nil 172 } 173 p.historyArchivers[archiverKey] = historyArchiver 174 return historyArchiver, nil 175 } 176 177 func (p *archiverProvider) GetVisibilityArchiver(scheme, serviceName string) (archiver.VisibilityArchiver, error) { 178 archiverKey := p.getArchiverKey(scheme, serviceName) 179 p.RLock() 180 if visibilityArchiver, ok := p.visibilityArchivers[archiverKey]; ok { 181 p.RUnlock() 182 return visibilityArchiver, nil 183 } 184 p.RUnlock() 185 186 container, ok := p.visibilityContainers[serviceName] 187 if !ok { 188 return nil, ErrBootstrapContainerNotFound 189 } 190 191 var visibilityArchiver archiver.VisibilityArchiver 192 var err error 193 194 switch scheme { 195 case filestore.URIScheme: 196 if p.visibilityArchiverConfigs.Filestore == nil { 197 return nil, ErrArchiverConfigNotFound 198 } 199 visibilityArchiver, err = filestore.NewVisibilityArchiver(container, p.visibilityArchiverConfigs.Filestore) 200 case s3store.URIScheme: 201 if p.visibilityArchiverConfigs.S3store == nil { 202 return nil, ErrArchiverConfigNotFound 203 } 204 visibilityArchiver, err = s3store.NewVisibilityArchiver(container, p.visibilityArchiverConfigs.S3store) 205 case gcloud.URIScheme: 206 if p.visibilityArchiverConfigs.Gstorage == nil { 207 return nil, ErrArchiverConfigNotFound 208 } 209 visibilityArchiver, err = gcloud.NewVisibilityArchiver(container, p.visibilityArchiverConfigs.Gstorage) 210 211 default: 212 return nil, ErrUnknownScheme 213 } 214 if err != nil { 215 return nil, err 216 } 217 218 p.Lock() 219 defer p.Unlock() 220 if existingVisibilityArchiver, ok := p.visibilityArchivers[archiverKey]; ok { 221 return existingVisibilityArchiver, nil 222 } 223 p.visibilityArchivers[archiverKey] = visibilityArchiver 224 return visibilityArchiver, nil 225 226 } 227 228 func (p *archiverProvider) getArchiverKey(scheme, serviceName string) string { 229 return scheme + ":" + serviceName 230 }