Skip to content

Commit 63eefd3

Browse files
authored
Merge pull request #567 from textileio/sander/pprof
PushPaths pre-verification
2 parents 4ed7549 + 8001733 commit 63eefd3

10 files changed

Lines changed: 471 additions & 402 deletions

File tree

api/billingd/gateway/gateway.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strings"
99
"time"
1010

11+
"github.com/gin-contrib/pprof"
1112
"github.com/gin-gonic/gin"
1213
logging "github.com/ipfs/go-log/v2"
1314
ma "github.com/multiformats/go-multiaddr"
@@ -82,6 +83,7 @@ func (g *Gateway) Start() {
8283
}
8384

8485
router := gin.Default()
86+
pprof.Register(router)
8587
router.GET("/health", func(c *gin.Context) {
8688
c.Writer.WriteHeader(http.StatusOK)
8789
})

api/bucketsd/client/client.go

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ type PushPathsQueue struct {
250250

251251
q []pushPath
252252
len int
253+
startCh chan []string
253254
inCh chan pushPath
254255
inWaitCh chan struct{}
255256
outCh chan PushPathsResult
@@ -375,6 +376,15 @@ func (c *PushPathsQueue) Next() (ok bool) {
375376
func (c *PushPathsQueue) start() {
376377
go func() {
377378
defer close(c.inWaitCh)
379+
380+
var paths []string
381+
c.lk.Lock()
382+
for _, p := range c.q {
383+
paths = append(paths, p.path)
384+
}
385+
c.lk.Unlock()
386+
c.startCh <- paths
387+
378388
for {
379389
c.lk.Lock()
380390
if c.closed {
@@ -391,7 +401,6 @@ func (c *PushPathsQueue) start() {
391401
c.lk.Unlock()
392402
c.inCh <- p
393403
}
394-
395404
}()
396405
}
397406

@@ -452,18 +461,8 @@ func (c *Client) PushPaths(ctx context.Context, key string, opts ...Option) (*Pu
452461
xr = args.root.String()
453462
}
454463

455-
if err := stream.Send(&pb.PushPathsRequest{
456-
Payload: &pb.PushPathsRequest_Header_{
457-
Header: &pb.PushPathsRequest_Header{
458-
Key: key,
459-
Root: xr,
460-
},
461-
},
462-
}); err != nil {
463-
return nil, err
464-
}
465-
466464
q := &PushPathsQueue{
465+
startCh: make(chan []string),
467466
inCh: make(chan pushPath),
468467
inWaitCh: make(chan struct{}),
469468
outCh: make(chan PushPathsResult),
@@ -543,33 +542,55 @@ func (c *Client) PushPaths(ctx context.Context, key string, opts ...Option) (*Pu
543542
}
544543

545544
go func() {
546-
for p := range q.inCh {
547-
r, err := p.r()
548-
if err != nil {
549-
q.outCh <- PushPathsResult{err: err}
550-
break
551-
}
552-
buf := make([]byte, chunkSize)
553-
for {
554-
n, err := r.Read(buf)
555-
c := &pb.PushPathsRequest_Chunk{
556-
Path: p.path,
545+
loop:
546+
for {
547+
select {
548+
case paths := <-q.startCh:
549+
if len(paths) > 0 {
550+
if err := stream.Send(&pb.PushPathsRequest{
551+
Payload: &pb.PushPathsRequest_Header_{
552+
Header: &pb.PushPathsRequest_Header{
553+
Key: key,
554+
Root: xr,
555+
Paths: paths,
556+
},
557+
},
558+
}); err != nil {
559+
q.outCh <- PushPathsResult{err: err}
560+
break loop
561+
}
562+
}
563+
case p, ok := <-q.inCh:
564+
if !ok {
565+
break loop
557566
}
558-
if n > 0 {
559-
c.Data = make([]byte, n)
560-
copy(c.Data, buf[:n])
561-
if ok := sendChunk(c); !ok {
567+
r, err := p.r()
568+
if err != nil {
569+
q.outCh <- PushPathsResult{err: err}
570+
break loop
571+
}
572+
buf := make([]byte, chunkSize)
573+
for {
574+
n, err := r.Read(buf)
575+
c := &pb.PushPathsRequest_Chunk{
576+
Path: p.path,
577+
}
578+
if n > 0 {
579+
c.Data = make([]byte, n)
580+
copy(c.Data, buf[:n])
581+
if ok := sendChunk(c); !ok {
582+
break
583+
}
584+
} else if err == io.EOF {
585+
sendChunk(c)
586+
break
587+
} else if err != nil {
588+
q.outCh <- PushPathsResult{err: err}
562589
break
563590
}
564-
} else if err == io.EOF {
565-
sendChunk(c)
566-
break
567-
} else if err != nil {
568-
q.outCh <- PushPathsResult{err: err}
569-
break
570591
}
592+
r.Close()
571593
}
572-
r.Close()
573594
}
574595
}()
575596

api/bucketsd/pb/bucketsd.pb.go

Lines changed: 357 additions & 347 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/bucketsd/pb/bucketsd.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ message PushPathsRequest {
146146
message Header {
147147
string key = 1;
148148
string root = 2;
149+
repeated string paths = 3;
149150
}
150151

151152
message Chunk {

api/bucketsd/service.go

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,9 @@ func (s *Service) PushPath(server pb.APIService_PushPathServer) (err error) {
16551655
dbToken, _ := thread.TokenFromContext(server.Context())
16561656

16571657
req, err := server.Recv()
1658-
if err != nil {
1658+
if err == io.EOF {
1659+
return nil
1660+
} else if err != nil {
16591661
return err
16601662
}
16611663
var buckKey, headerPath, root string
@@ -1946,14 +1948,18 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
19461948
dbToken, _ := thread.TokenFromContext(ctx)
19471949

19481950
req, err := server.Recv()
1949-
if err != nil {
1951+
if err == io.EOF {
1952+
return nil
1953+
} else if err != nil {
19501954
return fmt.Errorf("on receive: %v", err)
19511955
}
19521956
var buckKey, buckRoot string
1957+
var buckPaths []string
19531958
switch payload := req.Payload.(type) {
19541959
case *pb.PushPathsRequest_Header_:
19551960
buckKey = payload.Header.Key
19561961
buckRoot = payload.Header.Root
1962+
buckPaths = payload.Header.Paths
19571963
default:
19581964
return fmt.Errorf("push bucket path header is required")
19591965
}
@@ -1963,17 +1969,31 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
19631969
defer lck.Release()
19641970

19651971
buck := &tdb.Bucket{}
1966-
err = s.Buckets.GetSafe(ctx, dbID, buckKey, buck, tdb.WithToken(dbToken))
1967-
if err != nil {
1972+
if err := s.Buckets.GetSafe(ctx, dbID, buckKey, buck, tdb.WithToken(dbToken)); err != nil {
19681973
return fmt.Errorf("getting bucket: %v", err)
19691974
}
19701975
if buckRoot != "" && buckRoot != buck.Path {
19711976
return status.Error(codes.FailedPrecondition, buckets.ErrNonFastForward.Error())
19721977
}
1978+
19731979
readOnlyBuck := buck.Copy()
1980+
preVerified := make(map[string]struct{})
1981+
if len(buckPaths) > 0 {
1982+
readOnlyBuck.UpdatedAt = time.Now().UnixNano()
1983+
for _, p := range buckPaths {
1984+
readOnlyBuck.SetMetadataAtPath(p, tdb.Metadata{
1985+
UpdatedAt: readOnlyBuck.UpdatedAt,
1986+
})
1987+
readOnlyBuck.UnsetMetadataWithPrefix(p + "/")
1988+
preVerified[p] = struct{}{}
1989+
}
1990+
if err := s.Buckets.Verify(ctx, dbID, readOnlyBuck, tdb.WithToken(dbToken)); err != nil {
1991+
return status.Error(codes.PermissionDenied, fmt.Sprintf("verifying bucket update: %v", err))
1992+
}
1993+
}
19741994

19751995
var wg sync.WaitGroup
1976-
var ctxLock sync.RWMutex
1996+
var ctxLock, verifiedLock sync.RWMutex
19771997
addedCh := make(chan addedFile)
19781998
doneCh := make(chan struct{})
19791999
errCh := make(chan error)
@@ -2001,13 +2021,19 @@ func (s *Service) PushPaths(server pb.APIService_PushPathsServer) error {
20012021
ctxLock.RUnlock()
20022022
fa, err := queue.add(ctx, s.IPFSClient.Unixfs(), pth, func() ([]byte, error) {
20032023
wg.Add(1)
2004-
readOnlyBuck.UpdatedAt = time.Now().UnixNano()
2005-
readOnlyBuck.SetMetadataAtPath(pth, tdb.Metadata{
2006-
UpdatedAt: readOnlyBuck.UpdatedAt,
2007-
})
2008-
readOnlyBuck.UnsetMetadataWithPrefix(pth + "/")
2009-
if err = s.Buckets.Verify(ctx, dbID, readOnlyBuck, tdb.WithToken(dbToken)); err != nil {
2010-
return nil, fmt.Errorf("verifying bucket update: %v", err)
2024+
// Support requests that don't send all paths for pre-verification (pre v2.6.11)
2025+
verifiedLock.Lock()
2026+
_, ok := preVerified[pth]
2027+
verifiedLock.Unlock()
2028+
if !ok {
2029+
readOnlyBuck.UpdatedAt = time.Now().UnixNano()
2030+
readOnlyBuck.SetMetadataAtPath(pth, tdb.Metadata{
2031+
UpdatedAt: readOnlyBuck.UpdatedAt,
2032+
})
2033+
readOnlyBuck.UnsetMetadataWithPrefix(pth + "/")
2034+
if err = s.Buckets.Verify(ctx, dbID, readOnlyBuck, tdb.WithToken(dbToken)); err != nil {
2035+
return nil, fmt.Errorf("verifying bucket update: %v", err)
2036+
}
20112037
}
20122038
key, err := readOnlyBuck.GetFileEncryptionKeyForPath(pth)
20132039
if err != nil {

cmd/cmd.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
uc "github.com/textileio/textile/v2/api/usersd/client"
2020
"google.golang.org/grpc"
2121
"google.golang.org/grpc/credentials"
22+
"google.golang.org/grpc/keepalive"
2223
)
2324

2425
var (
@@ -102,6 +103,11 @@ func NewClients(hubTarget string, isHub bool, minerIndexTarget string) *Clients
102103
hubOpts = append(hubOpts, grpc.WithInsecure())
103104
}
104105
hubOpts = append(hubOpts, grpc.WithPerRPCCredentials(auth))
106+
hubOpts = append(hubOpts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
107+
Time: time.Second * 20,
108+
Timeout: time.Second * 10,
109+
PermitWithoutStream: true,
110+
}))
105111

106112
c := &Clients{}
107113
var err error

core/core.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,14 +475,11 @@ func NewTextile(ctx context.Context, conf Config, opts ...Option) (*Textile, err
475475
grpcm.WithUnaryServerChain(auth.UnaryServerInterceptor(t.noAuthFunc)),
476476
grpcm.WithStreamServerChain(auth.StreamServerInterceptor(t.noAuthFunc)),
477477
grpc.KeepaliveParams(keepalive.ServerParameters{
478-
MaxConnectionIdle: time.Hour * 24,
479-
MaxConnectionAge: time.Hour * 24,
480-
MaxConnectionAgeGrace: time.Hour * 24,
481-
Time: time.Hour * 2,
482-
Timeout: time.Hour * 2,
478+
Time: time.Second * 20,
479+
Timeout: time.Second * 10,
483480
}),
484481
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
485-
MinTime: time.Minute * 5,
482+
MinTime: time.Second * 20,
486483
PermitWithoutStream: true,
487484
}),
488485
}

gateway/gateway.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/gin-contrib/location"
15+
"github.com/gin-contrib/pprof"
1516
"github.com/gin-contrib/static"
1617
"github.com/gin-gonic/gin"
1718
"github.com/ipfs/go-cid"
@@ -148,6 +149,7 @@ func (g *Gateway) Start() {
148149
host: g.bucketsDomain,
149150
}))
150151
router.Use(gincors.New(cors.Options{}))
152+
pprof.Register(router)
151153

152154
router.GET("/health", func(c *gin.Context) {
153155
c.Writer.WriteHeader(http.StatusOK)

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/dustin/go-humanize v1.0.0
1515
github.com/filecoin-project/go-fil-markets v1.1.9
1616
github.com/gin-contrib/location v0.0.2
17+
github.com/gin-contrib/pprof v1.3.0
1718
github.com/gin-contrib/static v0.0.1
1819
github.com/gin-gonic/gin v1.7.4
1920
github.com/gogo/status v1.1.0
@@ -74,7 +75,7 @@ require (
7475
github.com/textileio/dcrypto v0.0.1
7576
github.com/textileio/go-assets v0.0.0-20200430191519-b341e634e2b7
7677
github.com/textileio/go-ds-mongo v0.1.5
77-
github.com/textileio/go-threads v1.1.1
78+
github.com/textileio/go-threads v1.1.2-0.20210828004955-e1f6dc25311a
7879
github.com/textileio/powergate/v2 v2.3.0
7980
github.com/textileio/swagger-ui v0.3.29-0.20210224180244-7d73a7a32fe7
8081
github.com/xakep666/mongo-migrate v0.2.1

go.sum

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,15 @@ github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgoo
401401
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
402402
github.com/gin-contrib/location v0.0.2 h1:QZKh1+K/LLR4KG/61eIO3b7MLuKi8tytQhV6texLgP4=
403403
github.com/gin-contrib/location v0.0.2/go.mod h1:NGoidiRlf0BlA/VKSVp+g3cuSMeTmip/63PhEjRhUAc=
404+
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
405+
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
404406
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
405407
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
406408
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2/go.mod h1:VhW/Ch/3FhimwZb8Oj+qJmdMmoB8r7lmJ5auRjm50oQ=
407409
github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U=
408410
github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs=
409411
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
412+
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
410413
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
411414
github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
412415
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
@@ -1881,8 +1884,8 @@ github.com/textileio/go-libp2p-pubsub-rpc v0.0.5 h1:De54sqNpQocJebf7P+4RrwtuUw8s
18811884
github.com/textileio/go-libp2p-pubsub-rpc v0.0.5/go.mod h1:MlOMOz3KZxexobvUuFXT/QY9Vjh9eKJpZPr48hDUdVo=
18821885
github.com/textileio/go-log/v2 v2.1.3-gke-1 h1:7e3xSUXQB8hn4uUe5fp41kLThW1o9T65gSM7qjS323g=
18831886
github.com/textileio/go-log/v2 v2.1.3-gke-1/go.mod h1:DwACkjFS3kjZZR/4Spx3aPfSsciyslwUe5bxV8CEU2w=
1884-
github.com/textileio/go-threads v1.1.1 h1:cAYayq8nrYpMzF/+oWZ0QKhbmcHNEHpRHjWKSC4vPzE=
1885-
github.com/textileio/go-threads v1.1.1/go.mod h1:xIuk2P+WXIwzvN2NlHZerPMZb1DkwxeWGlu5HkX9j3c=
1887+
github.com/textileio/go-threads v1.1.2-0.20210828004955-e1f6dc25311a h1:2WHvzu8r6GPnA5QC0ShjzflyxGMO7BltoW8Mv9g/1sM=
1888+
github.com/textileio/go-threads v1.1.2-0.20210828004955-e1f6dc25311a/go.mod h1:xIuk2P+WXIwzvN2NlHZerPMZb1DkwxeWGlu5HkX9j3c=
18861889
github.com/textileio/powergate/v2 v2.3.0 h1:kelYh+ZWDQao1rL5YiMznQscd6CsDjgt6P/D1S5UYwQ=
18871890
github.com/textileio/powergate/v2 v2.3.0/go.mod h1:2j2NL1oevaVdrI6MpKfHnfgUOy1D4L7eP3I+1czxDjw=
18881891
github.com/textileio/swagger-ui v0.3.29-0.20210224180244-7d73a7a32fe7 h1:qUEurT6kJF+nFkiNjUPMJJ7hgg9OIDnb8iLn6VtBukE=

0 commit comments

Comments
 (0)