diff --git a/.golangci.yaml b/.golangci.yaml index 8354f33902f..c99e5441134 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -35,4 +35,3 @@ linters: - gocritic - prealloc #- gosec - diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 1d0169d31c1..b907f682b3d 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -1166,31 +1166,24 @@ func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.St return c.Stat(ctx, req) } + infoFromProviders := make([]*provider.ResourceInfo, len(providers)) + errors := make([]error, len(providers)) + var wg sync.WaitGroup + + for i, p := range providers { + wg.Add(1) + go s.statOnProvider(ctx, req, infoFromProviders[i], p, &errors[i], &wg) + } + wg.Wait() + var totalSize uint64 - infos := []*provider.ResourceInfo{} - for _, p := range providers { - c, err := s.getStorageProviderClient(ctx, p) - if err != nil { + for i := range providers { + if errors[i] != nil { return &provider.StatResponse{ - Status: status.NewInternal(ctx, err, "error connecting to storage provider="+p.Address), + Status: status.NewStatusFromErrType(ctx, "stat ref: "+req.Ref.String(), errors[i]), }, nil } - - if resPath != "" && !strings.HasPrefix(resPath, p.ProviderPath) { - req = &provider.StatRequest{ - Ref: &provider.Reference{ - Spec: &provider.Reference_Path{ - Path: p.ProviderPath, - }, - }, - } - } - res, err := c.Stat(ctx, req) - if err != nil { - return nil, errors.Wrap(err, "gateway: error calling ListContainer") - } - totalSize += res.Info.Size - infos = append(infos, res.Info) + totalSize += infoFromProviders[i].Size } // TODO(ishank011): aggregrate other properties for references spread across storage providers, eg. /eos @@ -1202,13 +1195,41 @@ func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.St OpaqueId: uuid.New().String(), }, Type: provider.ResourceType_RESOURCE_TYPE_CONTAINER, - Etag: etag.GenerateEtagFromResources(nil, infos), + Etag: etag.GenerateEtagFromResources(nil, infoFromProviders), Path: resPath, Size: totalSize, }, }, nil } +func (s *svc) statOnProvider(ctx context.Context, req *provider.StatRequest, res *provider.ResourceInfo, p *registry.ProviderInfo, e *error, wg *sync.WaitGroup) { + defer wg.Done() + c, err := s.getStorageProviderClient(ctx, p) + if err != nil { + *e = errors.Wrap(err, "error connecting to storage provider="+p.Address) + return + } + + resPath := path.Clean(req.Ref.GetPath()) + newPath := req.Ref.GetPath() + if resPath != "" && !strings.HasPrefix(resPath, p.ProviderPath) { + newPath = p.ProviderPath + } + r, err := c.Stat(ctx, &provider.StatRequest{ + Ref: &provider.Reference{ + Spec: &provider.Reference_Path{ + Path: newPath, + }, + }, + }) + if err != nil { + *e = errors.Wrap(err, "gateway: error calling ListContainer") + return + } + res = &provider.ResourceInfo{} + *res = *r.Info +} + func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { p, st := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) if st.Code != rpc.Code_CODE_OK {