Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit c6b1485

Browse files
committed
gitserver: Stream fetch progress
Just an experiment, not merging for now. Test plan:
1 parent 80fd112 commit c6b1485

File tree

5 files changed

+1350
-1075
lines changed

5 files changed

+1350
-1075
lines changed

cmd/gitserver/internal/repositoryservice.go

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package internal
22

33
import (
44
"context"
5+
"sync"
6+
"time"
57

68
"github.com/sourcegraph/log"
79
"google.golang.org/grpc/codes"
@@ -26,6 +28,7 @@ func NewRepositoryServiceServer(server *Server, config *GRPCRepositoryServiceCon
2628
hostname: server.hostname,
2729
svc: server,
2830
fs: server.fs,
31+
locker: server.locker,
2932
}
3033

3134
if config.ExhaustiveRequestLoggingEnabled {
@@ -46,6 +49,7 @@ type repositoryServiceServer struct {
4649
hostname string
4750
fs gitserverfs.FS
4851
svc service
52+
locker RepositoryLocker
4953

5054
proto.UnimplementedGitserverRepositoryServiceServer
5155
}
@@ -78,20 +82,57 @@ func (s *repositoryServiceServer) DeleteRepository(ctx context.Context, req *pro
7882
return &proto.DeleteRepositoryResponse{}, nil
7983
}
8084

81-
func (s *repositoryServiceServer) FetchRepository(ctx context.Context, req *proto.FetchRepositoryRequest) (*proto.FetchRepositoryResponse, error) {
85+
func (s *repositoryServiceServer) FetchRepository(req *proto.FetchRepositoryRequest, ss proto.GitserverRepositoryService_FetchRepositoryServer) error {
8286
if req.GetRepoName() == "" {
83-
return nil, status.New(codes.InvalidArgument, "repo_name must be specified").Err()
87+
return status.New(codes.InvalidArgument, "repo_name must be specified").Err()
8488
}
8589

8690
repoName := api.RepoName(req.GetRepoName())
8791

88-
lastFetched, lastChanged, err := s.svc.FetchRepository(ctx, repoName)
92+
var wg sync.WaitGroup
93+
wg.Add(1)
94+
done := make(chan struct{})
95+
96+
go func() {
97+
defer wg.Done()
98+
99+
for {
100+
select {
101+
case <-done:
102+
return
103+
case <-time.After(time.Second):
104+
}
105+
status, locked := s.locker.Status(repoName)
106+
if locked {
107+
err := ss.Send(&proto.FetchRepositoryResponse{
108+
Payload: &proto.FetchRepositoryResponse_Progress{
109+
Progress: &proto.FetchRepositoryResponse_FetchProgress{
110+
Output: []byte(status),
111+
},
112+
},
113+
})
114+
if err != nil {
115+
s.logger.Error("failed to send progress event", log.Error(err), log.String("repo", string(repoName)))
116+
}
117+
}
118+
}
119+
120+
}()
121+
122+
lastFetched, lastChanged, err := s.svc.FetchRepository(ss.Context(), repoName)
89123
if err != nil {
90-
return nil, status.New(codes.Internal, errors.Wrap(err, "failed to fetch repository").Error()).Err()
124+
return status.New(codes.Internal, errors.Wrap(err, "failed to fetch repository").Error()).Err()
91125
}
92126

93-
return &proto.FetchRepositoryResponse{
94-
LastFetched: timestamppb.New(lastFetched),
95-
LastChanged: timestamppb.New(lastChanged),
96-
}, nil
127+
close(done)
128+
wg.Wait()
129+
130+
return ss.Send(&proto.FetchRepositoryResponse{
131+
Payload: &proto.FetchRepositoryResponse_Done{
132+
Done: &proto.FetchRepositoryResponse_FetchDone{
133+
LastFetched: timestamppb.New(lastFetched),
134+
LastChanged: timestamppb.New(lastChanged),
135+
},
136+
},
137+
})
97138
}

cmd/repo-updater/internal/gitserver/repositoryservice.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package gitserver
22

33
import (
44
"context"
5+
"fmt"
56
"time"
67

78
"github.com/sourcegraph/sourcegraph/internal/api"
@@ -36,13 +37,33 @@ func (c *repositoryServiceClient) FetchRepository(ctx context.Context, repo api.
3637
if err != nil {
3738
return lastFetched, lastChanged, err
3839
}
39-
resp, err := cc.FetchRepository(ctx, &proto.FetchRepositoryRequest{
40+
req, err := cc.FetchRepository(ctx, &proto.FetchRepositoryRequest{
4041
RepoName: string(repo),
4142
})
4243
if err != nil {
4344
return lastFetched, lastChanged, err
4445
}
45-
return resp.GetLastFetched().AsTime(), resp.GetLastChanged().AsTime(), nil
46+
47+
lastProgress := ""
48+
49+
for {
50+
resp, err := req.Recv()
51+
if err != nil {
52+
return lastFetched, lastChanged, err
53+
}
54+
55+
if done := resp.GetDone(); done != nil {
56+
return done.GetLastFetched().AsTime(), done.GetLastChanged().AsTime(), nil
57+
}
58+
59+
if pr := resp.GetProgress(); pr != nil {
60+
progress := string(pr.GetOutput())
61+
if progress != "" && progress != lastProgress {
62+
fmt.Printf("progress fetching repo %s: %s\n", repo, string(pr.GetOutput()))
63+
}
64+
lastProgress = progress
65+
}
66+
}
4667
}
4768

4869
func (c *repositoryServiceClient) clientForRepo(ctx context.Context, repo api.RepoName) (proto.GitserverRepositoryServiceClient, error) {

0 commit comments

Comments
 (0)