func (c *Client) Close() error {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.closed = true
	if c.client != nil {
		return c.client.Close()
	}
	return nil
}
Close closes the clients TTRPC connection to containerd
package ttrpcutil
import (
	"sync"
	"time"
	v1 "github.com/containerd/containerd/api/services/ttrpc/events/v1"
	"github.com/containerd/containerd/pkg/dialer"
	"github.com/containerd/ttrpc"
	"github.com/pkg/errors"
)
const ttrpcDialTimeout = 5 * time.Second
type ttrpcConnector func() (*ttrpc.Client, error)
type Client struct {
	mu        sync.Mutex
	connector ttrpcConnector
	client    *ttrpc.Client
	closed    bool
}
func NewClient(address string, opts ...ttrpc.ClientOpts) (*Client, error) {
	connector := func() (*ttrpc.Client, error) {
		conn, err := dialer.Dialer(address, ttrpcDialTimeout)
		if err != nil {
			return nil, errors.Wrap(err, "failed to connect")
		}
		client := ttrpc.NewClient(conn, opts...)
		return client, nil
	}
	return &Client{
		connector: connector,
	}, nil
}
func (c *Client) Reconnect() error {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.connector == nil {
		return errors.New("unable to reconnect to containerd, no connector available")
	}
	if c.closed {
		return errors.New("client is closed")
	}
	if c.client != nil {
		if err := c.client.Close(); err != nil {
			return err
		}
	}
	client, err := c.connector()
	if err != nil {
		return err
	}
	c.client = client
	return nil
}
func (c *Client) EventsService() (v1.EventsService, error) {
	client, err := c.Client()
	if err != nil {
		return nil, err
	}
	return v1.NewEventsClient(client), nil
}
func (c *Client) Client() (*ttrpc.Client, error) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.client == nil {
		client, err := c.connector()
		if err != nil {
			return nil, err
		}
		c.client = client
	}
	return c.client, nil
}