func (tm *TabletManager) Snapshot(ctx context.Context, args *actionnode.SnapshotArgs, sendReply func(interface{}) error) error { return tm.agent.RpcWrapLockAction(ctx, actionnode.TABLET_ACTION_SNAPSHOT, args, nil, true, func() error { // create a logger, send the result back to the caller logger := logutil.NewChannelLogger(10) wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logger { ssr := &gorpcproto.SnapshotStreamingReply{ Log: &e, } // 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 to send. sendReply(ssr) } wg.Done() }() sr, err := tm.agent.Snapshot(ctx, args, logger) close(logger) wg.Wait() if err != nil { return err } ssr := &gorpcproto.SnapshotStreamingReply{ Result: sr, } sendReply(ssr) return nil }) }
// ExecuteVtctlCommand is the server side method that will execute the query, // and stream the results. func (s *VtctlServer) ExecuteVtctlCommand(context context.Context, query *gorpcproto.ExecuteVtctlCommandArgs, sendReply func(interface{}) error) error { // 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, query.ActionTimeout, query.LockTimeout) // execute the command err := vtctl.RunCommand(wr, query.Args) // close the log channel, and wait for them all to be sent close(logstream) wg.Wait() return err }
func (tm *TabletManager) Restore(ctx context.Context, args *actionnode.RestoreArgs, sendReply func(interface{}) error) error { return tm.agent.RpcWrapLockAction(ctx, actionnode.TABLET_ACTION_RESTORE, args, nil, true, func() error { // create a logger, send the result back to the caller logger := logutil.NewChannelLogger(10) wg := sync.WaitGroup{} wg.Add(1) go func() { for e := range logger { // 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 to send. sendReply(&e) } wg.Done() }() err := tm.agent.Restore(ctx, args, logger) close(logger) wg.Wait() return err }) }