func main() { flag.Parse() ctx, cancel := context.WithTimeout(context.Background(), *actionTimeout) defer cancel() err := vtworkerclient.RunCommandAndWait( ctx, *server, flag.Args(), func(e *logutilpb.Event) { switch e.Level { case logutilpb.Level_INFO: log.Info(logutil.EventString(e)) case logutilpb.Level_WARNING: log.Warning(logutil.EventString(e)) case logutilpb.Level_ERROR: log.Error(logutil.EventString(e)) case logutilpb.Level_CONSOLE: fmt.Print(logutil.EventString(e)) } }) if err != nil { log.Error(err) os.Exit(1) } }
func main() { flag.Parse() ctx, cancel := context.WithTimeout(context.Background(), *actionTimeout) defer cancel() sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT) go func() { s := <-sigChan log.Errorf("Trying to cancel current command after receiving signal: %v", s) cancel() }() logger := logutil.NewConsoleLogger() err := vtworkerclient.RunCommandAndWait( ctx, *server, flag.Args(), func(e *logutilpb.Event) { logutil.LogEvent(logger, e) }) if err != nil { log.Error(err) os.Exit(1) } }
// ExecuteVtworker runs vtworker using vtworkerclient. The stream of LoggerEvent messages is concatenated into one output string. func ExecuteVtworker(ctx context.Context, server string, args []string) (string, error) { var output bytes.Buffer log.Infof("Executing remote vtworker command: %v server: %v", args, server) err := vtworkerclient.RunCommandAndWait( ctx, server, args, CreateLoggerEventToBufferFunction(&output)) return output.String(), err }
// ExecuteVtworker runs vtworker using vtworkerclient. The stream of LoggerEvent messages is concatenated into one output string. func ExecuteVtworker(ctx context.Context, server string, args []string) (string, error) { var output bytes.Buffer err := vtworkerclient.RunCommandAndWait( ctx, server, args, func(e *logutil.LoggerEvent) { e.ToBuffer(&output) }) return output.String(), err }
// ExecuteVtworker runs vtworker using vtworkerclient. The stream of LoggerEvent messages is concatenated into one output string. func ExecuteVtworker(ctx context.Context, server string, args []string) (string, error) { var output bytes.Buffer err := vtworkerclient.RunCommandAndWait( ctx, server, args, // TODO(mberlin): Should this value be configurable as flag? 30*time.Second, // dialTimeout func(e *logutil.LoggerEvent) { e.ToBuffer(&output) }) return output.String(), err }
func main() { flag.Parse() ctx, cancel := context.WithTimeout(context.Background(), *actionTimeout) defer cancel() logger := logutil.NewConsoleLogger() err := vtworkerclient.RunCommandAndWait( ctx, *server, flag.Args(), func(e *logutilpb.Event) { logutil.LogEvent(logger, e) }) if err != nil { log.Error(err) os.Exit(1) } }
// ExecuteVtworker executes the vtworker command in "args" via an RPC to // "server". // The output of the RPC, a stream of LoggerEvent messages, is concatenated into // one output string. // If a retryable error is encountered (e.g. the vtworker process is already // executing another command), this function will keep retrying infinitely until // "ctx" is cancelled. func ExecuteVtworker(ctx context.Context, server string, args []string) (string, error) { var output bytes.Buffer loggerToBufferFunc := createLoggerEventToBufferFunction(&output) outputLogger := newOutputLogger(loggerToBufferFunc) startMsg := fmt.Sprintf("Executing remote vtworker command: %v server: %v", args, server) outputLogger.Infof(startMsg) log.Info(startMsg) err := vtworkerclient.RunCommandAndWait(ctx, server, args, loggerToBufferFunc) endMsg := fmt.Sprintf("Executed remote vtworker command: %v server: %v err: %v", args, server, err) outputLogger.Infof(endMsg) // Log full output to log file (but not to the buffer). log.Infof("%v output (starting on next line):\n%v", endMsg, output.String()) return output.String(), err }
func main() { flag.Parse() err := vtworkerclient.RunCommandAndWait( context.Background(), *server, flag.Args(), *actionTimeout, func(e *logutil.LoggerEvent) { switch e.Level { case logutil.LOGGER_INFO: log.Info(e.String()) case logutil.LOGGER_WARNING: log.Warning(e.String()) case logutil.LOGGER_ERROR: log.Error(e.String()) case logutil.LOGGER_CONSOLE: fmt.Print(e.String()) } }) if err != nil { log.Error(err) os.Exit(1) } }
// ExecuteVtworker executes the vtworker command in "args" via an RPC to // "server". // The output of the RPC, a stream of LoggerEvent messages, is concatenated into // one output string. // If a retryable error is encountered (e.g. the vtworker process is already // executing another command), this function will keep retrying infinitely until // "ctx" is cancelled. func ExecuteVtworker(ctx context.Context, server string, args []string) (string, error) { var output bytes.Buffer loggerToBufferFunc := createLoggerEventToBufferFunction(&output) outputLogger := newOutputLogger(loggerToBufferFunc) startMsg := fmt.Sprintf("Executing remote vtworker command: %v server: %v", args, server) outputLogger.Infof(startMsg) log.Info(startMsg) var err error loggedRetryStart := make(map[string]bool) var retryStart time.Time var addrOfLastVtworkerTried string // List of resolved addresses which are logged every time they change. var lastSortedAddrs []string retryLoop: for { // Resolve "server" to a list of addresses before each retry. // If "server" resolves to multiple addresses, try them all without a wait // between each try. // Note that "addrs" will be shuffled by resolver.Resolve() to avoid that // two concurrent calls try the same task. var addrs []string addrs, err = resolver.Resolve(server) if err != nil { break retryLoop } // Log resolved addresses if they have changed since the last retry. sortedAddrs := make([]string, len(addrs)) copy(sortedAddrs, addrs) sort.Strings(sortedAddrs) if addrs[0] != server && !reflect.DeepEqual(sortedAddrs, lastSortedAddrs) { addrsResolvedMsg := fmt.Sprintf("vtworker hostname: %v resolved to addresses: %v", server, addrs) outputLogger.Infof(addrsResolvedMsg) log.Info(addrsResolvedMsg) lastSortedAddrs = sortedAddrs } for _, addr := range addrs { addrOfLastVtworkerTried = addr err = vtworkerclient.RunCommandAndWait( ctx, addr, args, loggerToBufferFunc) if err == nil { break retryLoop } if !isRetryable(err) { break retryLoop } // Log retry once per unique address. if !loggedRetryStart[addr] { loggedRetryStart[addr] = true retryStart = time.Now() retryStartMsg := fmt.Sprintf("vtworker (%s) responded with a retryable error (%v). continuing to retry every %.0f seconds until cancelled.", addr, err, retryInterval.Seconds()) outputLogger.Infof(retryStartMsg) log.Info(retryStartMsg) } } // Sleep until the next retry. timer := time.NewTimer(retryInterval) select { case <-ctx.Done(): // Context is up. The next retry would result in a non-retryable error, so // break out early. timer.Stop() err = ctx.Err() break retryLoop case <-timer.C: } } // retry loop if len(loggedRetryStart) > 0 { // Log end of retrying explicitly as well. d := time.Now().Sub(retryStart) retryEndMsg := fmt.Sprintf("Stopped retrying after %.1f seconds.", d.Seconds()) outputLogger.Infof(retryEndMsg) log.Info(retryEndMsg) } endMsg := fmt.Sprintf("Executed remote vtworker command: %v server: %v (%v) err: %v", args, server, addrOfLastVtworkerTried, err) outputLogger.Infof(endMsg) // Log full output to log file (but not to the buffer). log.Infof("%v output (starting on next line):\n%v", endMsg, output.String()) return output.String(), err }