| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You 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 plugin |
| |
| import ( |
| "strconv" |
| "sync/atomic" |
| "time" |
| |
| "github.com/ReneKroon/ttlcache/v2" |
| "github.com/apache/apisix-go-plugin-runner/internal/log" |
| "github.com/apache/apisix-go-plugin-runner/internal/util" |
| A6 "github.com/api7/ext-plugin-proto/go/A6" |
| pc "github.com/api7/ext-plugin-proto/go/A6/PrepareConf" |
| flatbuffers "github.com/google/flatbuffers/go" |
| ) |
| |
| type ConfEntry struct { |
| Name string |
| Value interface{} |
| } |
| type RuleConf []ConfEntry |
| |
| var ( |
| cache *ttlcache.Cache |
| cacheCounter uint32 = 0 |
| ) |
| |
| func InitConfCache(ttl time.Duration) { |
| cache = ttlcache.NewCache() |
| err := cache.SetTTL(ttl) |
| if err != nil { |
| log.Fatalf("failed to set global ttl for cache: %s", err) |
| } |
| cache.SkipTTLExtensionOnHit(false) |
| cacheCounter = 0 |
| } |
| |
| func genCacheToken() uint32 { |
| return atomic.AddUint32(&cacheCounter, 1) |
| } |
| |
| func PrepareConf(buf []byte) (*flatbuffers.Builder, error) { |
| req := pc.GetRootAsReq(buf, 0) |
| entries := RuleConf{} |
| |
| te := A6.TextEntry{} |
| for i := 0; i < req.ConfLength(); i++ { |
| if req.Conf(&te, i) { |
| name := string(te.Name()) |
| plugin := findPlugin(name) |
| if plugin == nil { |
| log.Warnf("can't find plugin %s, skip", name) |
| continue |
| } |
| |
| log.Infof("prepare conf for plugin %s", name) |
| |
| v := te.Value() |
| conf, err := plugin.ParseConf(v) |
| if err != nil { |
| log.Errorf( |
| "failed to parse configuration for plugin %s, configuration: %s", |
| name, string(v)) |
| continue |
| } |
| |
| entries = append(entries, ConfEntry{ |
| Name: name, |
| Value: conf, |
| }) |
| } |
| } |
| |
| token := genCacheToken() |
| err := cache.Set(strconv.FormatInt(int64(token), 10), entries) |
| if err != nil { |
| return nil, err |
| } |
| |
| builder := util.GetBuilder() |
| pc.RespStart(builder) |
| pc.RespAddConfToken(builder, token) |
| root := pc.RespEnd(builder) |
| builder.Finish(root) |
| return builder, nil |
| } |
| |
| func GetRuleConf(token uint32) (RuleConf, error) { |
| res, err := cache.Get(strconv.FormatInt(int64(token), 10)) |
| if err != nil { |
| return nil, err |
| } |
| return res.(RuleConf), err |
| } |
| |
| func SetRuleConf(token uint32, conf RuleConf) error { |
| return cache.Set(strconv.FormatInt(int64(token), 10), conf) |
| } |