github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/cmd/scandeps/sampleclient/main.go (about)

     1  // Copyright 2023 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Sample experiment client for connecting to a scandeps service
    16  package main
    17  
    18  import (
    19  	"context"
    20  	"flag"
    21  	"os"
    22  	"runtime"
    23  	"time"
    24  
    25  	"google.golang.org/grpc/codes"
    26  	"google.golang.org/grpc/status"
    27  
    28  	"github.com/bazelbuild/reclient/internal/pkg/ipc"
    29  
    30  	pb "github.com/bazelbuild/reclient/api/scandeps"
    31  
    32  	log "github.com/golang/glog"
    33  	"github.com/google/uuid"
    34  
    35  	emptypb "google.golang.org/protobuf/types/known/emptypb"
    36  )
    37  
    38  var (
    39  	serverAddr  = "127.0.0.1:8001"
    40  	dialTimeout = 3 * time.Minute
    41  )
    42  
    43  func main() {
    44  	flag.StringVar(&serverAddr, "server_address", serverAddr, "The server address in the format of host:port for network, or unix:///file for unix domain sockets.")
    45  	flag.Parse()
    46  	ctx, cancel := context.WithTimeout(context.Background(), dialTimeout)
    47  	defer cancel()
    48  	conn, err := ipc.DialContext(ctx, serverAddr)
    49  	if err != nil {
    50  		log.Fatalf("Fail to dial %s: %v", serverAddr, err)
    51  	}
    52  	defer conn.Close()
    53  
    54  	scandeps := pb.NewCPPDepsScannerClient(conn)
    55  
    56  	cmd := []string{}
    57  	directory, _ := os.Getwd()
    58  	filename := ""
    59  
    60  	switch runtime.GOOS {
    61  	case "darwin":
    62  		log.Fatalf("Scandeps service on Mac is not yet supported")
    63  	case "linux":
    64  		filename = "tests/integ/testdata/test.cpp"
    65  		cmd = append(cmd,
    66  			// Will be downloaded from GCS by run_integ_tests.sh.
    67  			"tests/integ/testdata/clang/bin/clang++",
    68  			"--sysroot", "tests/integ/testdata/sysroot",
    69  			"-c",
    70  			"-I",
    71  			"tests/integ/testdata/clang/include/c++/v1",
    72  			"-o", "test.obj",
    73  			filename,
    74  		)
    75  	case "windows":
    76  		filename = "tests\\integ\\testdata\\test.cpp"
    77  		cmd = append(cmd,
    78  			// Will be downloaded from GCS by prepare_chromium_integ_tests.bat
    79  			"tests\\integ\\testdata\\chromium\\src\\third_party\\llvm-build\\Release+Asserts\\bin\\clang-cl.exe",
    80  			"/nologo",
    81  			"/showIncludes:user",
    82  			"/TP",
    83  			"-fmsc-version=1916",
    84  			"/Brepro",
    85  			"/c",
    86  			"/winsysroottests\\integ\\testdata\\chromium\\src\\third_party\\depot_tools\\win_toolchain\\vs_files\\20d5f2553f",
    87  			"/Fo", "test.obj",
    88  			filename,
    89  		)
    90  	}
    91  
    92  	for {
    93  		processResponse, err := scandeps.ProcessInputs(
    94  			context.Background(),
    95  			&pb.CPPProcessInputsRequest{
    96  				ExecId:    uuid.New().String(),
    97  				Command:   cmd,
    98  				Directory: directory,
    99  				Filename:  filename,
   100  			})
   101  		if err != nil {
   102  			if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
   103  				log.Warningf("Disconnected from service during ProcessInputs; retrying after 10 seconds.")
   104  				time.Sleep(10)
   105  				log.Warningf("Retrying ProcessInputs.")
   106  				continue
   107  			}
   108  			log.Fatalf("ProcessInputs command failed: %v", err)
   109  		}
   110  		log.Infof("Dependencies: %v", processResponse.Dependencies)
   111  		log.Infof("Used cache: %t", processResponse.UsedCache)
   112  		break
   113  	}
   114  
   115  	for {
   116  		statusResponse, err := scandeps.Status(context.Background(), &emptypb.Empty{})
   117  		if err != nil {
   118  			log.Errorf("Status command failed: %v", err)
   119  			if st, ok := status.FromError(err); ok && st.Code() == codes.Unavailable {
   120  				log.Warningf("Disconnected from service during Status; retrying after 10 seconds.")
   121  				time.Sleep(10)
   122  				log.Warningf("Retrying Status.")
   123  				continue
   124  			}
   125  			log.Fatalf("Status command failed: %v", err)
   126  		}
   127  		log.Infof("Response from %s (v%s)", statusResponse.GetName(), statusResponse.GetVersion())
   128  		if statusResponse.GetUptime() != nil {
   129  			log.Infof("> Uptime: %d seconds", statusResponse.GetUptime().GetSeconds())
   130  		}
   131  		log.Infof("> Completed: %d", statusResponse.GetCompletedActions())
   132  		log.Infof("> In Progress: %d", statusResponse.GetRunningActions())
   133  		if statusResponse.GetLongestCurrentAction() != nil {
   134  			log.Infof("> Longest action: %d", statusResponse.GetLongestCurrentAction().GetSeconds())
   135  		}
   136  		break
   137  	}
   138  	log.Flush()
   139  }