Skip to content

Commit

Permalink
refreshable file datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
louyuting committed Mar 14, 2020
1 parent 4d4468c commit c6b1fc1
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 11 deletions.
125 changes: 125 additions & 0 deletions ext/datasource/refreshable_file/file_datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package refreshable_file

import (
"github.com/alibaba/sentinel-golang/ext/datasource"
"github.com/alibaba/sentinel-golang/logging"
"github.com/alibaba/sentinel-golang/util"
"github.com/fsnotify/fsnotify"
"github.com/pkg/errors"
"io/ioutil"
"os"
"time"
)

var (
logger = logging.GetDefaultLogger()
)

type RefreshableFileDataSource struct {
sourceFilePath string
handlers []datasource.PropertyHandler
}

func FileDataSourceStarter(sourceFilePath string, handlers ...datasource.PropertyHandler) (*RefreshableFileDataSource, error) {
ds := &RefreshableFileDataSource{
sourceFilePath: sourceFilePath,
handlers: handlers,
}
return ds, ds.Initialize()
}

// return idx if existed, else return -1
func (s *RefreshableFileDataSource) indexOfHandler(h datasource.PropertyHandler) int {
for idx, handler := range s.handlers {
if handler == h {
return idx
}
}
return -1
}

func (s *RefreshableFileDataSource) AddPropertyHandler(h datasource.PropertyHandler) {
if s.indexOfHandler(h) < 0 {
return
}
s.handlers = append(s.handlers, h)
}

func (s *RefreshableFileDataSource) RemovePropertyHandler(h datasource.PropertyHandler) {
idx := s.indexOfHandler(h)
if idx < 0 {
return
}
s.handlers = append(s.handlers[:idx], s.handlers[idx+1:]...)
}

func (s *RefreshableFileDataSource) ReadSource() ([]byte, error) {
f, err := os.Open(s.sourceFilePath)
defer f.Close()

if err != nil {
return nil, errors.Errorf("The rules file is not existed, err:%+v.", errors.WithStack(err))
}
src, err := ioutil.ReadAll(f)
if err != nil {
return nil, errors.Errorf("Fail to read file, err: %+v.", errors.WithStack(err))
}
return src, nil
}

func (s *RefreshableFileDataSource) Initialize() error {
s.doUpdate()

watcher, err := fsnotify.NewWatcher()
if err != nil {
return errors.Errorf("Fail to new a watcher of fsnotify, err:%+v", err)
}
err = watcher.Add(s.sourceFilePath)
if err != nil {
return errors.Errorf("Fail add a watcher on file(%s), err:%+v", s.sourceFilePath, err)
}

go util.RunWithRecover(func() {
defer watcher.Close()
for {
select {
case ev := <-watcher.Events:
if ev.Op&fsnotify.Write == fsnotify.Write {
s.doUpdate()
}

if ev.Op&fsnotify.Remove == fsnotify.Remove || ev.Op&fsnotify.Rename == fsnotify.Rename {
logger.Errorf("The file source(%s) was removed or renamed.", s.sourceFilePath)
for _, h := range s.handlers {
err := h.Handle(nil)
if err != nil {
logger.Errorf("RefreshableFileDataSource fail to publish rules, handle:%+v; err=%+v.", h, err)
}
}
}
case err := <-watcher.Errors:
logger.Errorf("Watch err on file(%s), err:", s.sourceFilePath, err)
time.Sleep(time.Second * 3)
}
}
}, logger)
return nil
}

func (s *RefreshableFileDataSource) doUpdate() {
src, err := s.ReadSource()
if err != nil {
logger.Errorf("%+v", err)
return
}
for _, h := range s.handlers {
err := h.Handle(src)
if err != nil {
logger.Errorf("RefreshableFileDataSource fail to publish rules, handle:%+v; err=%+v.", h, err)
}
}
}

func (s *RefreshableFileDataSource) Close() error {
return nil
}
19 changes: 19 additions & 0 deletions ext/datasource/refreshable_file/file_datasource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package refreshable_file

import (
"github.com/alibaba/sentinel-golang/ext/datasource"
"testing"
"time"
)

func TestNewFileDataSource_FlowRule(t *testing.T) {
ds, _ := FileDataSourceStarter("../../../tests/testdata/extension/refreshable_file/FlowRule.json", datasource.NewFlowRulesHandler(datasource.FlowRulesJsonConverter))
time.Sleep(5 * time.Second)
ds.Close()
}

func TestNewFileDataSource_SystemRule(t *testing.T) {
ds, _ := FileDataSourceStarter("../../../tests/testdata/extension/refreshable_file/SystemRule.json", datasource.NewSystemRulesHandler(datasource.SystemRulesJsonConverter))
time.Sleep(5 * time.Second)
ds.Close()
}
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ go 1.13
require (
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/apache/dubbo-go v0.1.2-0.20200224151332-dd1a3c24d656
github.com/fsnotify/fsnotify v1.4.7
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/google/uuid v1.1.1
github.com/pkg/errors v0.8.1
github.com/shirou/gopsutil v2.19.12+incompatible
github.com/stretchr/testify v1.4.0
github.com/tidwall/gjson v1.5.0
go.uber.org/multierr v1.5.0 // indirect
golang.org/x/sys v0.0.0-20200107162124-548cf772de50 // indirect
gopkg.in/yaml.v2 v2.2.2
go.uber.org/multierr v1.5.0
)
15 changes: 7 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest v10.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v10.15.3+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Jeffail/gabs v1.1.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
Expand Down Expand Up @@ -75,6 +76,7 @@ github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v0.0.0-20180123065059-ebf56d35bba7/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
Expand Down Expand Up @@ -114,8 +116,6 @@ github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:od
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20180828235145-f29afc2cceca/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
Expand Down Expand Up @@ -291,12 +291,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8=
github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k=
github.com/tidwall/gjson v1.5.0 h1:QCssIUI7J0RStkzIcI4A7O6P8rDA5wi5IPf70uqKSxg=
github.com/tidwall/gjson v1.5.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
Expand All @@ -313,6 +307,7 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
Expand All @@ -323,6 +318,7 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -337,6 +333,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down Expand Up @@ -371,6 +368,7 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20180829000535-087779f1d2c9/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
Expand Down Expand Up @@ -403,6 +401,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
istio.io/gogo-genproto v0.0.0-20190124151557-6d926a6e6feb/go.mod h1:eIDJ6jNk/IeJz6ODSksHl5Aiczy5JUq6vFhJWI5OtiI=
k8s.io/api v0.0.0-20180806132203-61b11ee65332/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
Expand Down
47 changes: 47 additions & 0 deletions tests/testdata/extension/refreshable_file/FlowRule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[
{
"id": 0,
"resource": "abc0",
"limitApp": "default",
"grade": 1,
"strategy": 0,
"controlBehavior": 0,
"refResource": "refDefault",
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 1000,
"clusterMode": false,
"clusterConfig": {
"thresholdType": 0
}
},
{
"id": 1,
"resource": "abc1",
"limitApp": "default",
"grade": 1,
"strategy": 0,
"controlBehavior": 0,
"refResource": "refDefault",
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 1000,
"clusterMode": false,
"clusterConfig": {
"thresholdType": 0
}
},
{
"id": 2,
"resource": "abc2",
"limitApp": "default",
"grade": 1,
"strategy": 0,
"controlBehavior": 0,
"refResource": "refDefault",
"warmUpPeriodSec": 10,
"maxQueueingTimeMs": 1000,
"clusterMode": false,
"clusterConfig": {
"thresholdType": 0
}
}
]
17 changes: 17 additions & 0 deletions tests/testdata/extension/refreshable_file/SystemRule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"id": 0,
"metricType": 0,
"adaptiveStrategy": 0
},
{
"id": 1,
"metricType": 0,
"adaptiveStrategy": 0
},
{
"id": 2,
"metricType": 0,
"adaptiveStrategy": 0
}
]

0 comments on commit c6b1fc1

Please sign in to comment.