Skip to content

Commit

Permalink
feat: cmdline supports to get multiple kv details (#70)
Browse files Browse the repository at this point in the history
* feat: cmdline supports to get multiple kv details

* refactor: get kv details in client side
  • Loading branch information
fireyun committed Jan 31, 2024
1 parent 44263b9 commit 7dc14ec
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 13 deletions.
6 changes: 3 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ type Client interface {
ListApps(match []string) ([]*pbfs.App, error)
// PullFiles pull files from remote
PullFiles(app string, opts ...AppOption) (*Release, error)
// Get KV release from remote
// PullKvs pull KV release from remote
PullKvs(app string, match []string, opts ...AppOption) (*Release, error)
// Pull Key Value from remote
// Get gets Key Value from remote
Get(app string, key string, opts ...AppOption) (string, error)
// AddWatcher add a watcher to client
AddWatcher(callback Callback, app string, opts ...AppOption) error
Expand Down Expand Up @@ -216,7 +216,7 @@ func (c *client) PullFiles(app string, opts ...AppOption) (*Release, error) {
return r, nil
}

// GetRelease get release from remote
// PullKvs get release from remote
func (c *client) PullKvs(app string, match []string, opts ...AppOption) (*Release, error) {
option := &AppOptions{}
for _, opt := range opts {
Expand Down
82 changes: 75 additions & 7 deletions cmd/bscp/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"encoding/json"
"fmt"
"os"
"sync"

"github.com/spf13/cobra"

Expand All @@ -28,9 +29,10 @@ var (
)

const (
outputFormatTable = ""
outputFormatJson = "json"
outputFormatValue = "value"
outputFormatTable = ""
outputFormatJson = "json"
outputFormatValue = "value"
outputFormatValueJson = "value_json"
)

var (
Expand Down Expand Up @@ -90,7 +92,7 @@ func init() {
// kv 参数
getKvCmd.Flags().StringVarP(&appName, "app", "a", "", "app name")
getKvCmd.Flags().StringVarP(&labelsStr, "labels", "l", "", "labels")
getKvCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "output format, One of: json|value")
getKvCmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "output format, One of: json|value|value_json")
}

// runGetApp executes the get app command.
Expand Down Expand Up @@ -187,6 +189,69 @@ func runGetKvValue(bscp client.Client, app, key string) error {
return err
}

func runGetKvValues(bscp client.Client, app string, keys []string) error {
release, err := bscp.PullKvs(app, []string{}, client.WithAppLabels(labels))
if err != nil {
return err
}
kvTypeMap := make(map[string]string)
isAll := false
if len(keys) == 0 {
isAll = true
}
for _, k := range release.KvItems {
kvTypeMap[k.Key] = k.KvType
if isAll {
keys = append(keys, k.Key)
}
}

values, hitError := getKvValues(bscp, app, keys)
if hitError != nil {
return hitError
}

output := make(map[string]any, len(keys))
for idx, key := range keys {
output[key] = map[string]string{
"kv_type": kvTypeMap[key],
"value": values[idx],
}
}

return jsonOutput(output)
}

// getKvValues get kv values concurrently
func getKvValues(bscp client.Client, app string, keys []string) ([]string, error) {
var hitError error
values := make([]string, len(keys))
pipe := make(chan struct{}, 10)
wg := sync.WaitGroup{}

for idx, key := range keys {
wg.Add(1)

pipe <- struct{}{}
go func(idx int, key string) {
defer func() {
wg.Done()
<-pipe
}()

value, err := bscp.Get(app, key, client.WithAppLabels(labels))
if err != nil {
hitError = fmt.Errorf("get kv value failed for key: %s, err:%v", key, err)
return
}
values[idx] = value
}(idx, key)
}
wg.Wait()

return values, hitError
}

// runGetKv executes the get kv command.
func runGetKv(args []string) error {
baseConf, err := initBaseConf()
Expand All @@ -208,15 +273,18 @@ func runGetKv(args []string) error {
return err
}

if outputFormat == outputFormatValue {
switch outputFormat {
case outputFormatValue:
if len(args) == 0 {
return fmt.Errorf("res must not be empty")
}
if len(args) > 1 {
return fmt.Errorf("multiple res are not supported")
}
return runGetKvValue(bscp, appName, args[0])
case outputFormatValueJson:
return runGetKvValues(bscp, appName, args)
default:
return runGetListKv(bscp, appName, args)
}

return runGetListKv(bscp, appName, args)
}
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bscp sdk examples
添加环境变量
```bash
# FEED 地址
export BSCP_FEED_ADDR="bscp-feed.example.com:9510"
export BSCP_FEED_ADDRS="bscp-feed.example.com:9510"
# 服务密钥 Token, 记得需要关联配置文件
export BSCP_TOKEN="xxx"
# 当前业务
Expand Down
2 changes: 1 addition & 1 deletion examples/kv-ctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func execute() {
} else {
result := map[string]string{}
if len(keySlice) == 0 {
release, err := bscp.PullKvs(appName, opts...)
release, err := bscp.PullKvs(appName, []string{}, opts...)
if err != nil {
slog.Error("pull kv failed", logger.ErrAttr(err))
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion internal/upstream/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (uc *upstreamClient) GetDownloadURL(vas *kit.Vas, req *pbfs.GetDownloadURLR
return uc.client.GetDownloadURL(vas.Ctx, req)
}

// GetKvValue get the kvs value from upstream feed server.
// GetKvValue get the kv value from upstream feed server.
func (uc *upstreamClient) GetKvValue(vas *kit.Vas, req *pbfs.GetKvValueReq) (*pbfs.GetKvValueResp, error) {
if err := uc.wait.WaitWithContext(vas.Ctx); err != nil {
return nil, err
Expand Down

0 comments on commit 7dc14ec

Please sign in to comment.