- k8s.io/api v0.28.1 - k8s.io/apiextensions-apiserver v0.28.1 - k8s.io/apimachinery v0.28.1 - k8s.io/client-go v0.28.1 - k8s.io/metrics v0.28.1 - sigs.k8s.io/controller-runtime v0.16.1 - sigs.k8s.io/controller-tools v0.13.0 Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
222 lines
7.1 KiB
Go
222 lines
7.1 KiB
Go
/*
|
|
Copyright 2016 The Fission Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package mqtrigger
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
k8sCache "k8s.io/client-go/tools/cache"
|
|
|
|
fv1 "github.com/fission/fission/pkg/apis/core/v1"
|
|
"github.com/fission/fission/pkg/generated/clientset/versioned"
|
|
"github.com/fission/fission/pkg/mqtrigger/messageQueue"
|
|
"github.com/fission/fission/pkg/utils"
|
|
"github.com/fission/fission/pkg/utils/metrics"
|
|
)
|
|
|
|
const (
|
|
ADD_TRIGGER requestType = iota
|
|
DELETE_TRIGGER
|
|
GET_TRIGGER_SUBSCRIPTION
|
|
)
|
|
|
|
type (
|
|
requestType int
|
|
|
|
MessageQueueTriggerManager struct {
|
|
logger *zap.Logger
|
|
reqChan chan request
|
|
triggers map[string]*triggerSubscription
|
|
fissionClient versioned.Interface
|
|
messageQueueType fv1.MessageQueueType
|
|
messageQueue messageQueue.MessageQueue
|
|
}
|
|
|
|
triggerSubscription struct {
|
|
trigger fv1.MessageQueueTrigger
|
|
subscription messageQueue.Subscription
|
|
}
|
|
|
|
request struct {
|
|
requestType
|
|
triggerSub *triggerSubscription
|
|
respChan chan response
|
|
}
|
|
response struct {
|
|
err error
|
|
triggerSub *triggerSubscription
|
|
}
|
|
)
|
|
|
|
func MakeMessageQueueTriggerManager(logger *zap.Logger,
|
|
fissionClient versioned.Interface, mqType fv1.MessageQueueType, messageQueue messageQueue.MessageQueue) *MessageQueueTriggerManager {
|
|
mqTriggerMgr := MessageQueueTriggerManager{
|
|
logger: logger.Named("message_queue_trigger_manager"),
|
|
reqChan: make(chan request),
|
|
triggers: make(map[string]*triggerSubscription),
|
|
fissionClient: fissionClient,
|
|
messageQueueType: mqType,
|
|
messageQueue: messageQueue,
|
|
}
|
|
return &mqTriggerMgr
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) Run(ctx context.Context) error {
|
|
go mqt.service()
|
|
for _, informer := range utils.GetInformersForNamespaces(mqt.fissionClient, time.Minute*30, fv1.MessageQueueResource) {
|
|
_, err := informer.AddEventHandler(mqt.mqtInformerHandlers())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
go informer.Run(ctx.Done())
|
|
if ok := k8sCache.WaitForCacheSync(ctx.Done(), informer.HasSynced); !ok {
|
|
mqt.logger.Fatal("failed to wait for caches to sync")
|
|
}
|
|
}
|
|
go metrics.ServeMetrics(ctx, mqt.logger)
|
|
return nil
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) service() {
|
|
for {
|
|
req := <-mqt.reqChan
|
|
resp := response{triggerSub: nil, err: nil}
|
|
k, err := k8sCache.MetaNamespaceKeyFunc(&req.triggerSub.trigger)
|
|
if err != nil {
|
|
resp.err = err
|
|
req.respChan <- resp
|
|
continue
|
|
}
|
|
|
|
switch req.requestType {
|
|
case ADD_TRIGGER:
|
|
if _, ok := mqt.triggers[k]; ok {
|
|
resp.err = errors.New("trigger already exists")
|
|
} else {
|
|
mqt.triggers[k] = req.triggerSub
|
|
mqt.logger.Debug("set trigger subscription", zap.String("key", k))
|
|
IncreaseSubscriptionCount()
|
|
}
|
|
req.respChan <- resp
|
|
case GET_TRIGGER_SUBSCRIPTION:
|
|
if _, ok := mqt.triggers[k]; !ok {
|
|
resp.err = errors.New("trigger does not exist")
|
|
} else {
|
|
resp.triggerSub = mqt.triggers[k]
|
|
}
|
|
req.respChan <- resp
|
|
case DELETE_TRIGGER:
|
|
delete(mqt.triggers, k)
|
|
mqt.logger.Debug("delete trigger", zap.String("key", k))
|
|
DecreaseSubscriptionCount()
|
|
req.respChan <- resp
|
|
}
|
|
}
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) makeRequest(requestType requestType, triggerSub *triggerSubscription) response {
|
|
respChan := make(chan response)
|
|
mqt.reqChan <- request{requestType, triggerSub, respChan}
|
|
return <-respChan
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) addTrigger(triggerSub *triggerSubscription) error {
|
|
resp := mqt.makeRequest(ADD_TRIGGER, triggerSub)
|
|
return resp.err
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) getTriggerSubscription(trigger *fv1.MessageQueueTrigger) *triggerSubscription {
|
|
resp := mqt.makeRequest(GET_TRIGGER_SUBSCRIPTION, &triggerSubscription{trigger: *trigger})
|
|
return resp.triggerSub
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) checkTriggerSubscription(trigger *fv1.MessageQueueTrigger) bool {
|
|
return mqt.getTriggerSubscription(trigger) != nil
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) delTriggerSubscription(trigger *fv1.MessageQueueTrigger) error {
|
|
resp := mqt.makeRequest(DELETE_TRIGGER, &triggerSubscription{trigger: *trigger})
|
|
return resp.err
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) RegisterTrigger(trigger *fv1.MessageQueueTrigger) {
|
|
isPresent := mqt.checkTriggerSubscription(trigger)
|
|
if isPresent {
|
|
mqt.logger.Debug("message queue trigger already registered", zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
return
|
|
}
|
|
|
|
// actually subscribe using the message queue client impl
|
|
sub, err := mqt.messageQueue.Subscribe(trigger)
|
|
if err != nil {
|
|
mqt.logger.Warn("failed to subscribe to message queue trigger", zap.Error(err), zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
return
|
|
}
|
|
if sub == nil {
|
|
mqt.logger.Warn("subscription is nil", zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
return
|
|
}
|
|
triggerSub := triggerSubscription{
|
|
trigger: *trigger,
|
|
subscription: sub,
|
|
}
|
|
// add to our list
|
|
err = mqt.addTrigger(&triggerSub)
|
|
if err != nil {
|
|
mqt.logger.Fatal("adding message queue trigger failed", zap.Error(err), zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
}
|
|
mqt.logger.Info("message queue trigger created", zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
}
|
|
|
|
func (mqt *MessageQueueTriggerManager) mqtInformerHandlers() k8sCache.ResourceEventHandlerFuncs {
|
|
return k8sCache.ResourceEventHandlerFuncs{
|
|
AddFunc: func(obj interface{}) {
|
|
trigger := obj.(*fv1.MessageQueueTrigger)
|
|
mqt.logger.Debug("Added mqt", zap.Any("trigger: ", trigger.ObjectMeta))
|
|
mqt.RegisterTrigger(trigger)
|
|
},
|
|
DeleteFunc: func(obj interface{}) {
|
|
trigger := obj.(*fv1.MessageQueueTrigger)
|
|
mqt.logger.Debug("Delete mqt", zap.Any("trigger: ", trigger.ObjectMeta))
|
|
triggerSubscription := mqt.getTriggerSubscription(trigger)
|
|
if triggerSubscription == nil {
|
|
mqt.logger.Info("Unsubscribe failed", zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
return
|
|
}
|
|
|
|
err := mqt.messageQueue.Unsubscribe(triggerSubscription.subscription)
|
|
if err != nil {
|
|
mqt.logger.Warn("failed to unsubscribe from message queue trigger", zap.Error(err), zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
return
|
|
}
|
|
err = mqt.delTriggerSubscription(trigger)
|
|
if err != nil {
|
|
mqt.logger.Warn("deleting message queue trigger failed", zap.Error(err), zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
}
|
|
mqt.logger.Info("message queue trigger deleted", zap.String("trigger_name", trigger.ObjectMeta.Name))
|
|
},
|
|
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
|
|
trigger := newObj.(*fv1.MessageQueueTrigger)
|
|
mqt.logger.Debug("Updated mqt", zap.Any("trigger: ", trigger.ObjectMeta))
|
|
mqt.RegisterTrigger(trigger)
|
|
},
|
|
}
|
|
}
|