You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: action.go
    path of file: ./repos/yoke/monitor
    
    the code of the file until where you have to start completion: //
package monitor

import (
	"bufio"
	"database/sql"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"sync"
	"syscall"
	"time"

	"github.com/hoisie/mustache"
	_ "github.com/lib/pq"
	"github.com/nanopack/yoke/config"
	"github.com/nanopack/yoke/state"
)

var (
	Done = errors.New("done")
)

type (
	Performer interface {
		TransitionToActive()
		TransitionToBackup()
		TransitionToSingle()
		Stop()
		Initialize() error
		Start() error
		Loop() error
	}

	performer struct {
		sync.Mutex
		step   map[string]bool
		me     state.State
		other  state.State
		err    chan error
		done   chan interface{}
		cmd    *exec.Cmd
		config config.Config
	}
)

func NewPrefix(prefix string) io.Writer {
	read, write := io.Pipe()
	scan := bufio.NewScanner(read)
	go func() {
		for scan.Scan() {
			fmt.Printf("%v %v\n", prefix, scan.Text())
		}
	}()
	return write
}

func NewPerformer(me state.State, other state.State, config config.Config) *performer {
	perform := performer{
		config: config,
		step: map[string]bool{
			"trigger": true, // this should only be there if the trigger file exists
		},
		me:    me,
		other: other,
		err:   make(chan error),
		done:  make(chan interface{}),
	}

	return &perform
}

func (performer *performer) Loop() error {
	config.Log.Info("Waiting for error")
	return <-performer.err
}

func (performer *performer) Stop() {
	config.Log.Info("going to stop")
	performer.Lock()
	defer performer.Unlock()
	config.Log.Info("stopping")
	performer.stop()
	config.Log.Info("stopped")
}

func (performer *performer) TransitionToSingle() {
	performer.Lock()
	defer performer.Unlock()

	// backups or actives can transition to single
	// it just means that the other node went down
	role, err := performer.me.GetDBRole()
	if err != nil {
		performer.err <- err
		return
	}
	if role
    
func (performer *performer) Active() error {
	config.Log.Info("transitioning to Active")
	if err := performer.replicate(false); err != nil {
		return err
	}

	// do an initial copy of files which might be corrupt because they are not consistant
	// this will be fixed later. we do this now so that a majority of the data will make it across without
	// having to pause the Durablility (ACID compliance) of postgres
	config.Log.Debug("[action] pre-backup started")
	dataDir, err := performer.other.GetDataDir()
	if err != nil {
		return err
	}
	location := performer.other.Location()
	ip, _, err := net.SplitHostPort(location)
	if err != nil {
		return err
	}
	sync := mustache.Render(performer.config.SyncCommand, map[string]string{"local_dir": performer.config.DataDir, "slave_ip": ip, "slave_dir": dataDir})

	if err := performer.sync(sync); err != nil {
		return err
	}

	db, err := performer.pgConnect()
	if err != nil {
		return err
	}
	defer db.Close()

	// this informs postgres to make the files on disk consistant for copying,
	// all changes are kept in memory from this point on
	_, err = db.Exec("select pg_start_backup('replication')")
	if err != nil {
		return err
	}

	config.Log.Debug("[action] backup started")

	if err := performer.sync(sync); err != nil {
		// stop the backup, if it fails, there is nothing we can do so we return the original error
		db.Exec("select pg_stop_backup()")

		// something went wrong, we are the master still, so lets wait for the slave to reconnect
		return nil
	}

	// connect to DB and tell it to stop backup
	if _, err = db.Exec("select pg_stop_backup()"); err != nil {
		return err
	}

	config.Log.Debug("[action] backup complete")

	// if we were unsucessfull at setting the sync flag on the other node
	// then we need to start all over
	if performer.other.SetSynced(true) != nil {
		return nil
	}

	// enable syncronus transaction commits.
	if err := performer.setSync(true, db); err != nil {
		return err
	}

	performer.addVip()
	performer.roleChangeCommand("master")

	performer.me.SetDBRole("active")
	return nil
}