func (c *controller) Invoke(topic string, message *[]byte) {
	c.InvokeWithContext(context.Background(), topic, message)
}
Invoke attempts to invoke any functions which match the
topic the incoming message was published on.
package types
import (
	"context"
	"fmt"
	"log"
	"sync"
	"time"
	"github.com/openfaas/faas-provider/auth"
)
type ControllerConfig struct {
	UpstreamTimeout time.Duration
	GatewayURL string
	PrintResponse bool
	PrintResponseBody bool
	RebuildInterval time.Duration
	TopicAnnotationDelimiter string
	AsyncFunctionInvocation bool
	PrintSync bool
	ContentType string
	BasicAuth bool
}
type Controller interface {
	Subscribe(subscriber ResponseSubscriber)
	Invoke(topic string, message *[]byte)
	InvokeWithContext(ctx context.Context, topic string, message *[]byte)
	BeginMapBuilder()
	Topics() []string
}
type controller struct {
	Config *ControllerConfig
	Invoker *Invoker
	TopicMap *TopicMap
	Credentials *auth.BasicAuthCredentials
	Subscribers []ResponseSubscriber
	Lock *sync.RWMutex
}
func NewController(credentials *auth.BasicAuthCredentials, config *ControllerConfig) Controller {
	gatewayFunctionPath := gatewayRoute(config)
	invoker := NewInvoker(gatewayFunctionPath,
		MakeClient(config.UpstreamTimeout),
		config.ContentType,
		config.PrintResponse)
	subs := []ResponseSubscriber{}
	topicMap := NewTopicMap()
	c := controller{
		Config:      config,
		Invoker:     invoker,
		TopicMap:    &topicMap,
		Credentials: credentials,
		Subscribers: subs,
		Lock:        &sync.RWMutex{},
	}
	if config.PrintResponse {
		c.Subscribe(&ResponsePrinter{config.PrintResponseBody})
	}
	go func(ch *chan InvokerResponse, controller *controller) {
		for {
			res := <-*ch
			controller.Lock.RLock()
			for _, sub := range controller.Subscribers {
				sub.Response(res)
			}
			controller.Lock.RUnlock()
		}
	}(&invoker.Responses, &c)
	return &c
}
func (c *controller) Subscribe(subscriber ResponseSubscriber) {
	c.Lock.Lock()
	defer c.Lock.Unlock()
	c.Subscribers = append(c.Subscribers, subscriber)
}