// ExecuteVtworkerCommand is part of the vtworkerdatapb.VtworkerServer interface func (s *VtworkerServer) ExecuteVtworkerCommand(args *vtworkerdatapb.ExecuteVtworkerCommandRequest, stream vtworkerservicepb.Vtworker_ExecuteVtworkerCommandServer) (err error) { // Please note that this panic handler catches only panics occuring in the code below. // The actual execution of the vtworker command takes place in a new go routine // (started in Instance.setAndStartWorker()) which has its own panic handler. defer servenv.HandlePanic("vtworker", &err) // Stream everything back what the Wrangler is logging. logstream := logutil.NewCallbackLogger(func(e *logutilpb.Event) { // If the client disconnects, we will just fail // to send the log events, but won't interrupt // the command. stream.Send(&vtworkerdatapb.ExecuteVtworkerCommandResponse{ Event: e, }) }) // Let the Wrangler also log everything to the console (and thereby // effectively to a logfile) to make sure that any information or errors // is preserved in the logs in case the RPC or vtworker crashes. logger := logutil.NewTeeLogger(logstream, logutil.NewConsoleLogger()) // create the wrangler wr := s.wi.CreateWrangler(logger) // execute the command worker, done, err := s.wi.RunCommand(args.Args, wr, false /*runFromCli*/) if err == nil && worker != nil && done != nil { err = s.wi.WaitForCommand(worker, done) } return err }
// ExecuteVtctlCommand is part of the pb.VtctlServer interface func (s *VtctlServer) ExecuteVtctlCommand(args *pb.ExecuteVtctlCommandRequest, stream pbs.Vtctl_ExecuteVtctlCommandServer) (err error) { defer servenv.HandlePanic("vtctl", &err) // create a logger, send the result back to the caller logstream := logutil.NewChannelLogger(10) logger := logutil.NewTeeLogger(logstream, logutil.NewConsoleLogger()) // send logs to the caller wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logstream { // Note we don't interrupt the loop here, as // we still need to flush and finish the // command, even if the channel to the client // has been broken. We'll just keep trying. stream.Send(&pb.ExecuteVtctlCommandResponse{ Event: logutil.LoggerEventToProto(&e), }) } wg.Done() }() // create the wrangler wr := wrangler.New(logger, s.ts, tmclient.NewTabletManagerClient(), time.Duration(args.LockTimeout)) // execute the command err = vtctl.RunCommand(stream.Context(), wr, args.Args) // close the log channel, and wait for them all to be sent close(logstream) wg.Wait() return err }
// SetMaxRate implements the gRPC server interface. It sets the rate on all // throttlers controlled by the manager. func (s *Server) SetMaxRate(_ context.Context, request *throttlerdata.SetMaxRateRequest) (_ *throttlerdata.SetMaxRateResponse, err error) { defer servenv.HandlePanic("throttler", &err) names := s.manager.SetMaxRate(request.Rate) return &throttlerdata.SetMaxRateResponse{ Names: names, }, nil }
// MaxRates implements the gRPC server interface. It returns the current max // rate for each throttler of the process. func (s *Server) MaxRates(_ context.Context, request *throttlerdata.MaxRatesRequest) (_ *throttlerdata.MaxRatesResponse, err error) { defer servenv.HandlePanic("throttler", &err) rates := s.manager.MaxRates() return &throttlerdata.MaxRatesResponse{ Rates: rates, }, nil }
// ExecuteVtworkerCommand is part of the pb.VtworkerServer interface func (s *VtworkerServer) ExecuteVtworkerCommand(args *pb.ExecuteVtworkerCommandRequest, stream pbs.Vtworker_ExecuteVtworkerCommandServer) (err error) { // Please note that this panic handler catches only panics occuring in the code below. // The actual execution of the vtworker command takes place in a new go routine // (started in Instance.setAndStartWorker()) which has its own panic handler. defer servenv.HandlePanic("vtworker", &err) // create a logger, send the result back to the caller logstream := logutil.NewChannelLogger(10) logger := logutil.NewTeeLogger(logstream, logutil.NewMemoryLogger()) // send logs to the caller wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logstream { // Note we don't interrupt the loop here, as // we still need to flush and finish the // command, even if the channel to the client // has been broken. We'll just keep trying. stream.Send(&pb.ExecuteVtworkerCommandResponse{ Event: &pbl.Event{ Time: &pbl.Time{ Seconds: e.Time.Unix(), Nanoseconds: int32(e.Time.Nanosecond()), }, Level: pbl.Level(e.Level), File: e.File, Line: int64(e.Line), Value: e.Value, }, }) } wg.Done() }() // create the wrangler wr := s.wi.CreateWrangler(logger) // execute the command if len(args.Args) >= 1 && args.Args[0] == "Reset" { err = s.wi.Reset() } else { // Make sure we use the global "err" variable and do not redeclare it in this scope. var worker worker.Worker var done chan struct{} worker, done, err = s.wi.RunCommand(args.Args, wr, false /*runFromCli*/) if err == nil { err = s.wi.WaitForCommand(worker, done) } } // close the log channel, and wait for them all to be sent close(logstream) wg.Wait() return err }
// ResetConfiguration implements the gRPC server interface. func (s *Server) ResetConfiguration(_ context.Context, request *throttlerdata.ResetConfigurationRequest) (_ *throttlerdata.ResetConfigurationResponse, err error) { defer servenv.HandlePanic("throttler", &err) names, err := s.manager.ResetConfiguration(request.ThrottlerName) if err != nil { return nil, err } return &throttlerdata.ResetConfigurationResponse{ Names: names, }, nil }
// ExecuteVtworkerCommand is part of the vtworkerdatapb.VtworkerServer interface func (s *VtworkerServer) ExecuteVtworkerCommand(args *vtworkerdatapb.ExecuteVtworkerCommandRequest, stream vtworkerservicepb.Vtworker_ExecuteVtworkerCommandServer) (err error) { // Please note that this panic handler catches only panics occuring in the code below. // The actual execution of the vtworker command takes place in a new go routine // (started in Instance.setAndStartWorker()) which has its own panic handler. defer servenv.HandlePanic("vtworker", &err) // Stream everything back what the Wrangler is logging. logstream := logutil.NewChannelLogger(10) // Let the Wrangler also log everything to the console (and thereby // effectively to a logfile) to make sure that any information or errors // is preserved in the logs in case the RPC or vtworker crashes. logger := logutil.NewTeeLogger(logstream, logutil.NewConsoleLogger()) // send logs to the caller wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logstream { // Note we don't interrupt the loop here, as // we still need to flush and finish the // command, even if the channel to the client // has been broken. We'll just keep trying. stream.Send(&vtworkerdatapb.ExecuteVtworkerCommandResponse{ Event: e, }) } wg.Done() }() // create the wrangler wr := s.wi.CreateWrangler(logger) // execute the command worker, done, err := s.wi.RunCommand(args.Args, wr, false /*runFromCli*/) if err == nil && worker != nil && done != nil { err = s.wi.WaitForCommand(worker, done) } // close the log channel, and wait for them all to be sent close(logstream) wg.Wait() return err }
// ExecuteVtctlCommand is part of the vtctldatapb.VtctlServer interface func (s *VtctlServer) ExecuteVtctlCommand(args *vtctldatapb.ExecuteVtctlCommandRequest, stream vtctlservicepb.Vtctl_ExecuteVtctlCommandServer) (err error) { defer servenv.HandlePanic("vtctl", &err) // create a logger, send the result back to the caller logstream := logutil.NewCallbackLogger(func(e *logutilpb.Event) { // If the client disconnects, we will just fail // to send the log events, but won't interrupt // the command. stream.Send(&vtctldatapb.ExecuteVtctlCommandResponse{ Event: e, }) }) logger := logutil.NewTeeLogger(logstream, logutil.NewConsoleLogger()) // create the wrangler wr := wrangler.New(logger, s.ts, tmclient.NewTabletManagerClient()) // execute the command return vtctl.RunCommand(stream.Context(), wr, args.Args) }
// ExecuteVtctlCommand is the server side method that will execute the query, // and stream the results. func (s *VtctlServer) ExecuteVtctlCommand(ctx context.Context, query *gorpcproto.ExecuteVtctlCommandArgs, sendReply func(interface{}) error) (err error) { defer servenv.HandlePanic("vtctl", &err) // create a logger, send the result back to the caller logstream := logutil.NewChannelLogger(10) logger := logutil.NewTeeLogger(logstream, logutil.NewConsoleLogger()) // send logs to the caller wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logstream { // Note we don't interrupt the loop here, as // we still need to flush and finish the // command, even if the channel to the client // has been broken. We'll just keep trying. sendReply(&e) } wg.Done() }() // create the wrangler wr := wrangler.New(logger, s.ts, tmclient.NewTabletManagerClient(), query.LockTimeout) // FIXME(alainjobart) use a single context, copy the source info from it ctx, cancel := context.WithTimeout(context.TODO(), query.ActionTimeout) // execute the command err = vtctl.RunCommand(ctx, wr, query.Args) cancel() // close the log channel, and wait for them all to be sent close(logstream) wg.Wait() return err }