Recorder CRD, Records API, Redis deployment (#818)
This commit is contained in:
committed by
Ta-Ching Chen
parent
07ca5df8d0
commit
74a3a54543
@@ -17,20 +17,26 @@ limitations under the License.
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/satori/go.uuid"
|
||||
"github.com/sirupsen/logrus"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/fission/fission"
|
||||
"github.com/fission/fission/crd"
|
||||
executorClient "github.com/fission/fission/executor/client"
|
||||
"github.com/fission/fission/redis"
|
||||
)
|
||||
|
||||
type tsRoundTripperParams struct {
|
||||
@@ -42,10 +48,13 @@ type tsRoundTripperParams struct {
|
||||
|
||||
type functionHandler struct {
|
||||
fmap *functionServiceMap
|
||||
frmap *functionRecorderMap
|
||||
trmap *triggerRecorderMap
|
||||
executor *executorClient.Client
|
||||
function *metav1.ObjectMeta
|
||||
httpTrigger *crd.HTTPTrigger
|
||||
tsRoundTripperParams *tsRoundTripperParams
|
||||
recorderName string
|
||||
}
|
||||
|
||||
// A layer on top of http.DefaultTransport, with retries.
|
||||
@@ -83,6 +92,27 @@ func (roundTripper RetryingRoundTripper) RoundTrip(req *http.Request) (resp *htt
|
||||
var needExecutor, serviceUrlFromExecutor bool
|
||||
var serviceUrl *url.URL
|
||||
|
||||
// TODO: Keep? --> Needed for queries encoded in URL before they're stripped by the proxy
|
||||
var originalUrl url.URL
|
||||
originalUrl = *req.URL
|
||||
|
||||
// Iff this request needs to be recorded, we save the body
|
||||
var postedBody string
|
||||
if len(roundTripper.funcHandler.recorderName) > 0 {
|
||||
if req.ContentLength > 0 {
|
||||
p := make([]byte, req.ContentLength)
|
||||
buf, _ := ioutil.ReadAll(req.Body)
|
||||
// We need two io readers because a single reader will drain the buffer, hence we keep a replacement copy
|
||||
rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf))
|
||||
rdr2 := ioutil.NopCloser(bytes.NewBuffer(buf))
|
||||
|
||||
rdr1.Read(p)
|
||||
postedBody = string(p)
|
||||
logrus.Info(fmt.Sprintf("%v", postedBody))
|
||||
req.Body = rdr2
|
||||
}
|
||||
}
|
||||
|
||||
// Metrics stuff
|
||||
startTime := time.Now()
|
||||
funcMetricLabels := &functionLabels{
|
||||
@@ -177,6 +207,27 @@ func (roundTripper RetryingRoundTripper) RoundTrip(req *http.Request) (resp *htt
|
||||
functionCallCompleted(funcMetricLabels, httpMetricLabels,
|
||||
overhead, time.Since(startTime), resp.ContentLength)
|
||||
|
||||
// if transport.RoundTrip succeeds and it was a cached entry, then tapService
|
||||
if !serviceUrlFromExecutor {
|
||||
go roundTripper.funcHandler.tapService(serviceUrl)
|
||||
}
|
||||
|
||||
trigger := ""
|
||||
if roundTripper.funcHandler.httpTrigger != nil {
|
||||
trigger = roundTripper.funcHandler.httpTrigger.Metadata.Name
|
||||
} else {
|
||||
log.Println("No trigger attached.") // Wording?
|
||||
}
|
||||
|
||||
if len(roundTripper.funcHandler.recorderName) > 0 {
|
||||
redis.Record(
|
||||
trigger,
|
||||
roundTripper.funcHandler.recorderName,
|
||||
req.Header.Get("X-Fission-ReqUID"), req, originalUrl, postedBody, resp, roundTripper.funcHandler.function.Namespace,
|
||||
time.Now().UnixNano(),
|
||||
)
|
||||
}
|
||||
|
||||
// return response back to user
|
||||
return resp, nil
|
||||
}
|
||||
@@ -227,6 +278,14 @@ func (fh *functionHandler) handler(responseWriter http.ResponseWriter, request *
|
||||
request.Header.Add(fmt.Sprintf("X-Fission-Params-%v", k), v)
|
||||
}
|
||||
|
||||
var reqUID string
|
||||
if len(fh.recorderName) > 0 {
|
||||
UID := strings.ToLower(uuid.NewV4().String())
|
||||
reqUID = "REQ" + UID
|
||||
request.Header.Add("X-Fission-ReqUID", reqUID)
|
||||
log.Print("Record request with ReqUID: ", reqUID)
|
||||
}
|
||||
|
||||
// system params
|
||||
MetadataToHeaders(HEADERS_FISSION_FUNCTION_PREFIX, fh.function, request)
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2018 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 router
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/fission/fission"
|
||||
"github.com/fission/fission/cache"
|
||||
"github.com/fission/fission/crd"
|
||||
)
|
||||
|
||||
type (
|
||||
functionRecorderMap struct {
|
||||
cache *cache.Cache // map[string]*crd.Recorder
|
||||
}
|
||||
)
|
||||
|
||||
// Why do we need an expiry?
|
||||
func makeFunctionRecorderMap(expiry time.Duration) *functionRecorderMap {
|
||||
return &functionRecorderMap{
|
||||
cache: cache.MakeCache(expiry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (frmap *functionRecorderMap) lookup(function string) (*crd.Recorder, error) {
|
||||
item, err := frmap.cache.Get(function)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u := item.(*crd.Recorder)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (frmap *functionRecorderMap) assign(function string, recorder *crd.Recorder) {
|
||||
err, _ := frmap.cache.Set(function, recorder)
|
||||
if err != nil {
|
||||
if e, ok := err.(fission.Error); ok && e.Code == fission.ErrorNameExists {
|
||||
return
|
||||
}
|
||||
log.Printf("error caching recorder for function name with a different value: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (frmap *functionRecorderMap) remove(function string) error {
|
||||
return frmap.cache.Delete(function)
|
||||
}
|
||||
+69
-4
@@ -49,12 +49,12 @@ type HTTPTriggerSet struct {
|
||||
functions []crd.Function
|
||||
funcStore k8sCache.Store
|
||||
funcController k8sCache.Controller
|
||||
recorderSet *RecorderSet
|
||||
updateRouterRequestChannel chan struct{}
|
||||
|
||||
tsRoundTripperParams *tsRoundTripperParams
|
||||
tsRoundTripperParams *tsRoundTripperParams
|
||||
}
|
||||
|
||||
func makeHTTPTriggerSet(fmap *functionServiceMap, fissionClient *crd.FissionClient,
|
||||
func makeHTTPTriggerSet(fmap *functionServiceMap, frmap *functionRecorderMap, trmap *triggerRecorderMap, fissionClient *crd.FissionClient,
|
||||
kubeClient *kubernetes.Clientset, executor *executorClient.Client, crdClient *rest.RESTClient, params *tsRoundTripperParams) (*HTTPTriggerSet, k8sCache.Store, k8sCache.Store) {
|
||||
httpTriggerSet := &HTTPTriggerSet{
|
||||
functionServiceMap: fmap,
|
||||
@@ -66,8 +66,9 @@ func makeHTTPTriggerSet(fmap *functionServiceMap, fissionClient *crd.FissionClie
|
||||
updateRouterRequestChannel: make(chan struct{}),
|
||||
tsRoundTripperParams: params,
|
||||
}
|
||||
var tStore, fnStore k8sCache.Store
|
||||
var tStore, fnStore, rStore k8sCache.Store
|
||||
var tController, fnController k8sCache.Controller
|
||||
var recorderSet *RecorderSet
|
||||
if httpTriggerSet.crdClient != nil {
|
||||
tStore, tController = httpTriggerSet.initTriggerController()
|
||||
httpTriggerSet.triggerStore = tStore
|
||||
@@ -76,6 +77,8 @@ func makeHTTPTriggerSet(fmap *functionServiceMap, fissionClient *crd.FissionClie
|
||||
httpTriggerSet.funcStore = fnStore
|
||||
httpTriggerSet.funcController = fnController
|
||||
}
|
||||
recorderSet = MakeRecorderSet(httpTriggerSet, crdClient, rStore, frmap, trmap)
|
||||
httpTriggerSet.recorderSet = recorderSet
|
||||
return httpTriggerSet, tStore, fnStore
|
||||
}
|
||||
|
||||
@@ -92,6 +95,11 @@ func (ts *HTTPTriggerSet) subscribeRouter(ctx context.Context, mr *mutableRouter
|
||||
go ts.updateRouter()
|
||||
go ts.runWatcher(ctx, ts.funcController)
|
||||
go ts.runWatcher(ctx, ts.triggerController)
|
||||
if ts.recorderSet.recController != nil {
|
||||
go ts.runWatcher(ctx, ts.recorderSet.recController)
|
||||
} else {
|
||||
log.Fatal("Failed to run recorder Controller")
|
||||
}
|
||||
}
|
||||
|
||||
func defaultHomeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -121,6 +129,14 @@ func (ts *HTTPTriggerSet) getRouter() *mux.Router {
|
||||
continue
|
||||
}
|
||||
|
||||
var recorderName string
|
||||
recorder, err := ts.recorderSet.triggerRecorderMap.lookup(trigger.Metadata.Name)
|
||||
if err == nil && recorder != nil {
|
||||
recorderName = recorder.Spec.Name
|
||||
}
|
||||
|
||||
//log.Printf("The trigger %v should be recorded: %v", trigger.Metadata.Name, doRecord)
|
||||
|
||||
if rr.resolveResultType != resolveResultSingleFunction {
|
||||
// not implemented yet
|
||||
log.Panicf("resolve result type not implemented (%v)", rr.resolveResultType)
|
||||
@@ -128,10 +144,13 @@ func (ts *HTTPTriggerSet) getRouter() *mux.Router {
|
||||
|
||||
fh := &functionHandler{
|
||||
fmap: ts.functionServiceMap,
|
||||
frmap: ts.recorderSet.functionRecorderMap,
|
||||
trmap: ts.recorderSet.triggerRecorderMap,
|
||||
function: rr.functionMetadata,
|
||||
executor: ts.executor,
|
||||
httpTrigger: &trigger,
|
||||
tsRoundTripperParams: ts.tsRoundTripperParams,
|
||||
recorderName: recorderName,
|
||||
}
|
||||
|
||||
ht := muxRouter.HandleFunc(trigger.Spec.RelativeURL, fh.handler)
|
||||
@@ -158,11 +177,21 @@ func (ts *HTTPTriggerSet) getRouter() *mux.Router {
|
||||
// triggers route into these.
|
||||
for _, function := range ts.functions {
|
||||
m := function.Metadata
|
||||
|
||||
var recorderName string
|
||||
recorder, err := ts.recorderSet.functionRecorderMap.lookup(m.Name)
|
||||
if err == nil && recorder != nil {
|
||||
recorderName = recorder.Spec.Name
|
||||
}
|
||||
|
||||
fh := &functionHandler{
|
||||
fmap: ts.functionServiceMap,
|
||||
frmap: ts.recorderSet.functionRecorderMap,
|
||||
trmap: ts.recorderSet.triggerRecorderMap,
|
||||
function: &m,
|
||||
executor: ts.executor,
|
||||
tsRoundTripperParams: ts.tsRoundTripperParams,
|
||||
recorderName: recorderName,
|
||||
}
|
||||
muxRouter.HandleFunc(fission.UrlForFunction(function.Metadata.Name, function.Metadata.Namespace), fh.handler)
|
||||
}
|
||||
@@ -186,11 +215,22 @@ func (ts *HTTPTriggerSet) initTriggerController() (k8sCache.Store, k8sCache.Cont
|
||||
trigger := obj.(*crd.HTTPTrigger)
|
||||
go createIngress(trigger, ts.kubeClient)
|
||||
ts.syncTriggers()
|
||||
// Check if this trigger's function needs to be recorded
|
||||
fnRef := trigger.Spec.FunctionReference.Name
|
||||
recorder, err := ts.recorderSet.functionRecorderMap.lookup(fnRef)
|
||||
if err == nil && recorder != nil {
|
||||
if len(recorder.Spec.Triggers) == 0 {
|
||||
ts.recorderSet.triggerRecorderMap.assign(trigger.Metadata.Name, recorder)
|
||||
}
|
||||
} else {
|
||||
log.Print("Unable to lookup function in functionRecorderMap")
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
ts.syncTriggers()
|
||||
trigger := obj.(*crd.HTTPTrigger)
|
||||
go deleteIngress(trigger, ts.kubeClient)
|
||||
go ts.recorderSet.DeleteTriggerFromRecorderMap(trigger)
|
||||
},
|
||||
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
|
||||
oldTrigger := oldObj.(*crd.HTTPTrigger)
|
||||
@@ -216,7 +256,9 @@ func (ts *HTTPTriggerSet) initFunctionController() (k8sCache.Store, k8sCache.Con
|
||||
ts.syncTriggers()
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
function := obj.(*crd.Function)
|
||||
ts.syncTriggers()
|
||||
go ts.recorderSet.DeleteFunctionFromRecorderMap(function)
|
||||
},
|
||||
UpdateFunc: func(oldObj interface{}, newObj interface{}) {
|
||||
oldFn := oldObj.(*crd.Function)
|
||||
@@ -243,6 +285,29 @@ func (ts *HTTPTriggerSet) initFunctionController() (k8sCache.Store, k8sCache.Con
|
||||
return store, controller
|
||||
}
|
||||
|
||||
func (ts *HTTPTriggerSet) initRecorderController() (k8sCache.Store, k8sCache.Controller) {
|
||||
resyncPeriod := 30 * time.Second
|
||||
listWatch := k8sCache.NewListWatchFromClient(ts.crdClient, "recorders", metav1.NamespaceAll, fields.Everything())
|
||||
store, controller := k8sCache.NewInformer(listWatch, &crd.Recorder{}, resyncPeriod,
|
||||
k8sCache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
recorder := obj.(*crd.Recorder)
|
||||
ts.recorderSet.newRecorder(recorder)
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
recorder := obj.(*crd.Recorder)
|
||||
ts.recorderSet.disableRecorder(recorder)
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
oldRecorder := oldObj.(*crd.Recorder)
|
||||
newRecorder := newObj.(*crd.Recorder)
|
||||
ts.recorderSet.updateRecorder(oldRecorder, newRecorder)
|
||||
},
|
||||
},
|
||||
)
|
||||
return store, controller
|
||||
}
|
||||
|
||||
func (ts *HTTPTriggerSet) runWatcher(ctx context.Context, controller k8sCache.Controller) {
|
||||
go func() {
|
||||
controller.Run(ctx.Done())
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/fission/fission/crd"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/client-go/rest"
|
||||
k8sCache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type RecorderSet struct {
|
||||
httpTriggerSet *HTTPTriggerSet
|
||||
|
||||
crdClient *rest.RESTClient
|
||||
|
||||
recStore k8sCache.Store
|
||||
recController k8sCache.Controller
|
||||
|
||||
functionRecorderMap *functionRecorderMap
|
||||
triggerRecorderMap *triggerRecorderMap
|
||||
}
|
||||
|
||||
func MakeRecorderSet(httpTriggerSet *HTTPTriggerSet, crdClient *rest.RESTClient, rStore k8sCache.Store, frmap *functionRecorderMap, trmap *triggerRecorderMap) *RecorderSet {
|
||||
recorderSet := &RecorderSet{
|
||||
httpTriggerSet: httpTriggerSet,
|
||||
crdClient: crdClient,
|
||||
recStore: rStore,
|
||||
functionRecorderMap: frmap,
|
||||
triggerRecorderMap: trmap,
|
||||
}
|
||||
recorderSet.recStore, recorderSet.recController = httpTriggerSet.initRecorderController()
|
||||
return recorderSet
|
||||
}
|
||||
|
||||
// All new recorders are by default enabled
|
||||
func (rs *RecorderSet) newRecorder(r *crd.Recorder) {
|
||||
function := r.Spec.Function
|
||||
triggers := r.Spec.Triggers
|
||||
|
||||
// If triggers are not explicitly specified during the creation of this recorder,
|
||||
// keep track of those associated with the function specified [implicitly added triggers]
|
||||
needTrackByFunction := len(triggers) == 0
|
||||
|
||||
rs.functionRecorderMap.assign(function, r)
|
||||
|
||||
if needTrackByFunction {
|
||||
for _, t := range rs.httpTriggerSet.triggerStore.List() {
|
||||
trigger := *t.(*crd.HTTPTrigger)
|
||||
if trigger.Spec.FunctionReference.Name == function {
|
||||
rs.triggerRecorderMap.assign(trigger.Metadata.Name, r)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, trigger := range triggers {
|
||||
rs.triggerRecorderMap.assign(trigger, r)
|
||||
}
|
||||
}
|
||||
|
||||
rs.httpTriggerSet.syncTriggers()
|
||||
}
|
||||
|
||||
// TODO: Delete or disable?
|
||||
func (rs *RecorderSet) disableRecorder(r *crd.Recorder) {
|
||||
function := r.Spec.Function
|
||||
triggers := r.Spec.Triggers
|
||||
|
||||
log.Info("Disabling recorder ", r.Metadata.Name)
|
||||
|
||||
// Account for function
|
||||
err := rs.functionRecorderMap.remove(function)
|
||||
if err != nil {
|
||||
log.Error("Error disabling recorder (failed to remove function from functionRecorderMap): ", err)
|
||||
}
|
||||
|
||||
// Account for explicitly added triggers
|
||||
if len(triggers) != 0 {
|
||||
for _, trigger := range triggers {
|
||||
err := rs.triggerRecorderMap.remove(trigger)
|
||||
if err != nil {
|
||||
log.Error("Error disabling recorder (failed to remove triggers from triggerRecorderMap): ", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Account for implicitly added triggers
|
||||
for _, t := range rs.httpTriggerSet.triggerStore.List() {
|
||||
trigger := *t.(*crd.HTTPTrigger)
|
||||
if trigger.Spec.FunctionReference.Name == function {
|
||||
err := rs.triggerRecorderMap.remove(trigger.Metadata.Name)
|
||||
if err != nil {
|
||||
log.Error("Failed to remove trigger from triggerRecorderMap: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rs.httpTriggerSet.syncTriggers()
|
||||
}
|
||||
|
||||
func (rs *RecorderSet) updateRecorder(old *crd.Recorder, newer *crd.Recorder) {
|
||||
if newer.Spec.Enabled == true {
|
||||
rs.newRecorder(newer) // TODO: Test this
|
||||
} else {
|
||||
rs.disableRecorder(old)
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RecorderSet) DeleteTriggerFromRecorderMap(trigger *crd.HTTPTrigger) {
|
||||
err := rs.triggerRecorderMap.remove(trigger.Metadata.Name)
|
||||
if err != nil {
|
||||
log.Error("Failed to remove trigger from triggerRecorderMap: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (rs *RecorderSet) DeleteFunctionFromRecorderMap(function *crd.Function) {
|
||||
err := rs.functionRecorderMap.remove(function.Metadata.Name)
|
||||
if err != nil {
|
||||
log.Error("Failed to remove function from functionRecorderMap: ", err)
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -86,6 +86,10 @@ func Start(port int, executorUrl string) {
|
||||
|
||||
fmap := makeFunctionServiceMap(time.Minute)
|
||||
|
||||
frmap := makeFunctionRecorderMap(time.Minute)
|
||||
|
||||
trmap := makeTriggerRecorderMap(time.Minute)
|
||||
|
||||
fissionClient, kubeClient, _, err := crd.MakeFissionClient()
|
||||
if err != nil {
|
||||
log.Fatalf("Error connecting to kubernetes API: %v", err)
|
||||
@@ -120,13 +124,14 @@ func Start(port int, executorUrl string) {
|
||||
log.Fatalf("Failed to parse max retry times: %v", err)
|
||||
}
|
||||
|
||||
triggers, _, fnStore := makeHTTPTriggerSet(fmap, fissionClient, kubeClient, executor, restClient,
|
||||
triggers, _, fnStore := makeHTTPTriggerSet(fmap, frmap, trmap, fissionClient, kubeClient, executor, restClient,
|
||||
&tsRoundTripperParams{
|
||||
timeout: timeout,
|
||||
timeoutExponent: timeoutExponent,
|
||||
keepAlive: keepAlive,
|
||||
maxRetries: maxRetries,
|
||||
})
|
||||
|
||||
resolver := makeFunctionReferenceResolver(fnStore)
|
||||
|
||||
go serveMetric()
|
||||
|
||||
@@ -58,8 +58,12 @@ func TestRouter(t *testing.T) {
|
||||
}
|
||||
frr.refCache.Set(nfr, rr)
|
||||
|
||||
frmap := makeFunctionRecorderMap(time.Minute)
|
||||
|
||||
trmap := makeTriggerRecorderMap(time.Minute)
|
||||
|
||||
// HTTP trigger set with a trigger for this function
|
||||
triggers, _, _ := makeHTTPTriggerSet(fmap, nil, nil, nil, nil,
|
||||
triggers, _, _ := makeHTTPTriggerSet(fmap, frmap, trmap, nil, nil, nil, nil,
|
||||
&tsRoundTripperParams{
|
||||
timeout: 50 * time.Millisecond,
|
||||
timeoutExponent: 2,
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2018 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 router
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/fission/fission"
|
||||
"github.com/fission/fission/cache"
|
||||
"github.com/fission/fission/crd"
|
||||
)
|
||||
|
||||
type (
|
||||
triggerRecorderMap struct {
|
||||
cache *cache.Cache // map[string]*crd.Recorder
|
||||
}
|
||||
)
|
||||
|
||||
func makeTriggerRecorderMap(expiry time.Duration) *triggerRecorderMap {
|
||||
return &triggerRecorderMap{
|
||||
cache: cache.MakeCache(expiry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (trmap *triggerRecorderMap) lookup(trigger string) (*crd.Recorder, error) {
|
||||
item, err := trmap.cache.Get(trigger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u := item.(*crd.Recorder)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (trmap *triggerRecorderMap) assign(trigger string, recorder *crd.Recorder) {
|
||||
err, _ := trmap.cache.Set(trigger, recorder)
|
||||
if err != nil {
|
||||
if e, ok := err.(fission.Error); ok && e.Code == fission.ErrorNameExists {
|
||||
return
|
||||
}
|
||||
log.Printf("error caching recorder for function name with a different value: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (trmap *triggerRecorderMap) remove(trigger string) error {
|
||||
return trmap.cache.Delete(trigger)
|
||||
}
|
||||
Reference in New Issue
Block a user