From 2adcf4768f79775629f790d055c9bf97e07eb48b Mon Sep 17 00:00:00 2001 From: Moses Narrow Date: Sat, 21 Sep 2024 15:38:37 -0500 Subject: [PATCH 01/17] remove the hardcoded defaults from skywire-utilities --- cmd/skywire-cli/commands/config/dmsghttp.go | 97 ------------- cmd/skywire-cli/commands/config/gen.go | 153 +++++--------------- cmd/skywire-cli/commands/config/root.go | 7 +- cmd/skywire-cli/commands/config/services.go | 5 +- cmd/skywire-cli/commands/log/log.go | 16 +- cmd/skywire-cli/commands/log/root.go | 2 + cmd/skywire-cli/commands/mdisc/root.go | 18 ++- cmd/skywire-cli/commands/proxy/proxy.go | 16 +- cmd/skywire-cli/commands/proxy/root.go | 2 + cmd/skywire-cli/commands/rewards/ui.go | 17 ++- cmd/skywire-cli/commands/route/route.go | 25 +++- cmd/skywire-cli/commands/survey/root.go | 12 +- cmd/skywire-cli/commands/tp/tp.go | 22 ++- cmd/skywire-cli/commands/ut/root.go | 11 +- cmd/skywire-cli/commands/vpn/vvpn.go | 19 ++- pkg/app/appdisc/factory.go | 13 +- pkg/visor/init.go | 13 +- pkg/visor/visorconfig/config.go | 51 +++---- pkg/visor/visorconfig/hypervisorconfig.go | 19 ++- pkg/visor/visorconfig/services.go | 6 + skywire.go | 27 ++++ 21 files changed, 251 insertions(+), 300 deletions(-) delete mode 100644 cmd/skywire-cli/commands/config/dmsghttp.go diff --git a/cmd/skywire-cli/commands/config/dmsghttp.go b/cmd/skywire-cli/commands/config/dmsghttp.go deleted file mode 100644 index 4bd97f3f5e..0000000000 --- a/cmd/skywire-cli/commands/config/dmsghttp.go +++ /dev/null @@ -1,97 +0,0 @@ -// Package cliconfig cmd/skywire-cli/commands/config/dmsghttp.go -package cliconfig - -import ( - "context" - "encoding/json" - "io" - "net/http" - "os" - - "github.com/spf13/cobra" - - "github.com/skycoin/skywire-utilities/pkg/cmdutil" - "github.com/skycoin/skywire-utilities/pkg/httputil" - "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire-utilities/pkg/skyenv" -) - -var dmsghttpPath string - -func init() { - updateCmd.AddCommand(dmsghttpCmd) - dmsghttpCmd.Flags().SortFlags = false - //TODO: fix path for non linux package defaults - dmsghttpCmd.Flags().StringVarP(&dmsghttpPath, "path", "p", "/opt/skywire/dmsghttp-config.json", "path of dmsghttp-config file, default is for pkg installation") -} - -var dmsghttpCmd = &cobra.Command{ - Use: "dmsghttp", - Short: "update dmsghttp-config.json file from config bootstrap service", - Run: func(cmd *cobra.Command, args []string) { //nolint - log := logging.MustGetLogger("dmsghttp_updater") - - ctx, cancel := cmdutil.SignalContext(context.Background(), log) - defer cancel() - go func() { - <-ctx.Done() - cancel() - os.Exit(1) - }() - dmsghttpConf, err := fetchDmsghttpConf() - if err != nil { - log.WithError(err).Error("Cannot fetching updated dmsghttp-config data") - } - - file, err := json.MarshalIndent(dmsghttpConf, "", " ") - if err != nil { - log.WithError(err).Error("Error accurs during marshal content to json file") - } - - err = os.WriteFile(dmsghttpPath, file, 0600) - if err != nil { - log.WithError(err).Errorf("Cannot save new dmsghttp-config.json file at %s", dmsghttpPath) - } - }, -} - -type dmsghttpConf struct { //nolint - Test httputil.DMSGHTTPConf `json:"test"` - Prod httputil.DMSGHTTPConf `json:"prod"` -} - -func fetchDmsghttpConf() (dmsghttpConf, error) { - var newConf dmsghttpConf - var prodConf httputil.DMSGHTTPConf - prodResp, err := http.Get(skyenv.ServiceConfAddr + "/dmsghttp") - if err != nil { - return newConf, err - } - defer prodResp.Body.Close() //nolint - body, err := io.ReadAll(prodResp.Body) - if err != nil { - return newConf, err - } - err = json.Unmarshal(body, &prodConf) - if err != nil { - return newConf, err - } - newConf.Prod = prodConf - - var testConf httputil.DMSGHTTPConf - testResp, err := http.Get(skyenv.TestServiceConfAddr + "/dmsghttp") - if err != nil { - return newConf, err - } - defer testResp.Body.Close() //nolint - body, err = io.ReadAll(testResp.Body) - if err != nil { - return newConf, err - } - err = json.Unmarshal(body, &testConf) - if err != nil { - return newConf, err - } - newConf.Test = testConf - return newConf, nil -} diff --git a/cmd/skywire-cli/commands/config/gen.go b/cmd/skywire-cli/commands/config/gen.go index 4eeb8436ba..7dfb312909 100644 --- a/cmd/skywire-cli/commands/config/gen.go +++ b/cmd/skywire-cli/commands/config/gen.go @@ -22,7 +22,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/buildinfo" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/netutil" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/pkg/app/appserver" "github.com/skycoin/skywire/pkg/dmsgc" "github.com/skycoin/skywire/pkg/routing" @@ -72,7 +71,7 @@ func init() { genConfigCmd.Flags().SortFlags = false RootCmd.AddCommand(genConfigCmd, genKeysCmd, checkPKCmd) - genConfigCmd.Flags().StringVarP(&serviceConfURL, "url", "a", scriptExecArray(fmt.Sprintf("${SVCCONFADDR[@]-%s}", utilenv.ServiceConfAddr)), "services conf url\n\r") + genConfigCmd.Flags().StringVarP(&serviceConfURL, "url", "a", scriptExecArray(fmt.Sprintf("${SVCCONFADDR[@]-%s}", serviceConfURL)), "services conf url\n\r") gHiddenFlags = append(gHiddenFlags, "url") genConfigCmd.Flags().StringVar(&logLevel, "loglvl", scriptExecString("${LOGLVL:-info}"), "level of logging in config\033[0m") gHiddenFlags = append(gHiddenFlags, "loglvl") @@ -302,7 +301,7 @@ var genConfigCmd = &cobra.Command{ } //use test deployment if isTestEnv { - serviceConfURL = utilenv.TestServiceConfAddr + serviceConfURL = testServiceConfURL } var err error if isDmsgHTTP { @@ -391,13 +390,19 @@ var genConfigCmd = &cobra.Command{ isStdout = false } - if !noFetch { + //determine best protocol + if isBestProtocol && netutil.LocalProtocol() { + disablePublicAutoConn = true + isDmsgHTTP = true + } + + if !noFetch && !isDmsgHTTP { // create an http client to fetch the services client := http.Client{ Timeout: time.Second * 15, // Timeout after 15 seconds } if serviceConfURL == "" { - serviceConfURL = utilenv.ServiceConfAddr + serviceConfURL = "http://" } if !isStdout { log.Infof("Fetching service endpoints from %s", serviceConfURL) @@ -516,11 +521,7 @@ var genConfigCmd = &cobra.Command{ } } - //determine best protocol - if isBestProtocol && netutil.LocalProtocol() { - disablePublicAutoConn = true - isDmsgHTTP = true - } + //generate the common config containing public & secret keys u := buildinfo.Version() x := u @@ -546,8 +547,6 @@ var genConfigCmd = &cobra.Command{ conf.Common.SK = sk conf.Common.PK = pk - dnsServer := utilenv.DNSServer - if services.DNSServer != "" { dnsServer = services.DNSServer } @@ -581,12 +580,8 @@ var genConfigCmd = &cobra.Command{ // If nothing was fetched if services.SurveyWhitelist == nil { // By default - if !noDefaults { - // set the hardcoded defaults from skywire-utilities for the service public keys - if err := surveyWlPKs.Set(utilenv.SurveyWhitelistPKs); err != nil { - log.Fatalf("Failed to unmarshal survey whitelist public keys: %v", err) - } - } + log.Error("Services were not fetched from default conf service URL") + } //if the flag is not empty if surveyWhitelistPKs != "" { @@ -597,109 +592,29 @@ var genConfigCmd = &cobra.Command{ } services.SurveyWhitelist = append(services.SurveyWhitelist, surveyWlPKs...) - if !isTestEnv { - if services.DmsgDiscovery == "" { - services.DmsgDiscovery = utilenv.DmsgDiscAddr - } - if services.DmsgDiscovery == "" { - services.DmsgDiscovery = utilenv.DmsgDiscAddr - } - if services.TransportDiscovery == "" { - services.TransportDiscovery = utilenv.TpDiscAddr - } - if services.AddressResolver == "" { - services.AddressResolver = utilenv.AddressResolverAddr - } - if services.RouteFinder == "" { - services.RouteFinder = utilenv.RouteFinderAddr - } - if services.UptimeTracker == "" { - services.UptimeTracker = utilenv.UptimeTrackerAddr - } - if services.ServiceDiscovery == "" { - services.ServiceDiscovery = utilenv.ServiceDiscAddr - } - if services.StunServers == nil { - services.StunServers = utilenv.GetStunServers() - } - if services.DNSServer == "" { - services.DNSServer = utilenv.DNSServer - } - if routeSetupNodes != "" { - if err := routeSetupPKs.Set(routeSetupNodes); err != nil { - log.Fatalf("bad key set for route setup node flag: %v", err) - } - } - if services.RouteSetupNodes == nil { - if !noDefaults { - if err := routeSetupPKs.Set(utilenv.RouteSetupPKs); err != nil { - log.Fatalf("Failed to unmarshal route setup-node public keys: %v", err) - } - } - } - services.RouteSetupNodes = append(services.RouteSetupNodes, routeSetupPKs...) - if transportSetupPKs != "" { - if err := tpSetupPKs.Set(transportSetupPKs); err != nil { - log.Fatalf("bad key set for transport setup node flag: %v", err) - } - } - if services.TransportSetupPKs == nil { - if !noDefaults { - if err := tpSetupPKs.Set(utilenv.TPSetupPKs); err != nil { - log.Fatalf("Failed to unmarshal transport setup-node public keys: %v", err) - } - } - } - services.TransportSetupPKs = append(services.TransportSetupPKs, tpSetupPKs...) - } else { - if services.DmsgDiscovery == "" { - services.DmsgDiscovery = utilenv.TestDmsgDiscAddr - } - if services.TransportDiscovery == "" { - services.TransportDiscovery = utilenv.TestTpDiscAddr - } - if services.AddressResolver == "" { - services.AddressResolver = utilenv.TestAddressResolverAddr - } - if services.RouteFinder == "" { - services.RouteFinder = utilenv.TestRouteFinderAddr - } - if services.UptimeTracker == "" { - services.UptimeTracker = utilenv.TestUptimeTrackerAddr - } - if services.ServiceDiscovery == "" { - services.ServiceDiscovery = utilenv.TestServiceDiscAddr - } - if services.StunServers == nil { - services.StunServers = utilenv.GetStunServers() - } - if services.DNSServer == "" { - services.DNSServer = utilenv.DNSServer - } - if routeSetupNodes != "" { - if err := routeSetupPKs.Set(routeSetupNodes); err != nil { - log.Fatalf("bad key set for route setup node flag: %v", err) - } - } - if services.RouteSetupNodes == nil { - if err := routeSetupPKs.Set(utilenv.TestRouteSetupPKs); err != nil { - log.Fatalf("Failed to unmarshal route setup-node public keys: %v", err) - } - } - services.RouteSetupNodes = append(services.RouteSetupNodes, routeSetupPKs...) - if transportSetupPKs != "" { - if err := tpSetupPKs.Set(transportSetupPKs); err != nil { - log.Fatalf("bad key set for transport setup node flag: %v", err) - } + if services.DmsgDiscovery == "" { + log.Fatalf("Dmsg Discovery not set") + } + if services.TransportDiscovery == "" { + log.Fatalf("Transport Discovery not set") + } + if routeSetupNodes != "" { + if err := routeSetupPKs.Set(routeSetupNodes); err != nil { + log.Fatalf("bad key set for route setup node flag: %v", err) } - if services.TransportSetupPKs == nil { - if !noDefaults { - if err := tpSetupPKs.Set(utilenv.TestTPSetupPKs); err != nil { - log.Fatalf("Failed to unmarshal transport setup-node public keys: %v", err) - } - } + } + services.RouteSetupNodes = append(services.RouteSetupNodes, routeSetupPKs...) + if services.RouteSetupNodes == nil { + log.Fatalf("Route Setup node not set") + } + if transportSetupPKs != "" { + if err := tpSetupPKs.Set(transportSetupPKs); err != nil { + log.Fatalf("bad key set for transport setup node flag: %v", err) } - services.TransportSetupPKs = append(services.TransportSetupPKs, tpSetupPKs...) + } + services.TransportSetupPKs = append(services.TransportSetupPKs, tpSetupPKs...) + if services.TransportSetupPKs == nil { + log.Fatalf("Route Setup node not set") } conf.Dmsg = &dmsgc.DmsgConfig{ diff --git a/cmd/skywire-cli/commands/config/root.go b/cmd/skywire-cli/commands/config/root.go index d08fc195e9..c57cccf24c 100644 --- a/cmd/skywire-cli/commands/config/root.go +++ b/cmd/skywire-cli/commands/config/root.go @@ -12,7 +12,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/pkg/visor/visorconfig" ) @@ -55,7 +54,9 @@ var ( selectedOS string disableApps string isBestProtocol bool - serviceConfURL string + serviceConfURL = "http://conf.skywire.skycoin.com" + testServiceConfURL = "http://conf.skywire.dev" + dnsServer = "1.1.1.1" services visorconfig.Services servicesConfig servicesConf isForce bool @@ -64,8 +65,6 @@ var ( isOutUnset bool ver string isRoot = visorconfig.IsRoot() - svcConf = strings.ReplaceAll(utilenv.ServiceConfAddr, "http://", "") //visorconfig.DefaultServiceConfAddr - testConf = strings.ReplaceAll(utilenv.TestServiceConfAddr, "http://", "") //visorconfig.DefaultServiceConfAddr gHiddenFlags []string uHiddenFlags []string binPath string diff --git a/cmd/skywire-cli/commands/config/services.go b/cmd/skywire-cli/commands/config/services.go index 96c96dafc9..b76a813df9 100644 --- a/cmd/skywire-cli/commands/config/services.go +++ b/cmd/skywire-cli/commands/config/services.go @@ -12,7 +12,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/pkg/visor/visorconfig" ) @@ -57,7 +56,7 @@ var servicesCmd = &cobra.Command{ func fetchServicesConf() (servicesConf, error) { var newConf servicesConf var prodConf visorconfig.Services - prodResp, err := http.Get(skyenv.ServiceConfAddr) + prodResp, err := http.Get(serviceConfURL) if err != nil { return newConf, err } @@ -73,7 +72,7 @@ func fetchServicesConf() (servicesConf, error) { newConf.Prod = prodConf var testConf visorconfig.Services - testResp, err := http.Get(skyenv.TestServiceConfAddr) + testResp, err := http.Get(testServiceConfURL) if err != nil { return newConf, err } diff --git a/cmd/skywire-cli/commands/log/log.go b/cmd/skywire-cli/commands/log/log.go index 087898cf6a..d7f12e8c6c 100644 --- a/cmd/skywire-cli/commands/log/log.go +++ b/cmd/skywire-cli/commands/log/log.go @@ -22,13 +22,23 @@ import ( "github.com/skycoin/dmsg/pkg/dmsghttp" "github.com/spf13/cobra" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire-utilities/pkg/skyenv" ) func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + dmsgDiscURL = services.DmsgDiscovery + utURL = services.UptimeTracker + } + } + logCmd.Flags().SortFlags = false logCmd.Flags().BoolVarP(&logOnly, "log", "l", false, "fetch only transport logs") logCmd.Flags().BoolVarP(&surveyOnly, "survey", "v", false, "fetch only surveys") @@ -42,8 +52,8 @@ func init() { logCmd.Flags().BoolVar(&allVisors, "all", false, "consider all visors ; no version filtering") logCmd.Flags().IntVar(&batchSize, "batchSize", 50, "number of visor in each batch") logCmd.Flags().Int64Var(&maxFileSize, "maxfilesize", 1024, "maximum file size allowed to download during collecting logs, in KB") - logCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", skyenv.DmsgDiscAddr, "dmsg discovery url\n") - logCmd.Flags().StringVarP(&utAddr, "ut", "u", skyenv.UptimeTrackerAddr, "uptime tracker url\n") + logCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", dmsgDiscURL, "dmsg discovery url\n") + logCmd.Flags().StringVarP(&utAddr, "ut", "u", utURL, "uptime tracker url\n") if os.Getenv("DMSGCURL_SK") != "" { sk.Set(os.Getenv("DMSGCURL_SK")) //nolint } diff --git a/cmd/skywire-cli/commands/log/root.go b/cmd/skywire-cli/commands/log/root.go index 0056d54cfb..4a9740907c 100644 --- a/cmd/skywire-cli/commands/log/root.go +++ b/cmd/skywire-cli/commands/log/root.go @@ -6,6 +6,8 @@ import ( ) var ( + dmsgDiscURL string + utURL string pubKey string duration int minv string diff --git a/cmd/skywire-cli/commands/mdisc/root.go b/cmd/skywire-cli/commands/mdisc/root.go index 6d60a85757..d21b43e76a 100644 --- a/cmd/skywire-cli/commands/mdisc/root.go +++ b/cmd/skywire-cli/commands/mdisc/root.go @@ -18,7 +18,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/cmd/skywire-cli/internal" ) @@ -27,6 +26,8 @@ var ( cacheFilesAge int mdURL string isStats bool + dmsgDiscURL string + ) // var allEntries bool @@ -34,6 +35,15 @@ var masterLogger = logging.NewMasterLogger() var packageLogger = masterLogger.PackageLogger("mdisc:disc") func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + dmsgDiscURL = services.DmsgDiscovery + utURL = services.UptimeTracker + } + } RootCmd.AddCommand( entryCmd, availableServersCmd, @@ -41,9 +51,9 @@ func init() { RootCmd.Flags().StringVar(&cacheFileDMSGD, "cfu", os.TempDir()+"/dmsgd.json", "DMSGD cache file location.") RootCmd.Flags().IntVarP(&cacheFilesAge, "cfa", "m", 5, "update cache file if older than n minutes") RootCmd.Flags().BoolVarP(&isStats, "stats", "s", false, "count the number of results") - entryCmd.Flags().StringVar(&mdURL, "url", utilenv.DmsgDiscAddr, "specify alternative DMSG discovery url") - RootCmd.Flags().StringVar(&mdURL, "url", utilenv.DmsgDiscAddr, "specify alternative DMSG discovery url") - availableServersCmd.Flags().StringVar(&mdURL, "url", utilenv.DmsgDiscAddr, "specify alternative DMSG discovery url") + entryCmd.Flags().StringVar(&mdURL, "url", dmsgDiscURL, "specify alternative DMSG discovery url") + RootCmd.Flags().StringVar(&mdURL, "url", dmsgDiscURL, "specify alternative DMSG discovery url") + availableServersCmd.Flags().StringVar(&mdURL, "url", dmsgDiscURL, "specify alternative DMSG discovery url") } // RootCmd is the command that contains sub-commands which interacts with DMSG services. diff --git a/cmd/skywire-cli/commands/proxy/proxy.go b/cmd/skywire-cli/commands/proxy/proxy.go index 69feb29381..720765c039 100644 --- a/cmd/skywire-cli/commands/proxy/proxy.go +++ b/cmd/skywire-cli/commands/proxy/proxy.go @@ -17,7 +17,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/buildinfo" "github.com/skycoin/skywire-utilities/pkg/cmdutil" - "github.com/skycoin/skywire-utilities/pkg/skyenv" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/app/appserver" @@ -258,12 +257,21 @@ var statusCmd = &cobra.Command{ var isLabel bool func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + svcDiscURL = services.DmsgDiscovery + utURL = services.UptimeTracker + } + } if version == "unknown" { version = "" //nolint } version = strings.Split(version, "-")[0] - listCmd.Flags().StringVarP(&utURL, "uturl", "w", skyenv.UptimeTrackerAddr, "uptime tracker url") - listCmd.Flags().StringVarP(&sdURL, "sdurl", "a", skyenv.ServiceDiscAddr, "service discovery url") + listCmd.Flags().StringVarP(&utURL, "uturl", "w", utURL, "uptime tracker url") + listCmd.Flags().StringVarP(&sdURL, "sdurl", "a", svcDiscURL, "service discovery url") listCmd.Flags().BoolVarP(&rawData, "raw", "r", false, "print raw data") listCmd.Flags().BoolVarP(&noFilterOnline, "noton", "o", false, "do not filter by online status in UT") listCmd.Flags().StringVar(&cacheFileSD, "cfs", os.TempDir()+"/proxysd.json", "SD cache file location") @@ -280,7 +288,7 @@ func init() { var listCmd = &cobra.Command{ Use: "list", Short: "List servers", - Long: fmt.Sprintf("List %v servers from service discovery\n%v/api/services?type=%v\n%v/api/services?type=%v&country=US\n\nSet cache file location to \"\" to avoid using cache files", serviceType, skyenv.ServiceDiscAddr, serviceType, skyenv.ServiceDiscAddr, serviceType), + Long: fmt.Sprintf("List %v servers from service discovery\n%v/api/services?type=%v\n%v/api/services?type=%v&country=US\n\nSet cache file location to \"\" to avoid using cache files", serviceType, svcDiscURL, serviceType, svcDiscURL, serviceType), Run: func(cmd *cobra.Command, args []string) { sds := internal.GetData(cacheFileSD, sdURL+"/api/services?type="+serviceType, cacheFilesAge) if rawData { diff --git a/cmd/skywire-cli/commands/proxy/root.go b/cmd/skywire-cli/commands/proxy/root.go index 0caa1ee242..5413bc741e 100644 --- a/cmd/skywire-cli/commands/proxy/root.go +++ b/cmd/skywire-cli/commands/proxy/root.go @@ -32,6 +32,8 @@ var ( addr string startingTimeout int httpAddr string + svcDiscURL string + utURL string ) // RootCmd contains commands that interact with the skywire-visor diff --git a/cmd/skywire-cli/commands/rewards/ui.go b/cmd/skywire-cli/commands/rewards/ui.go index 5fdd7686e4..eb74b032ca 100644 --- a/cmd/skywire-cli/commands/rewards/ui.go +++ b/cmd/skywire-cli/commands/rewards/ui.go @@ -32,10 +32,17 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire-utilities/pkg/skyenv" ) func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + dmsgDiscURL = services.DmsgDiscovery + } + } RootCmd.CompletionOptions.DisableDefaultCmd = true RootCmd.AddCommand( uiCmd, @@ -48,7 +55,7 @@ func init() { msg += "\n\r" } uiCmd.Flags().StringVarP(&wl, "wl", "w", scriptExecArray("${REWARDPKS[@]}"), msg) - uiCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", "", "dmsg discovery url default:\n"+skyenv.DmsgDiscAddr) + uiCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", "", "dmsg discovery url default:\n"+dmsgDiscURL) uiCmd.Flags().StringVarP(&ensureOnlineURL, "ensure-online", "O", scriptExecString("${ENSUREONLINE}"), "Exit when the specified URL cannot be fetched;\ni.e. https://fiber.skywire.dev") if os.Getenv("DMSGHTTP_SK") != "" { sk.Set(os.Getenv("DMSGHTTP_SK")) //nolint @@ -93,6 +100,8 @@ var ( wlkeys []cipher.PubKey webPort uint ensureOnlineURL string + dmsgDiscURL string + ) var skyenvfile = os.Getenv("SKYENV") @@ -240,10 +249,10 @@ var tmpl *htmpl.Template func server() { + log := logging.MustGetLogger("dmsghttp") if dmsgDisc == "" { - dmsgDisc = skyenv.DmsgDiscAddr + log.Fatal("Dmsg Discovery URL not specified") } - log := logging.MustGetLogger("dmsghttp") ctx, cancel := cmdutil.SignalContext(context.Background(), log) defer cancel() diff --git a/cmd/skywire-cli/commands/route/route.go b/cmd/skywire-cli/commands/route/route.go index fa19fb0423..7ecc1c3669 100644 --- a/cmd/skywire-cli/commands/route/route.go +++ b/cmd/skywire-cli/commands/route/route.go @@ -18,27 +18,38 @@ import ( "golang.org/x/net/context" "github.com/skycoin/skywire-utilities/pkg/cipher" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/routefinder/rfclient" "github.com/skycoin/skywire/pkg/router" "github.com/skycoin/skywire/pkg/routing" + "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire/pkg/skyenv" "github.com/skycoin/skywire/pkg/visor/visorconfig" ) -var frAddr string -var frMinHops, frMaxHops uint16 -var timeout time.Duration -var skywireconfig string +var ( + frAddr string + frMinHops, frMaxHops uint16 + timeout time.Duration + skywireconfig string + rfURL string +) func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + rfURL = services.RouteFinderAddr + } + } findCmd.Flags().SortFlags = false findCmd.Flags().Uint16VarP(&frMinHops, "min", "n", 1, "minimum hops") findCmd.Flags().Uint16VarP(&frMaxHops, "max", "x", 1000, "maximum hops") findCmd.Flags().DurationVarP(&timeout, "timeout", "t", 10*time.Second, "request timeout") - findCmd.Flags().StringVarP(&frAddr, "addr", "a", "", "route finder service address\n"+utilenv.RouteFinderAddr) + findCmd.Flags().StringVarP(&frAddr, "addr", "a", rfURL, "route finder service address") } // RootCmd is the command that queries the route finder. @@ -58,7 +69,7 @@ Assumes the local visor public key as an argument if only one argument is given` } //set the routefinder address. It's not used as the default value to fix the display of the help command if frAddr == "" { - frAddr = utilenv.RouteFinderAddr + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Route Finder URL not specified")) } //assume the local public key as the first argument if only 1 argument is given ; resize args array to 2 and move the first argument to the second one if len(args) == 1 { diff --git a/cmd/skywire-cli/commands/survey/root.go b/cmd/skywire-cli/commands/survey/root.go index 813f20e819..9bd18922d1 100644 --- a/cmd/skywire-cli/commands/survey/root.go +++ b/cmd/skywire-cli/commands/survey/root.go @@ -15,7 +15,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/visor/visorconfig" ) @@ -33,12 +32,21 @@ var ( pkgconfigexists bool userconfigexists bool conf *visorconfig.V1 + dmsgDiscURL string ) func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + dmsgDiscURL = services.DmsgDiscovery + } + } surveyCmd.Flags().SortFlags = false surveyCmd.Flags().StringVarP(&confPath, "config", "c", "", "optionl config file to use (i.e.: "+visorconfig.ConfigName+")") - surveyCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", skyenv.DmsgDiscAddr, "value of dmsg discovery") + surveyCmd.Flags().StringVarP(&dmsgDisc, "dmsg-disc", "D", dmsgDiscURL, "value of dmsg discovery") // surveyCmd.Flags().StringVarP(&confArg, "confarg", "C", "", "supply config as argument") // surveyCmd.Flags().BoolVarP(&stdin, "stdin", "n", false, "read config from stdin") if _, err := os.Stat(visorconfig.SkywirePath + "/" + visorconfig.ConfigJSON); err == nil { diff --git a/cmd/skywire-cli/commands/tp/tp.go b/cmd/skywire-cli/commands/tp/tp.go index 19ffa8dda9..7d24d3f640 100644 --- a/cmd/skywire-cli/commands/tp/tp.go +++ b/cmd/skywire-cli/commands/tp/tp.go @@ -22,7 +22,6 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/transport" @@ -37,9 +36,22 @@ var ( logger = logging.MustGetLogger("skywire-cli") removeAll bool tpTypes bool + tpDiscURL string + sdURL string + utURL string ) func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + tpDiscURL = services.TransportDiscovery + sdURL = services.ServiceDiscovery + utURL = services.UptimeTracker + } + } tpCmd.Flags().SortFlags = false addTpCmd.Flags().SortFlags = false rmTpCmd.Flags().SortFlags = false @@ -138,7 +150,7 @@ func init() { addTpCmd.Flags().StringVarP(&rpk, "rpk", "r", "", "remote public key.") addTpCmd.Flags().StringVarP(&transportType, "type", "t", "", "type of transport to add.") addTpCmd.Flags().DurationVarP(&timeout, "timeout", "o", 0, "if specified, sets an operation timeout") - addTpCmd.Flags().StringVarP(&sdURL, "sdurl", "a", utilenv.ServiceDiscAddr, "service discovery url") + addTpCmd.Flags().StringVarP(&sdURL, "sdurl", "a", sdURL, "service discovery url") //TODO // listCmd.Flags().BoolVarP(&queryHealth, "health", "q", false, "check /health of remote visor over dmsg before creating transport") addTpCmd.Flags().BoolVarP(&forceAttempt, "force", "f", false, "attempt transport creation without check of SD") // or visor /health over dmsg @@ -410,8 +422,8 @@ func init() { treeCmd.Flags().StringVarP(&rootNode, "source", "k", "", "root node ; defaults to visor with most transports") treeCmd.Flags().StringVarP(&lastNode, "dest", "d", "", "map route between source and dest") - treeCmd.Flags().StringVarP(&tpdURL, "tpdurl", "a", utilenv.TpDiscAddr, "transport discovery url") - treeCmd.Flags().StringVarP(&utURL, "uturl", "w", utilenv.UptimeTrackerAddr, "uptime tracker url") + treeCmd.Flags().StringVarP(&tpdURL, "tpdurl", "a", tpDiscURL, "transport discovery url") + treeCmd.Flags().StringVarP(&utURL, "uturl", "w", utURL, "uptime tracker url") treeCmd.Flags().BoolVarP(&rawData, "raw", "r", false, "print raw json data") treeCmd.Flags().BoolVarP(&refinedData, "pretty", "p", false, "print pretty json data") treeCmd.Flags().BoolVarP(&noFilterOnline, "noton", "o", false, "do not filter by online status in UT") @@ -427,7 +439,7 @@ func init() { var treeCmd = &cobra.Command{ Use: "tree", Short: "tree map of transports on the skywire network", - Long: fmt.Sprintf("display a tree representation of transports from TPD\n\n%v/all-transports\n\nSet cache file location to \"\" to avoid using cache files", utilenv.TpDiscAddr), + Long: fmt.Sprintf("display a tree representation of transports from TPD\n\n%v/all-transports\n\nSet cache file location to \"\" to avoid using cache files", tpDiscURL), Run: func(cmd *cobra.Command, args []string) { if rootNode != "" { err := rootnode.Set(rootNode) diff --git a/cmd/skywire-cli/commands/ut/root.go b/cmd/skywire-cli/commands/ut/root.go index 402074ce8c..6aaaae2c88 100644 --- a/cmd/skywire-cli/commands/ut/root.go +++ b/cmd/skywire-cli/commands/ut/root.go @@ -8,7 +8,6 @@ import ( "github.com/bitfield/script" "github.com/spf13/cobra" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/cmd/skywire-cli/internal" ) @@ -28,6 +27,14 @@ var ( var minUT int func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + utURL = services.UptimeTracker + } + } utCmd.Flags().StringVarP(&pk, "pk", "k", "", "check uptime for the specified key") utCmd.Flags().BoolVarP(&online, "on", "o", false, "list currently online visors") utCmd.Flags().BoolVarP(&isStats, "stats", "s", false, "count the number of results") @@ -35,7 +42,7 @@ func init() { utCmd.Flags().IntVarP(&minUT, "min", "n", 75, "list visors meeting minimum uptime") utCmd.Flags().StringVar(&cacheFileUT, "cfu", os.TempDir()+"/ut.json", "UT cache file location.") utCmd.Flags().IntVarP(&cacheFilesAge, "cfa", "m", 5, "update cache files if older than n minutes") - utCmd.Flags().StringVarP(&utURL, "url", "u", utilenv.UptimeTrackerAddr, "specify alternative uptime tracker url") + utCmd.Flags().StringVarP(&utURL, "url", "u", utURL, "specify alternative uptime tracker url") } var utCmd = &cobra.Command{ diff --git a/cmd/skywire-cli/commands/vpn/vvpn.go b/cmd/skywire-cli/commands/vpn/vvpn.go index eee5127d2a..4684504abf 100644 --- a/cmd/skywire-cli/commands/vpn/vvpn.go +++ b/cmd/skywire-cli/commands/vpn/vvpn.go @@ -16,7 +16,6 @@ import ( "github.com/tidwall/pretty" "github.com/skycoin/skywire-utilities/pkg/cmdutil" - "github.com/skycoin/skywire-utilities/pkg/skyenv" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/app/appserver" @@ -163,14 +162,26 @@ var statusCmd = &cobra.Command{ } var isLabel bool +var utURL string +var sdURL string + func init() { + log := logging.MustGetLogger("skywire-cli") + var envServices skywire.EnvServices + var services skywire.Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + sdURL = services.ServiceDiscovery + utURL = services.UptimeTracker + } + } if version == "unknown" { version = "" } version = strings.Split(version, "-")[0] - listCmd.Flags().StringVarP(&utURL, "uturl", "w", skyenv.UptimeTrackerAddr, "uptime tracker url") - listCmd.Flags().StringVarP(&sdURL, "sdurl", "a", skyenv.ServiceDiscAddr, "service discovery url") + listCmd.Flags().StringVarP(&utURL, "uturl", "w", utURL, "uptime tracker url") + listCmd.Flags().StringVarP(&sdURL, "sdurl", "a", sdURL, "service discovery url") listCmd.Flags().BoolVarP(&rawData, "raw", "r", false, "print raw data") listCmd.Flags().BoolVarP(&noFilterOnline, "noton", "o", false, "do not filter by online status in UT") listCmd.Flags().StringVar(&cacheFileSD, "cfs", os.TempDir()+"/vpnsd.json", "SD cache file location") @@ -187,7 +198,7 @@ func init() { var listCmd = &cobra.Command{ Use: "list", Short: "List servers", - Long: fmt.Sprintf("List %v servers from service discovery\n%v/api/services?type=%v\n%v/api/services?type=%v&country=US\n\nSet cache file location to \"\" to avoid using cache files", serviceType, skyenv.ServiceDiscAddr, serviceType, skyenv.ServiceDiscAddr, serviceType), + Long: fmt.Sprintf("List %v servers from service discovery\n%v/api/services?type=%v\n%v/api/services?type=%v&country=US\n\nSet cache file location to \"\" to avoid using cache files", serviceType, sdURL, serviceType, sdURL, serviceType), Run: func(cmd *cobra.Command, args []string) { sds := internal.GetData(cacheFileSD, sdURL+"/api/services?type="+serviceType, cacheFilesAge) if rawData { diff --git a/pkg/app/appdisc/factory.go b/pkg/app/appdisc/factory.go index 9ac8548f3a..fd7d73c4f7 100644 --- a/pkg/app/appdisc/factory.go +++ b/pkg/app/appdisc/factory.go @@ -2,13 +2,14 @@ package appdisc import ( + "encoding/json" "net/http" "github.com/sirupsen/logrus" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" + "github.com/skycoin/skywire" "github.com/skycoin/skywire/pkg/app/appcommon" "github.com/skycoin/skywire/pkg/servicedisc" "github.com/skycoin/skywire/pkg/skyenv" @@ -31,7 +32,15 @@ func (f *Factory) setDefaults() { f.Log = logging.MustGetLogger("appdisc") } if f.ServiceDisc == "" { - f.ServiceDisc = utilenv.ServiceDiscAddr + var envServices skywire.EnvServices + var services skywire.Services + var sdURL string + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + sdURL = services.ServiceDiscovery + } + } + f.ServiceDisc = sdURL } } diff --git a/pkg/visor/init.go b/pkg/visor/init.go index 4f341c1b88..75ffaf5204 100644 --- a/pkg/visor/init.go +++ b/pkg/visor/init.go @@ -33,7 +33,7 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire-utilities/pkg/netutil" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" + "github.com/skycoin/skywire" "github.com/skycoin/skywire/internal/vpn" "github.com/skycoin/skywire/pkg/app/appdisc" "github.com/skycoin/skywire/pkg/app/appevent" @@ -1516,8 +1516,15 @@ func initPublicAutoconnect(ctx context.Context, v *Visor, log *logging.Logger) e return nil } serviceDisc := v.conf.Launcher.ServiceDisc - if serviceDisc == "" { - serviceDisc = utilenv.ServiceDiscAddr + if serviceDisc == "" { //it might be intentionally blank ; consider revising. + var envServices skywire.EnvServices + var services skywire.Services + var sdURL string + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal(envServices.Prod, &services); err == nil { + serviceDisc = services.ServiceDiscovery + } + } } // todo: refactor updatedisc: split connecting to services in updatedisc and diff --git a/pkg/visor/visorconfig/config.go b/pkg/visor/visorconfig/config.go index d456596052..f3019b083d 100644 --- a/pkg/visor/visorconfig/config.go +++ b/pkg/visor/visorconfig/config.go @@ -13,8 +13,8 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" "github.com/skycoin/skywire/pkg/app/appserver" + "github.com/skycoin/skywire" "github.com/skycoin/skywire/pkg/dmsgc" "github.com/skycoin/skywire/pkg/routing" "github.com/skycoin/skywire/pkg/skyenv" @@ -25,34 +25,21 @@ import ( // This is used as default values if no config is given, or for missing *required* fields. // This function always returns the latest config version. func MakeBaseConfig(common *Common, testEnv bool, dmsgHTTP bool, services *Services, dmsgHTTPServersList *DmsgHTTPServers) *V1 { + //check if any services were passed if services == nil { - //fall back on defaults + var envServices EnvServices + if err := json.Unmarshal([]byte(jsonData), &envServices); err != nil { + return nil + } if !testEnv { - services = &Services{ - DmsgDiscovery: utilenv.DmsgDiscAddr, - TransportDiscovery: utilenv.TpDiscAddr, - AddressResolver: utilenv.AddressResolverAddr, - RouteFinder: utilenv.RouteFinderAddr, - RouteSetupNodes: MustPKs(utilenv.RouteSetupPKs), - TransportSetupPKs: MustPKs(utilenv.TPSetupPKs), - UptimeTracker: utilenv.UptimeTrackerAddr, - ServiceDiscovery: utilenv.ServiceDiscAddr, - StunServers: utilenv.GetStunServers(), - DNSServer: utilenv.DNSServer, + var prodServices Services + if err := json.Unmarshal(envServices.Prod, &services); err != nil { + return nil } } else { - services = &Services{ - DmsgDiscovery: utilenv.TestDmsgDiscAddr, - TransportDiscovery: utilenv.TestTpDiscAddr, - AddressResolver: utilenv.TestAddressResolverAddr, - RouteFinder: utilenv.TestRouteFinderAddr, - RouteSetupNodes: MustPKs(utilenv.TestRouteSetupPKs), - TransportSetupPKs: MustPKs(utilenv.TestTPSetupPKs), - UptimeTracker: utilenv.TestUptimeTrackerAddr, - ServiceDiscovery: utilenv.TestServiceDiscAddr, - StunServers: utilenv.GetStunServers(), - DNSServer: utilenv.DNSServer, + if err := json.Unmarshal(envServices.Test, &services); err != nil { + return nil } } } @@ -61,14 +48,14 @@ func MakeBaseConfig(common *Common, testEnv bool, dmsgHTTP bool, services *Servi conf.Common = common } conf.Dmsg = &dmsgc.DmsgConfig{ - Discovery: services.DmsgDiscovery, //utilenv.DmsgDiscAddr, + Discovery: services.DmsgDiscovery, SessionsCount: 1, Servers: []*disc.Entry{}, ConnectedServersType: "all", } conf.Transport = &Transport{ - Discovery: services.TransportDiscovery, //utilenv.TpDiscAddr, - AddressResolver: services.AddressResolver, //utilenv.AddressResolverAddr, + Discovery: services.TransportDiscovery, + AddressResolver: services.AddressResolver, PublicAutoconnect: PublicAutoconnect, LogStore: &LogStore{ Type: FileLogStore, @@ -79,25 +66,25 @@ func MakeBaseConfig(common *Common, testEnv bool, dmsgHTTP bool, services *Servi StcprPort: 0, } conf.Routing = &Routing{ - RouteFinder: services.RouteFinder, //utilenv.RouteFinderAddr, - RouteSetupNodes: services.RouteSetupNodes, //[]cipher.PubKey{utilenv.MustPK(utilenv.SetupPK)}, + RouteFinder: services.RouteFinder, + RouteSetupNodes: services.RouteSetupNodes, RouteFinderTimeout: DefaultTimeout, } conf.Launcher = &Launcher{ - ServiceDisc: services.ServiceDiscovery, //utilenv.ServiceDiscAddr, + ServiceDisc: services.ServiceDiscovery, Apps: nil, ServerAddr: AppSrvAddr, BinPath: AppBinPath, DisplayNodeIP: false, } conf.UptimeTracker = &UptimeTracker{ - Addr: services.UptimeTracker, //utilenv.UptimeTrackerAddr, + Addr: services.UptimeTracker, } conf.CLIAddr = RPCAddr conf.LogLevel = LogLevel conf.LocalPath = LocalPath conf.DmsgHTTPServerPath = LocalPath + "/" + Custom - conf.StunServers = services.StunServers //utilenv.GetStunServers() + conf.StunServers = services.StunServers conf.ShutdownTimeout = DefaultTimeout conf.Dmsgpty = &Dmsgpty{ diff --git a/pkg/visor/visorconfig/hypervisorconfig.go b/pkg/visor/visorconfig/hypervisorconfig.go index 99b284ea37..5b23e4d270 100644 --- a/pkg/visor/visorconfig/hypervisorconfig.go +++ b/pkg/visor/visorconfig/hypervisorconfig.go @@ -12,7 +12,7 @@ import ( "time" "github.com/skycoin/skywire-utilities/pkg/cipher" - utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" + "github.com/skycoin/skywire" "github.com/skycoin/skywire/pkg/util/pathutil" ) @@ -112,11 +112,20 @@ func (c *HypervisorConfig) FillDefaults(testEnv bool) { } if c.DmsgDiscovery == "" { - if testEnv { - c.DmsgDiscovery = utilenv.TestDmsgDiscAddr + var envServices EnvServices + var services Services + if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if testEnv { + if err := json.Unmarshal(envServices.Test, &services); err != nil { + return + } } else { - c.DmsgDiscovery = utilenv.DmsgDiscAddr - } + if err := json.Unmarshal(envServices.Prod, &services); err != nil { + return + } + } + + c.DmsgDiscovery = services.DmsgDiscovery } if c.DmsgPort == 0 { c.DmsgPort = DmsgHypervisorPort diff --git a/pkg/visor/visorconfig/services.go b/pkg/visor/visorconfig/services.go index 44ff133a83..e448fe4410 100644 --- a/pkg/visor/visorconfig/services.go +++ b/pkg/visor/visorconfig/services.go @@ -52,6 +52,12 @@ func Fetch(mLog *logging.MasterLogger, serviceConf string, stdout bool) (service return services } +// Wrapper struct for the outer JSON +type EnvServices struct { + Test json.RawMessage `json:"test"` + Prod json.RawMessage `json:"prod"` +} + // Services are subdomains and IP addresses of the skywire services type Services struct { DmsgDiscovery string `json:"dmsg_discovery,omitempty"` diff --git a/skywire.go b/skywire.go index 2b778f83a6..54489d1e24 100644 --- a/skywire.go +++ b/skywire.go @@ -4,3 +4,30 @@ package skywire /* workaround to avoid go module errors. */ + +//go:embed services-config.json +var ServicesJSON []byte + +//go:embed dmsghttp-config.json +var DmsghttpJSON []byte + +// Wrapper struct for the outer JSON +type EnvServices struct { + Test json.RawMessage `json:"test"` + Prod json.RawMessage `json:"prod"` +} + +// Services are subdomains and IP addresses of the skywire services +type Services struct { + DmsgDiscovery string `json:"dmsg_discovery,omitempty"` + TransportDiscovery string `json:"transport_discovery,omitempty"` + AddressResolver string `json:"address_resolver,omitempty"` + RouteFinder string `json:"route_finder,omitempty"` + RouteSetupNodes []cipher.PubKey `json:"route_setup_nodes,omitempty"` + TransportSetupPKs []cipher.PubKey `json:"transport_setup,omitempty"` + UptimeTracker string `json:"uptime_tracker,omitempty"` + ServiceDiscovery string `json:"service_discovery,omitempty"` + StunServers []string `json:"stun_servers,omitempty"` + DNSServer string `json:"dns_server,omitempty"` + SurveyWhitelist []cipher.PubKey `json:"survey_whitelist,omitempty"` +} From f2bae228801c77e804546bee3145d2a59c9cd90c Mon Sep 17 00:00:00 2001 From: Moses Narrow Date: Sat, 21 Sep 2024 18:30:56 -0500 Subject: [PATCH 02/17] fix CI errors --- cmd/apps/skychat/commands/skychat.go | 6 +- cmd/apps/vpn-server/commands/vpn-server.go | 2 +- cmd/skywire-cli/commands/config/gen.go | 3 +- cmd/skywire-cli/commands/config/root.go | 4 +- cmd/skywire-cli/commands/config/update.go | 11 +- cmd/skywire-cli/commands/log/log.go | 3 +- cmd/skywire-cli/commands/log/root.go | 4 +- cmd/skywire-cli/commands/mdisc/root.go | 9 +- cmd/skywire-cli/commands/proxy/proxy.go | 5 +- cmd/skywire-cli/commands/proxy/root.go | 3 +- cmd/skywire-cli/commands/rewards/ui.go | 8 +- cmd/skywire-cli/commands/route/route.go | 18 +- cmd/skywire-cli/commands/survey/root.go | 6 +- cmd/skywire-cli/commands/tp/tp.go | 13 +- cmd/skywire-cli/commands/ut/root.go | 7 +- cmd/skywire-cli/commands/vpn/vvpn.go | 8 +- cmd/skywire/skywire.go | 18 - go.mod | 14 +- go.sum | 12 - pkg/app/appdisc/factory.go | 4 +- pkg/visor/init.go | 5 +- pkg/visor/visorconfig/config.go | 24 +- pkg/visor/visorconfig/hypervisorconfig.go | 33 +- skywire.go | 18 +- vendor/github.com/go-redis/redis/.gitignore | 2 - vendor/github.com/go-redis/redis/.travis.yml | 20 - vendor/github.com/go-redis/redis/CHANGELOG.md | 25 - vendor/github.com/go-redis/redis/LICENSE | 25 - vendor/github.com/go-redis/redis/Makefile | 22 - vendor/github.com/go-redis/redis/README.md | 146 - vendor/github.com/go-redis/redis/cluster.go | 1627 ----------- .../go-redis/redis/cluster_commands.go | 22 - vendor/github.com/go-redis/redis/command.go | 1972 ------------- vendor/github.com/go-redis/redis/commands.go | 2583 ----------------- vendor/github.com/go-redis/redis/doc.go | 4 - .../internal/consistenthash/consistenthash.go | 81 - .../go-redis/redis/internal/error.go | 89 - .../redis/internal/hashtag/hashtag.go | 77 - .../go-redis/redis/internal/internal.go | 24 - .../github.com/go-redis/redis/internal/log.go | 15 - .../go-redis/redis/internal/once.go | 60 - .../go-redis/redis/internal/pool/conn.go | 95 - .../go-redis/redis/internal/pool/pool.go | 476 --- .../redis/internal/pool/pool_single.go | 203 -- .../redis/internal/pool/pool_sticky.go | 109 - .../go-redis/redis/internal/proto/reader.go | 290 -- .../go-redis/redis/internal/proto/scan.go | 166 -- .../go-redis/redis/internal/proto/writer.go | 159 - .../go-redis/redis/internal/util.go | 39 - .../go-redis/redis/internal/util/safe.go | 11 - .../go-redis/redis/internal/util/strconv.go | 19 - .../go-redis/redis/internal/util/unsafe.go | 22 - vendor/github.com/go-redis/redis/iterator.go | 74 - vendor/github.com/go-redis/redis/options.go | 226 -- vendor/github.com/go-redis/redis/pipeline.go | 133 - vendor/github.com/go-redis/redis/pubsub.go | 514 ---- vendor/github.com/go-redis/redis/redis.go | 583 ---- vendor/github.com/go-redis/redis/result.go | 140 - vendor/github.com/go-redis/redis/ring.go | 702 ----- vendor/github.com/go-redis/redis/script.go | 62 - vendor/github.com/go-redis/redis/sentinel.go | 415 --- vendor/github.com/go-redis/redis/tx.go | 110 - vendor/github.com/go-redis/redis/universal.go | 180 -- .../dmsg-discovery/commands/dmsg-discovery.go | 45 +- .../cmd/dmsg-socks5/commands/dmsg-socks5.go | 16 +- .../dmsg/cmd/dmsgcurl/commands/dmsgcurl.go | 21 +- .../dmsg/cmd/dmsghttp/commands/dmsghttp.go | 13 +- .../dmsg/cmd/dmsgpty-host/commands/root.go | 4 +- .../dmsg/cmd/dmsgweb/commands/dmsgweb.go | 9 +- .../dmsg/cmd/dmsgweb/commands/dmsgwebsrv.go | 3 +- .../github.com/skycoin/dmsg/pkg/dmsg/const.go | 23 +- .../skycoin/dmsg/pkg/dmsgcurl/dmsgcurl.go | 4 +- .../skycoin/dmsg/pkg/dmsgcurl/flags.go | 14 +- .../skycoin/dmsg/pkg/dmsghttp/util.go | 24 +- .../skycoin/dmsg/pkg/dmsgpty/conf.go | 2 +- .../skycoin/dmsg/pkg/dmsgserver/config.go | 6 +- .../cmd/service-discovery/commands/root.go | 55 +- .../cmd/address-resolver/commands/root.go | 21 +- .../cmd/config-bootstrapper/commands/root.go | 25 +- .../cmd/dmsg-monitor/commands/root.go | 123 - .../cmd/liveness-checker/commands/root.go | 124 - .../cmd/network-monitor/commands/root.go | 175 -- .../cmd/public-visor-monitor/commands/root.go | 114 - .../cmd/route-finder/commands/root.go | 33 +- .../cmd/skysocks-monitor/commands/root.go | 104 - .../cmd/transport-discovery/commands/root.go | 30 +- .../cmd/vpn-monitor/commands/root.go | 104 - .../internal/armetrics/victoria_metrics.go | 4 +- .../internal/config/runners.go | 4 +- .../skywire-services/internal/lc/data.go | 19 - .../skywire-services/internal/nm/types.go | 14 - .../internal/nmmetrics/empty.go | 19 - .../internal/nmmetrics/metrics.go | 8 - .../internal/nmmetrics/victoria_metrics.go | 37 - .../internal/tpdiscmetrics/empty.go | 4 +- .../internal/tpdiscmetrics/metrics.go | 4 +- .../skywire-services/internal/vpn/client.go | 360 --- .../internal/vpn/client_config.go | 8 - .../skywire-services/internal/vpn/const.go | 8 - .../skywire-services/internal/vpn/errors.go | 46 - .../internal/vpn/handshake_status.go | 53 - .../skywire-services/internal/vpn/hello.go | 15 - .../skywire-services/internal/vpn/net.go | 89 - .../internal/vpn/tun_device.go | 9 - .../internal/vpn/tun_device_unix.go | 21 - .../internal/vpn/tun_device_windows.go | 50 - .../pkg/config-bootstrapper/api/api.go | 22 +- .../pkg/dmsg-monitor/api/api.go | 450 --- .../pkg/liveness-checker/api/api.go | 617 ---- .../liveness-checker/store/memory_store.go | 46 - .../pkg/liveness-checker/store/redis_store.go | 118 - .../pkg/liveness-checker/store/store.go | 40 - .../pkg/network-monitor/api/api.go | 596 ---- .../pkg/network-monitor/store/memory_store.go | 59 - .../pkg/network-monitor/store/redis_store.go | 101 - .../pkg/network-monitor/store/store.go | 40 - .../pkg/public-visor-monitor/api/api.go | 344 --- .../pkg/route-finder/store/priority_queue.go | 4 +- .../pkg/skysocks-monitor/api/api.go | 419 --- .../pkg/vpn-monitor/api/api.go | 422 --- .../skywire-utilities/pkg/skyenv/values.go | 51 - vendor/modules.txt | 40 +- 122 files changed, 368 insertions(+), 16625 deletions(-) delete mode 100644 vendor/github.com/go-redis/redis/.gitignore delete mode 100644 vendor/github.com/go-redis/redis/.travis.yml delete mode 100644 vendor/github.com/go-redis/redis/CHANGELOG.md delete mode 100644 vendor/github.com/go-redis/redis/LICENSE delete mode 100644 vendor/github.com/go-redis/redis/Makefile delete mode 100644 vendor/github.com/go-redis/redis/README.md delete mode 100644 vendor/github.com/go-redis/redis/cluster.go delete mode 100644 vendor/github.com/go-redis/redis/cluster_commands.go delete mode 100644 vendor/github.com/go-redis/redis/command.go delete mode 100644 vendor/github.com/go-redis/redis/commands.go delete mode 100644 vendor/github.com/go-redis/redis/doc.go delete mode 100644 vendor/github.com/go-redis/redis/internal/consistenthash/consistenthash.go delete mode 100644 vendor/github.com/go-redis/redis/internal/error.go delete mode 100644 vendor/github.com/go-redis/redis/internal/hashtag/hashtag.go delete mode 100644 vendor/github.com/go-redis/redis/internal/internal.go delete mode 100644 vendor/github.com/go-redis/redis/internal/log.go delete mode 100644 vendor/github.com/go-redis/redis/internal/once.go delete mode 100644 vendor/github.com/go-redis/redis/internal/pool/conn.go delete mode 100644 vendor/github.com/go-redis/redis/internal/pool/pool.go delete mode 100644 vendor/github.com/go-redis/redis/internal/pool/pool_single.go delete mode 100644 vendor/github.com/go-redis/redis/internal/pool/pool_sticky.go delete mode 100644 vendor/github.com/go-redis/redis/internal/proto/reader.go delete mode 100644 vendor/github.com/go-redis/redis/internal/proto/scan.go delete mode 100644 vendor/github.com/go-redis/redis/internal/proto/writer.go delete mode 100644 vendor/github.com/go-redis/redis/internal/util.go delete mode 100644 vendor/github.com/go-redis/redis/internal/util/safe.go delete mode 100644 vendor/github.com/go-redis/redis/internal/util/strconv.go delete mode 100644 vendor/github.com/go-redis/redis/internal/util/unsafe.go delete mode 100644 vendor/github.com/go-redis/redis/iterator.go delete mode 100644 vendor/github.com/go-redis/redis/options.go delete mode 100644 vendor/github.com/go-redis/redis/pipeline.go delete mode 100644 vendor/github.com/go-redis/redis/pubsub.go delete mode 100644 vendor/github.com/go-redis/redis/redis.go delete mode 100644 vendor/github.com/go-redis/redis/result.go delete mode 100644 vendor/github.com/go-redis/redis/ring.go delete mode 100644 vendor/github.com/go-redis/redis/script.go delete mode 100644 vendor/github.com/go-redis/redis/sentinel.go delete mode 100644 vendor/github.com/go-redis/redis/tx.go delete mode 100644 vendor/github.com/go-redis/redis/universal.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/dmsg-monitor/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/liveness-checker/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/network-monitor/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/public-visor-monitor/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/skysocks-monitor/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/cmd/vpn-monitor/commands/root.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/lc/data.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/nm/types.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/nmmetrics/empty.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/nmmetrics/metrics.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/nmmetrics/victoria_metrics.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/client.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/client_config.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/const.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/errors.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/handshake_status.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/hello.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/net.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/tun_device.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/tun_device_unix.go delete mode 100644 vendor/github.com/skycoin/skywire-services/internal/vpn/tun_device_windows.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/dmsg-monitor/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/liveness-checker/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/liveness-checker/store/memory_store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/liveness-checker/store/redis_store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/liveness-checker/store/store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/network-monitor/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/network-monitor/store/memory_store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/network-monitor/store/redis_store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/network-monitor/store/store.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/public-visor-monitor/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/skysocks-monitor/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-services/pkg/vpn-monitor/api/api.go delete mode 100644 vendor/github.com/skycoin/skywire-utilities/pkg/skyenv/values.go diff --git a/cmd/apps/skychat/commands/skychat.go b/cmd/apps/skychat/commands/skychat.go index b9d3c8dba0..becbe7d89b 100644 --- a/cmd/apps/skychat/commands/skychat.go +++ b/cmd/apps/skychat/commands/skychat.go @@ -277,8 +277,10 @@ func sseHandler(w http.ResponseWriter, req *http.Request) { if !ok { return } - _, _ = fmt.Fprintf(w, "data: %s\n\n", msg) - f.Flush() + _, err := fmt.Fprintf(w, "data: %s\n\n", msg) + if err == nil { + f.Flush() + } case <-req.Context().Done(): fmt.Print("SSE connection were closed.") diff --git a/cmd/apps/vpn-server/commands/vpn-server.go b/cmd/apps/vpn-server/commands/vpn-server.go index 685a51a6c7..a9b9adad70 100644 --- a/cmd/apps/vpn-server/commands/vpn-server.go +++ b/cmd/apps/vpn-server/commands/vpn-server.go @@ -56,7 +56,7 @@ var RootCmd = &cobra.Command{ DisableSuggestions: true, DisableFlagsInUseLine: true, Version: buildinfo.Version(), - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { appCl := app.NewClient(nil) defer appCl.Close() diff --git a/cmd/skywire-cli/commands/config/gen.go b/cmd/skywire-cli/commands/config/gen.go index 7dfb312909..b1901870a7 100644 --- a/cmd/skywire-cli/commands/config/gen.go +++ b/cmd/skywire-cli/commands/config/gen.go @@ -158,7 +158,7 @@ func init() { } genConfigCmd.Flags().VarP(&sk, "sk", "s", "a random key is generated if unspecified\n\r") gHiddenFlags = append(gHiddenFlags, "sk") - genConfigCmd.Flags().BoolVarP(&isTestEnv, "testenv", "t", scriptExecBool("${TESTENV:-false}"), "use test deployment "+testConf+"\033[0m") + genConfigCmd.Flags().BoolVarP(&isTestEnv, "testenv", "t", scriptExecBool("${TESTENV:-false}"), "use test deployment\033[0m") gHiddenFlags = append(gHiddenFlags, "testenv") genConfigCmd.Flags().BoolVarP(&isVpnServerEnable, "servevpn", "v", scriptExecBool("${VPNSERVER:-false}"), "enable vpn server\033[0m") gHiddenFlags = append(gHiddenFlags, "servevpn") @@ -521,7 +521,6 @@ var genConfigCmd = &cobra.Command{ } } - //generate the common config containing public & secret keys u := buildinfo.Version() x := u diff --git a/cmd/skywire-cli/commands/config/root.go b/cmd/skywire-cli/commands/config/root.go index c57cccf24c..dc3dc00c98 100644 --- a/cmd/skywire-cli/commands/config/root.go +++ b/cmd/skywire-cli/commands/config/root.go @@ -55,8 +55,8 @@ var ( disableApps string isBestProtocol bool serviceConfURL = "http://conf.skywire.skycoin.com" - testServiceConfURL = "http://conf.skywire.dev" - dnsServer = "1.1.1.1" + testServiceConfURL = "http://conf.skywire.dev" + dnsServer = "1.1.1.1" services visorconfig.Services servicesConfig servicesConf isForce bool diff --git a/cmd/skywire-cli/commands/config/update.go b/cmd/skywire-cli/commands/config/update.go index fdbfcc24d0..dc8fa35490 100644 --- a/cmd/skywire-cli/commands/config/update.go +++ b/cmd/skywire-cli/commands/config/update.go @@ -12,6 +12,7 @@ import ( coinCipher "github.com/skycoin/skycoin/src/cipher" "github.com/spf13/cobra" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire/pkg/dmsgc" @@ -31,8 +32,8 @@ func init() { updateCmd.Flags().SortFlags = false updateCmd.Flags().BoolVarP(&isUpdateEndpoints, "endpoints", "a", false, "update server endpoints") updateCmd.Flags().StringVar(&logLevel, "log-level", "", "level of logging in config") - updateCmd.Flags().StringVarP(&serviceConfURL, "url", "b", "", "service config URL: "+svcConf) - updateCmd.Flags().BoolVarP(&isTestEnv, "testenv", "t", false, "use test deployment: "+testConf) + updateCmd.Flags().StringVarP(&serviceConfURL, "url", "b", skywire.ConfService, "service config URL") + updateCmd.Flags().BoolVarP(&isTestEnv, "testenv", "t", false, "use test deployment") updateCmd.Flags().StringVar(&setPublicAutoconnect, "public-autoconn", "", "change public autoconnect configuration") updateCmd.Flags().IntVar(&minHops, "set-minhop", -1, "change min hops value") updateCmd.PersistentFlags().StringVarP(&input, "input", "i", "", "path of input config file.") @@ -91,9 +92,9 @@ var updateCmd = &cobra.Command{ PreRun: func(_ *cobra.Command, _ []string) { if isUpdateEndpoints && (serviceConfURL == "") { if !isTestEnv { - serviceConfURL = svcConf + serviceConfURL = skywire.ConfService } else { - serviceConfURL = testConf + serviceConfURL = skywire.ConfServiceTest } } setDefaults() @@ -106,7 +107,7 @@ var updateCmd = &cobra.Command{ conf = initUpdate() if isUpdateEndpoints { if isTestEnv { - serviceConfURL = testConf + serviceConfURL = skywire.ConfServiceTest } mLog := logging.NewMasterLogger() mLog.SetLevel(logrus.InfoLevel) diff --git a/cmd/skywire-cli/commands/log/log.go b/cmd/skywire-cli/commands/log/log.go index d7f12e8c6c..215902d5c7 100644 --- a/cmd/skywire-cli/commands/log/log.go +++ b/cmd/skywire-cli/commands/log/log.go @@ -29,10 +29,9 @@ import ( ) func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { dmsgDiscURL = services.DmsgDiscovery utURL = services.UptimeTracker diff --git a/cmd/skywire-cli/commands/log/root.go b/cmd/skywire-cli/commands/log/root.go index 4a9740907c..ef5f37d68f 100644 --- a/cmd/skywire-cli/commands/log/root.go +++ b/cmd/skywire-cli/commands/log/root.go @@ -6,8 +6,8 @@ import ( ) var ( - dmsgDiscURL string - utURL string + dmsgDiscURL string + utURL string pubKey string duration int minv string diff --git a/cmd/skywire-cli/commands/mdisc/root.go b/cmd/skywire-cli/commands/mdisc/root.go index d21b43e76a..2de25db765 100644 --- a/cmd/skywire-cli/commands/mdisc/root.go +++ b/cmd/skywire-cli/commands/mdisc/root.go @@ -4,6 +4,7 @@ package climdisc import ( "bytes" "context" + "encoding/json" "fmt" "net/http" "os" @@ -16,6 +17,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire/cmd/skywire-cli/internal" @@ -26,8 +28,7 @@ var ( cacheFilesAge int mdURL string isStats bool - dmsgDiscURL string - + dmsgDiscURL string ) // var allEntries bool @@ -35,13 +36,11 @@ var masterLogger = logging.NewMasterLogger() var packageLogger = masterLogger.PackageLogger("mdisc:disc") func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { dmsgDiscURL = services.DmsgDiscovery - utURL = services.UptimeTracker } } RootCmd.AddCommand( diff --git a/cmd/skywire-cli/commands/proxy/proxy.go b/cmd/skywire-cli/commands/proxy/proxy.go index 720765c039..2671a6ef0d 100644 --- a/cmd/skywire-cli/commands/proxy/proxy.go +++ b/cmd/skywire-cli/commands/proxy/proxy.go @@ -4,6 +4,7 @@ package skysocksc import ( "bytes" "context" + "encoding/json" "fmt" "os" "strings" @@ -15,6 +16,7 @@ import ( "github.com/spf13/cobra" "github.com/tidwall/pretty" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/buildinfo" "github.com/skycoin/skywire-utilities/pkg/cmdutil" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" @@ -257,10 +259,9 @@ var statusCmd = &cobra.Command{ var isLabel bool func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { svcDiscURL = services.DmsgDiscovery utURL = services.UptimeTracker diff --git a/cmd/skywire-cli/commands/proxy/root.go b/cmd/skywire-cli/commands/proxy/root.go index 5413bc741e..49646a83b9 100644 --- a/cmd/skywire-cli/commands/proxy/root.go +++ b/cmd/skywire-cli/commands/proxy/root.go @@ -32,8 +32,7 @@ var ( addr string startingTimeout int httpAddr string - svcDiscURL string - utURL string + svcDiscURL string ) // RootCmd contains commands that interact with the skywire-visor diff --git a/cmd/skywire-cli/commands/rewards/ui.go b/cmd/skywire-cli/commands/rewards/ui.go index eb74b032ca..eabb1af321 100644 --- a/cmd/skywire-cli/commands/rewards/ui.go +++ b/cmd/skywire-cli/commands/rewards/ui.go @@ -6,6 +6,7 @@ import ( "context" "encoding/base64" "encoding/csv" + "encoding/json" "fmt" htmpl "html/template" "io" @@ -29,16 +30,16 @@ import ( dmsg "github.com/skycoin/dmsg/pkg/dmsg" "github.com/spf13/cobra" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" ) func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { dmsgDiscURL = services.DmsgDiscovery } @@ -100,8 +101,7 @@ var ( wlkeys []cipher.PubKey webPort uint ensureOnlineURL string - dmsgDiscURL string - + dmsgDiscURL string ) var skyenvfile = os.Getenv("SKYENV") diff --git a/cmd/skywire-cli/commands/route/route.go b/cmd/skywire-cli/commands/route/route.go index 7ecc1c3669..c988b265a3 100644 --- a/cmd/skywire-cli/commands/route/route.go +++ b/cmd/skywire-cli/commands/route/route.go @@ -3,6 +3,7 @@ package cliroute import ( "bytes" + "encoding/json" "errors" "fmt" "io" @@ -17,32 +18,31 @@ import ( "github.com/spf13/pflag" "golang.org/x/net/context" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/routefinder/rfclient" "github.com/skycoin/skywire/pkg/router" "github.com/skycoin/skywire/pkg/routing" - "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire/pkg/skyenv" "github.com/skycoin/skywire/pkg/visor/visorconfig" ) var ( - frAddr string - frMinHops, frMaxHops uint16 - timeout time.Duration - skywireconfig string - rfURL string + frAddr string + frMinHops, frMaxHops uint16 + timeout time.Duration + skywireconfig string + rfURL string ) func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { - rfURL = services.RouteFinderAddr + rfURL = services.RouteFinder } } findCmd.Flags().SortFlags = false diff --git a/cmd/skywire-cli/commands/survey/root.go b/cmd/skywire-cli/commands/survey/root.go index 9bd18922d1..75abbc2e57 100644 --- a/cmd/skywire-cli/commands/survey/root.go +++ b/cmd/skywire-cli/commands/survey/root.go @@ -12,6 +12,7 @@ import ( "github.com/skycoin/dmsg/pkg/dmsg" "github.com/spf13/cobra" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" @@ -32,14 +33,13 @@ var ( pkgconfigexists bool userconfigexists bool conf *visorconfig.V1 - dmsgDiscURL string + dmsgDiscURL string ) func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { dmsgDiscURL = services.DmsgDiscovery } diff --git a/cmd/skywire-cli/commands/tp/tp.go b/cmd/skywire-cli/commands/tp/tp.go index 7d24d3f640..a6bc7aa0b5 100644 --- a/cmd/skywire-cli/commands/tp/tp.go +++ b/cmd/skywire-cli/commands/tp/tp.go @@ -3,6 +3,7 @@ package clitp import ( "bytes" + "encoding/json" "errors" "fmt" "os" @@ -20,6 +21,7 @@ import ( "github.com/spf13/pflag" "github.com/tidwall/pretty" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" @@ -36,16 +38,15 @@ var ( logger = logging.MustGetLogger("skywire-cli") removeAll bool tpTypes bool - tpDiscURL string - sdURL string - utURL string + tpDiscURL string + sdURL string + utURL string ) func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { tpDiscURL = services.TransportDiscovery sdURL = services.ServiceDiscovery @@ -121,7 +122,6 @@ var tpCmd = &cobra.Command{ var ( sortedEdgeKeys []string - utURL string tpdURL string rootNode string lastNode string @@ -138,7 +138,6 @@ var ( transportType string timeout time.Duration rpk string - sdURL string cacheFileSD string cacheFilesAge int forceAttempt bool diff --git a/cmd/skywire-cli/commands/ut/root.go b/cmd/skywire-cli/commands/ut/root.go index 6aaaae2c88..ec5e9751ec 100644 --- a/cmd/skywire-cli/commands/ut/root.go +++ b/cmd/skywire-cli/commands/ut/root.go @@ -2,12 +2,14 @@ package cliut import ( + "encoding/json" "fmt" "os" "github.com/bitfield/script" "github.com/spf13/cobra" + "github.com/skycoin/skywire" "github.com/skycoin/skywire/cmd/skywire-cli/internal" ) @@ -27,10 +29,9 @@ var ( var minUT int func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { utURL = services.UptimeTracker } @@ -48,7 +49,7 @@ func init() { var utCmd = &cobra.Command{ Use: "ut", Short: "query uptime tracker", - Long: fmt.Sprintf("query uptime tracker\n\n%v/uptimes?v=v2\n\nCheck local visor daily uptime percent with:\n skywire-cli ut -k $(skywire-cli visor pk)n\nSet cache file location to \"\" to avoid using cache files", utilenv.UptimeTrackerAddr), + Long: fmt.Sprintf("query uptime tracker\n\n%v/uptimes?v=v2\n\nCheck local visor daily uptime percent with:\n skywire-cli ut -k $(skywire-cli visor pk)n\nSet cache file location to \"\" to avoid using cache files", utURL), Run: func(cmd *cobra.Command, _ []string) { uts := internal.GetData(cacheFileUT, utURL+"/uptimes?v=v2", cacheFilesAge) if online { diff --git a/cmd/skywire-cli/commands/vpn/vvpn.go b/cmd/skywire-cli/commands/vpn/vvpn.go index 4684504abf..c8739d6acf 100644 --- a/cmd/skywire-cli/commands/vpn/vvpn.go +++ b/cmd/skywire-cli/commands/vpn/vvpn.go @@ -4,6 +4,7 @@ package clivpn import ( "bytes" "context" + "encoding/json" "fmt" "os" "strings" @@ -15,6 +16,7 @@ import ( "github.com/spf13/cobra" "github.com/tidwall/pretty" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cmdutil" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" @@ -162,15 +164,11 @@ var statusCmd = &cobra.Command{ } var isLabel bool -var utURL string -var sdURL string - func init() { - log := logging.MustGetLogger("skywire-cli") var envServices skywire.EnvServices var services skywire.Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { sdURL = services.ServiceDiscovery utURL = services.UptimeTracker diff --git a/cmd/skywire/skywire.go b/cmd/skywire/skywire.go index 08466e37dd..3232213cb6 100644 --- a/cmd/skywire/skywire.go +++ b/cmd/skywire/skywire.go @@ -29,18 +29,12 @@ import ( ar "github.com/skycoin/skywire-services/cmd/address-resolver/commands" confbs "github.com/skycoin/skywire-services/cmd/config-bootstrapper/commands" - dmsgmon "github.com/skycoin/skywire-services/cmd/dmsg-monitor/commands" kg "github.com/skycoin/skywire-services/cmd/keys-gen/commands" - lc "github.com/skycoin/skywire-services/cmd/liveness-checker/commands" - nwmon "github.com/skycoin/skywire-services/cmd/network-monitor/commands" nv "github.com/skycoin/skywire-services/cmd/node-visualizer/commands" - pvmon "github.com/skycoin/skywire-services/cmd/public-visor-monitor/commands" rf "github.com/skycoin/skywire-services/cmd/route-finder/commands" - ssmon "github.com/skycoin/skywire-services/cmd/skysocks-monitor/commands" se "github.com/skycoin/skywire-services/cmd/sw-env/commands" tpd "github.com/skycoin/skywire-services/cmd/transport-discovery/commands" tps "github.com/skycoin/skywire-services/cmd/transport-setup/commands" - vpnmon "github.com/skycoin/skywire-services/cmd/vpn-monitor/commands" "github.com/skycoin/skywire-utilities/pkg/buildinfo" sc "github.com/skycoin/skywire/cmd/apps/skychat/commands" ssc "github.com/skycoin/skywire/cmd/apps/skysocks-client/commands" @@ -66,7 +60,6 @@ func init() { dmsgcurl.RootCmd, dmsgweb.RootCmd, dmsgsocks.RootCmd, - dmsgmon.RootCmd, ) svcCmd.AddCommand( sn.RootCmd, @@ -76,14 +69,9 @@ func init() { rf.RootCmd, confbs.RootCmd, kg.RootCmd, - lc.RootCmd, nv.RootCmd, se.RootCmd, sd.RootCmd, - nwmon.RootCmd, - pvmon.RootCmd, - ssmon.RootCmd, - vpnmon.RootCmd, ) appsCmd.AddCommand( vpns.RootCmd, @@ -116,19 +104,13 @@ func init() { dmsgcurl.RootCmd.Use = "curl" dmsgweb.RootCmd.Use = "web" dmsgsocks.RootCmd.Use = "socks" - dmsgmon.RootCmd.Use = "mon" tpd.RootCmd.Use = "tpd" tps.RootCmd.Use = "tps" ar.RootCmd.Use = "ar" rf.RootCmd.Use = "rf" confbs.RootCmd.Use = "cb" kg.RootCmd.Use = "kg" - lc.RootCmd.Use = "lc" nv.RootCmd.Use = "nv" - vpnmon.RootCmd.Use = "vpnm" - pvmon.RootCmd.Use = "pvm" - ssmon.RootCmd.Use = "ssm" - nwmon.RootCmd.Use = "nwmon" se.RootCmd.Use = "se" sd.RootCmd.Use = "sd" sn.RootCmd.Use = "sn" diff --git a/go.mod b/go.mod index 5b867b8bdd..69a356803c 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/pterm/pterm v0.12.66 github.com/robert-nix/ansihtml v1.0.1 github.com/sirupsen/logrus v1.9.3 - github.com/skycoin/dmsg v1.3.25 + github.com/skycoin/dmsg v1.3.26-0.20240910062314-dc25f3d9ea6c github.com/skycoin/skycoin v0.27.1 github.com/skycoin/skycoin-service-discovery v1.3.25 github.com/skycoin/skywire-services v1.3.25 @@ -84,7 +84,6 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.1 // indirect - github.com/go-redis/redis v6.15.9+incompatible // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/goccy/go-json v0.10.2 // indirect @@ -169,10 +168,13 @@ require ( replace github.com/xxxserxxx/gotop/v4 => github.com/ersonp/gotop/v4 v4.2.1 // Uncomment for tests with local sources of other skywire repos -// replace github.com/skycoin/dmsg => ../dmsg -// replace github.com/skycoin/skywire-services => ../skywire-services -// replace github.com/skycoin/skycoin-service-discovery => ../skycoin-service-discovery -// replace github.com/skycoin/skywire-utilities => ../skywire-utilities +replace github.com/skycoin/dmsg => ../dmsg + +replace github.com/skycoin/skywire-services => ../skywire-services + +replace github.com/skycoin/skycoin-service-discovery => ../skycoin-service-discovery + +replace github.com/skycoin/skywire-utilities => ../skywire-utilities // Uncomment to update other skywire deps to specific commit hash. // run `go mod tidy ; go mod vendor` diff --git a/go.sum b/go.sum index 3b8cd6e2f7..7edbf6cfd9 100644 --- a/go.sum +++ b/go.sum @@ -682,22 +682,10 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skycoin/dmsg v1.3.25 h1:Gs4aRhLq/ZCo5I0vN3nTv/N5/MC6sunWCuS50Tct6qI= -github.com/skycoin/dmsg v1.3.25/go.mod h1:3pyc9MmDJQYP0spTAWKLMctz4+ZKjMZgXtdMmXpYolw= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 h1:1Nc5EBY6pjfw1kwW0duwyG+7WliWz5u9kgk1h5MnLuA= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:UXghlricA7J3aRD/k7p/zBObQfmBawwCxIVPVjz2Q3o= github.com/skycoin/skycoin v0.27.1 h1:HatxsRwVSPaV4qxH6290xPBmkH/HgiuAoY2qC+e8C9I= github.com/skycoin/skycoin v0.27.1/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw= -github.com/skycoin/skycoin-service-discovery v0.0.0-20240627171358-7f59a951fa29 h1:Y7EJVrs41zHGLHvqTH69Lx2Rc39s+umxIlZ439osBeA= -github.com/skycoin/skycoin-service-discovery v0.0.0-20240627171358-7f59a951fa29/go.mod h1:v2r2hqtBsF9rb1wBoJWn21YCiGm0EmGgnhrwD4c54yY= -github.com/skycoin/skycoin-service-discovery v1.3.25 h1:vnB4Is0/+rYuE9pH3+pBdnTbKQYQV3h9BvzxHZi7GB8= -github.com/skycoin/skycoin-service-discovery v1.3.25/go.mod h1:D/4UQpOMdv8In2IY3P7+pLJUgJDqrpq7vpjX7dQEPng= -github.com/skycoin/skywire-services v0.0.0-20240627171623-87edf49d9025 h1:48nukMj8f8VsUlNuGfJP/49wqfzqfJshoKXkjKf4Qyc= -github.com/skycoin/skywire-services v0.0.0-20240627171623-87edf49d9025/go.mod h1:007npHSDcpTeQiG7e3h36W5IMl2+YT8N6nUB0pwtSYs= -github.com/skycoin/skywire-services v1.3.25 h1:LzUsNx7CNBTodkhkyl6fmJ1pbHY7WALiS4mNw8PKPe0= -github.com/skycoin/skywire-services v1.3.25/go.mod h1:gRucqzsrQmzyPYBfYLJYFgi3+o98j+04oVFY0jRLScs= -github.com/skycoin/skywire-utilities v1.3.25 h1:mk8dUonFdhVopFF3d9wbOyXXoiuAO+mN1y+ve6SzgX4= -github.com/skycoin/skywire-utilities v1.3.25/go.mod h1:yFKWpL1bDRPKU3uK+cTF4PnYUMe+eyIj5N2bk4sF5Cw= github.com/skycoin/systray v1.10.0 h1:fQZJHMylpVvfmOOTLvUssfyHVDoC8Idx6Ba2BlLEuGg= github.com/skycoin/systray v1.10.0/go.mod h1:/i17Eni5GxFiboIZceeamY5LktDSFFRCvd3fBMerQ+4= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= diff --git a/pkg/app/appdisc/factory.go b/pkg/app/appdisc/factory.go index fd7d73c4f7..9b193610eb 100644 --- a/pkg/app/appdisc/factory.go +++ b/pkg/app/appdisc/factory.go @@ -7,9 +7,9 @@ import ( "github.com/sirupsen/logrus" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" - "github.com/skycoin/skywire" "github.com/skycoin/skywire/pkg/app/appcommon" "github.com/skycoin/skywire/pkg/servicedisc" "github.com/skycoin/skywire/pkg/skyenv" @@ -35,7 +35,7 @@ func (f *Factory) setDefaults() { var envServices skywire.EnvServices var services skywire.Services var sdURL string - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { sdURL = services.ServiceDiscovery } diff --git a/pkg/visor/init.go b/pkg/visor/init.go index 75ffaf5204..9ff6687433 100644 --- a/pkg/visor/init.go +++ b/pkg/visor/init.go @@ -30,10 +30,10 @@ import ( "github.com/skycoin/dmsg/pkg/dmsghttp" "github.com/skycoin/dmsg/pkg/dmsgpty" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire-utilities/pkg/netutil" - "github.com/skycoin/skywire" "github.com/skycoin/skywire/internal/vpn" "github.com/skycoin/skywire/pkg/app/appdisc" "github.com/skycoin/skywire/pkg/app/appevent" @@ -1519,8 +1519,7 @@ func initPublicAutoconnect(ctx context.Context, v *Visor, log *logging.Logger) e if serviceDisc == "" { //it might be intentionally blank ; consider revising. var envServices skywire.EnvServices var services skywire.Services - var sdURL string - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if err := json.Unmarshal(envServices.Prod, &services); err == nil { serviceDisc = services.ServiceDiscovery } diff --git a/pkg/visor/visorconfig/config.go b/pkg/visor/visorconfig/config.go index f3019b083d..b598410362 100644 --- a/pkg/visor/visorconfig/config.go +++ b/pkg/visor/visorconfig/config.go @@ -11,10 +11,10 @@ import ( "github.com/skycoin/dmsg/pkg/dmsgpty" coinCipher "github.com/skycoin/skycoin/src/cipher" + "github.com/skycoin/skywire" "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/logging" "github.com/skycoin/skywire/pkg/app/appserver" - "github.com/skycoin/skywire" "github.com/skycoin/skywire/pkg/dmsgc" "github.com/skycoin/skywire/pkg/routing" "github.com/skycoin/skywire/pkg/skyenv" @@ -28,12 +28,11 @@ func MakeBaseConfig(common *Common, testEnv bool, dmsgHTTP bool, services *Servi //check if any services were passed if services == nil { - var envServices EnvServices - if err := json.Unmarshal([]byte(jsonData), &envServices); err != nil { + var envServices skywire.EnvServices + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err != nil { return nil } if !testEnv { - var prodServices Services if err := json.Unmarshal(envServices.Prod, &services); err != nil { return nil } @@ -135,9 +134,22 @@ func MakeDefaultConfig(log *logging.MasterLogger, sk *cipher.SecKey, usrEnv bool if err != nil { return nil, err } + dnsServer := "" var dmsgHTTPServersList *DmsgHTTPServers - - dnsServer := utilenv.DNSServer + var envServices skywire.EnvServices + var svcs skywire.Services + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err != nil { + return nil, nil + } + if !testEnv { + if err := json.Unmarshal(envServices.Prod, &svcs); err != nil { + dnsServer = svcs.DNSServer + } + } else { + if err := json.Unmarshal(envServices.Test, &svcs); err != nil { + dnsServer = svcs.DNSServer + } + } if services != nil { if services.DNSServer != "" { dnsServer = services.DNSServer diff --git a/pkg/visor/visorconfig/hypervisorconfig.go b/pkg/visor/visorconfig/hypervisorconfig.go index 5b23e4d270..aa2476cda5 100644 --- a/pkg/visor/visorconfig/hypervisorconfig.go +++ b/pkg/visor/visorconfig/hypervisorconfig.go @@ -11,8 +11,8 @@ import ( "path/filepath" "time" - "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire" + "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire/pkg/util/pathutil" ) @@ -114,31 +114,32 @@ func (c *HypervisorConfig) FillDefaults(testEnv bool) { if c.DmsgDiscovery == "" { var envServices EnvServices var services Services - if err := json.Unmarshal([]byte(jsonData), &envServices); err == nil { + if err := json.Unmarshal([]byte(skywire.ServicesJSON), &envServices); err == nil { if testEnv { if err := json.Unmarshal(envServices.Test, &services); err != nil { return - } - } else { + } + } else { if err := json.Unmarshal(envServices.Prod, &services); err != nil { return } } c.DmsgDiscovery = services.DmsgDiscovery - } - if c.DmsgPort == 0 { - c.DmsgPort = DmsgHypervisorPort - } - if c.HTTPAddr == "" { - c.HTTPAddr = httpAddr - } - c.Cookies.FillDefaults() - c.EnableAuth = EnableAuth - c.EnableTLS = EnableTLS - c.TLSCertFile = TLSCert - c.TLSKeyFile = TLSKey + } + if c.DmsgPort == 0 { + c.DmsgPort = DmsgHypervisorPort + } + if c.HTTPAddr == "" { + c.HTTPAddr = httpAddr + } + c.Cookies.FillDefaults() + c.EnableAuth = EnableAuth + c.EnableTLS = EnableTLS + c.TLSCertFile = TLSCert + c.TLSKeyFile = TLSKey + } } // Parse parses the file in path, and decodes to the config. diff --git a/skywire.go b/skywire.go index 54489d1e24..0d51f4be50 100644 --- a/skywire.go +++ b/skywire.go @@ -1,8 +1,19 @@ // Package skywire skywire.go package skywire +import ( + _ "embed" + "encoding/json" + + "github.com/skycoin/skywire-utilities/pkg/cipher" +) + /* -workaround to avoid go module errors. +Embedded Deployment Defaults + +Change the contents of the files to embed updated values + +Vendor the commit of the change in any repo which depends on them */ //go:embed services-config.json @@ -17,6 +28,11 @@ type EnvServices struct { Prod json.RawMessage `json:"prod"` } +const ( + ConfService = "http://conf.skywire.skycoin.com" + ConfServiceTest = "http://conf.skywire.dev" +) + // Services are subdomains and IP addresses of the skywire services type Services struct { DmsgDiscovery string `json:"dmsg_discovery,omitempty"` diff --git a/vendor/github.com/go-redis/redis/.gitignore b/vendor/github.com/go-redis/redis/.gitignore deleted file mode 100644 index ebfe903bcd..0000000000 --- a/vendor/github.com/go-redis/redis/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.rdb -testdata/*/ diff --git a/vendor/github.com/go-redis/redis/.travis.yml b/vendor/github.com/go-redis/redis/.travis.yml deleted file mode 100644 index 06d7897b4e..0000000000 --- a/vendor/github.com/go-redis/redis/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -sudo: false -language: go - -services: - - redis-server - -go: - - 1.9.x - - 1.10.x - - 1.11.x - - 1.12.x - - tip - -matrix: - allow_failures: - - go: tip - -install: - - go get github.com/onsi/ginkgo - - go get github.com/onsi/gomega diff --git a/vendor/github.com/go-redis/redis/CHANGELOG.md b/vendor/github.com/go-redis/redis/CHANGELOG.md deleted file mode 100644 index 19645661a4..0000000000 --- a/vendor/github.com/go-redis/redis/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# Changelog - -## Unreleased - -- Cluster and Ring pipelines process commands for each node in its own goroutine. - -## 6.14 - -- Added Options.MinIdleConns. -- Added Options.MaxConnAge. -- PoolStats.FreeConns is renamed to PoolStats.IdleConns. -- Add Client.Do to simplify creating custom commands. -- Add Cmd.String, Cmd.Int, Cmd.Int64, Cmd.Uint64, Cmd.Float64, and Cmd.Bool helpers. -- Lower memory usage. - -## v6.13 - -- Ring got new options called `HashReplicas` and `Hash`. It is recommended to set `HashReplicas = 1000` for better keys distribution between shards. -- Cluster client was optimized to use much less memory when reloading cluster state. -- PubSub.ReceiveMessage is re-worked to not use ReceiveTimeout so it does not lose data when timeout occurres. In most cases it is recommended to use PubSub.Channel instead. -- Dialer.KeepAlive is set to 5 minutes by default. - -## v6.12 - -- ClusterClient got new option called `ClusterSlots` which allows to build cluster of normal Redis Servers that don't have cluster mode enabled. See https://godoc.org/github.com/go-redis/redis#example-NewClusterClient--ManualSetup diff --git a/vendor/github.com/go-redis/redis/LICENSE b/vendor/github.com/go-redis/redis/LICENSE deleted file mode 100644 index 298bed9bea..0000000000 --- a/vendor/github.com/go-redis/redis/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2013 The github.com/go-redis/redis Authors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-redis/redis/Makefile b/vendor/github.com/go-redis/redis/Makefile deleted file mode 100644 index fa3b4e004f..0000000000 --- a/vendor/github.com/go-redis/redis/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -all: testdeps - go test ./... - go test ./... -short -race - env GOOS=linux GOARCH=386 go test ./... - go vet - go get github.com/gordonklaus/ineffassign - ineffassign . - -testdeps: testdata/redis/src/redis-server - -bench: testdeps - go test ./... -test.run=NONE -test.bench=. -test.benchmem - -.PHONY: all test testdeps bench - -testdata/redis: - mkdir -p $@ - wget -qO- https://github.com/antirez/redis/archive/5.0.tar.gz | tar xvz --strip-components=1 -C $@ - -testdata/redis/src/redis-server: testdata/redis - sed -i.bak 's/libjemalloc.a/libjemalloc.a -lrt/g' $ -} - -func ExampleClient() { - err := client.Set("key", "value", 0).Err() - if err != nil { - panic(err) - } - - val, err := client.Get("key").Result() - if err != nil { - panic(err) - } - fmt.Println("key", val) - - val2, err := client.Get("key2").Result() - if err == redis.Nil { - fmt.Println("key2 does not exist") - } else if err != nil { - panic(err) - } else { - fmt.Println("key2", val2) - } - // Output: key value - // key2 does not exist -} -``` - -## Howto - -Please go through [examples](https://godoc.org/github.com/go-redis/redis#pkg-examples) to get an idea how to use this package. - -## Look and feel - -Some corner cases: - -```go -// SET key value EX 10 NX -set, err := client.SetNX("key", "value", 10*time.Second).Result() - -// SORT list LIMIT 0 2 ASC -vals, err := client.Sort("list", redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result() - -// ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2 -vals, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ - Min: "-inf", - Max: "+inf", - Offset: 0, - Count: 2, -}).Result() - -// ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM -vals, err := client.ZInterStore("out", redis.ZStore{Weights: []int64{2, 3}}, "zset1", "zset2").Result() - -// EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello" -vals, err := client.Eval("return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result() -``` - -## Benchmark - -go-redis vs redigo: - -``` -BenchmarkSetGoRedis10Conns64Bytes-4 200000 7621 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis100Conns64Bytes-4 200000 7554 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis10Conns1KB-4 200000 7697 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis100Conns1KB-4 200000 7688 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis10Conns10KB-4 200000 9214 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis100Conns10KB-4 200000 9181 ns/op 210 B/op 6 allocs/op -BenchmarkSetGoRedis10Conns1MB-4 2000 583242 ns/op 2337 B/op 6 allocs/op -BenchmarkSetGoRedis100Conns1MB-4 2000 583089 ns/op 2338 B/op 6 allocs/op -BenchmarkSetRedigo10Conns64Bytes-4 200000 7576 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo100Conns64Bytes-4 200000 7782 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo10Conns1KB-4 200000 7958 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo100Conns1KB-4 200000 7725 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo10Conns10KB-4 100000 18442 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo100Conns10KB-4 100000 18818 ns/op 208 B/op 7 allocs/op -BenchmarkSetRedigo10Conns1MB-4 2000 668829 ns/op 226 B/op 7 allocs/op -BenchmarkSetRedigo100Conns1MB-4 2000 679542 ns/op 226 B/op 7 allocs/op -``` - -Redis Cluster: - -``` -BenchmarkRedisPing-4 200000 6983 ns/op 116 B/op 4 allocs/op -BenchmarkRedisClusterPing-4 100000 11535 ns/op 117 B/op 4 allocs/op -``` - -## See also - -- [Golang PostgreSQL ORM](https://github.com/go-pg/pg) -- [Golang msgpack](https://github.com/vmihailenco/msgpack) -- [Golang message task queue](https://github.com/vmihailenco/taskq) diff --git a/vendor/github.com/go-redis/redis/cluster.go b/vendor/github.com/go-redis/redis/cluster.go deleted file mode 100644 index ab2c76f05e..0000000000 --- a/vendor/github.com/go-redis/redis/cluster.go +++ /dev/null @@ -1,1627 +0,0 @@ -package redis - -import ( - "context" - "crypto/tls" - "fmt" - "math" - "math/rand" - "net" - "runtime" - "sort" - "sync" - "sync/atomic" - "time" - - "github.com/go-redis/redis/internal" - "github.com/go-redis/redis/internal/hashtag" - "github.com/go-redis/redis/internal/pool" - "github.com/go-redis/redis/internal/proto" -) - -var errClusterNoNodes = fmt.Errorf("redis: cluster has no nodes") - -// ClusterOptions are used to configure a cluster client and should be -// passed to NewClusterClient. -type ClusterOptions struct { - // A seed list of host:port addresses of cluster nodes. - Addrs []string - - // The maximum number of retries before giving up. Command is retried - // on network errors and MOVED/ASK redirects. - // Default is 8 retries. - MaxRedirects int - - // Enables read-only commands on slave nodes. - ReadOnly bool - // Allows routing read-only commands to the closest master or slave node. - // It automatically enables ReadOnly. - RouteByLatency bool - // Allows routing read-only commands to the random master or slave node. - // It automatically enables ReadOnly. - RouteRandomly bool - - // Optional function that returns cluster slots information. - // It is useful to manually create cluster of standalone Redis servers - // and load-balance read/write operations between master and slaves. - // It can use service like ZooKeeper to maintain configuration information - // and Cluster.ReloadState to manually trigger state reloading. - ClusterSlots func() ([]ClusterSlot, error) - - // Optional hook that is called when a new node is created. - OnNewNode func(*Client) - - // Following options are copied from Options struct. - - OnConnect func(*Conn) error - - Password string - - MaxRetries int - MinRetryBackoff time.Duration - MaxRetryBackoff time.Duration - - DialTimeout time.Duration - ReadTimeout time.Duration - WriteTimeout time.Duration - - // PoolSize applies per cluster node and not for the whole cluster. - PoolSize int - MinIdleConns int - MaxConnAge time.Duration - PoolTimeout time.Duration - IdleTimeout time.Duration - IdleCheckFrequency time.Duration - - TLSConfig *tls.Config -} - -func (opt *ClusterOptions) init() { - if opt.MaxRedirects == -1 { - opt.MaxRedirects = 0 - } else if opt.MaxRedirects == 0 { - opt.MaxRedirects = 8 - } - - if (opt.RouteByLatency || opt.RouteRandomly) && opt.ClusterSlots == nil { - opt.ReadOnly = true - } - - if opt.PoolSize == 0 { - opt.PoolSize = 5 * runtime.NumCPU() - } - - switch opt.ReadTimeout { - case -1: - opt.ReadTimeout = 0 - case 0: - opt.ReadTimeout = 3 * time.Second - } - switch opt.WriteTimeout { - case -1: - opt.WriteTimeout = 0 - case 0: - opt.WriteTimeout = opt.ReadTimeout - } - - switch opt.MinRetryBackoff { - case -1: - opt.MinRetryBackoff = 0 - case 0: - opt.MinRetryBackoff = 8 * time.Millisecond - } - switch opt.MaxRetryBackoff { - case -1: - opt.MaxRetryBackoff = 0 - case 0: - opt.MaxRetryBackoff = 512 * time.Millisecond - } -} - -func (opt *ClusterOptions) clientOptions() *Options { - const disableIdleCheck = -1 - - return &Options{ - OnConnect: opt.OnConnect, - - MaxRetries: opt.MaxRetries, - MinRetryBackoff: opt.MinRetryBackoff, - MaxRetryBackoff: opt.MaxRetryBackoff, - Password: opt.Password, - readOnly: opt.ReadOnly, - - DialTimeout: opt.DialTimeout, - ReadTimeout: opt.ReadTimeout, - WriteTimeout: opt.WriteTimeout, - - PoolSize: opt.PoolSize, - MinIdleConns: opt.MinIdleConns, - MaxConnAge: opt.MaxConnAge, - PoolTimeout: opt.PoolTimeout, - IdleTimeout: opt.IdleTimeout, - IdleCheckFrequency: disableIdleCheck, - - TLSConfig: opt.TLSConfig, - } -} - -//------------------------------------------------------------------------------ - -type clusterNode struct { - Client *Client - - latency uint32 // atomic - generation uint32 // atomic - loading uint32 // atomic -} - -func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode { - opt := clOpt.clientOptions() - opt.Addr = addr - node := clusterNode{ - Client: NewClient(opt), - } - - node.latency = math.MaxUint32 - if clOpt.RouteByLatency { - go node.updateLatency() - } - - if clOpt.OnNewNode != nil { - clOpt.OnNewNode(node.Client) - } - - return &node -} - -func (n *clusterNode) String() string { - return n.Client.String() -} - -func (n *clusterNode) Close() error { - return n.Client.Close() -} - -func (n *clusterNode) updateLatency() { - const probes = 10 - - var latency uint32 - for i := 0; i < probes; i++ { - start := time.Now() - n.Client.Ping() - probe := uint32(time.Since(start) / time.Microsecond) - latency = (latency + probe) / 2 - } - atomic.StoreUint32(&n.latency, latency) -} - -func (n *clusterNode) Latency() time.Duration { - latency := atomic.LoadUint32(&n.latency) - return time.Duration(latency) * time.Microsecond -} - -func (n *clusterNode) MarkAsLoading() { - atomic.StoreUint32(&n.loading, uint32(time.Now().Unix())) -} - -func (n *clusterNode) Loading() bool { - const minute = int64(time.Minute / time.Second) - - loading := atomic.LoadUint32(&n.loading) - if loading == 0 { - return false - } - if time.Now().Unix()-int64(loading) < minute { - return true - } - atomic.StoreUint32(&n.loading, 0) - return false -} - -func (n *clusterNode) Generation() uint32 { - return atomic.LoadUint32(&n.generation) -} - -func (n *clusterNode) SetGeneration(gen uint32) { - for { - v := atomic.LoadUint32(&n.generation) - if gen < v || atomic.CompareAndSwapUint32(&n.generation, v, gen) { - break - } - } -} - -//------------------------------------------------------------------------------ - -type clusterNodes struct { - opt *ClusterOptions - - mu sync.RWMutex - allAddrs []string - allNodes map[string]*clusterNode - clusterAddrs []string - closed bool - - _generation uint32 // atomic -} - -func newClusterNodes(opt *ClusterOptions) *clusterNodes { - return &clusterNodes{ - opt: opt, - - allAddrs: opt.Addrs, - allNodes: make(map[string]*clusterNode), - } -} - -func (c *clusterNodes) Close() error { - c.mu.Lock() - defer c.mu.Unlock() - - if c.closed { - return nil - } - c.closed = true - - var firstErr error - for _, node := range c.allNodes { - if err := node.Client.Close(); err != nil && firstErr == nil { - firstErr = err - } - } - - c.allNodes = nil - c.clusterAddrs = nil - - return firstErr -} - -func (c *clusterNodes) Addrs() ([]string, error) { - var addrs []string - c.mu.RLock() - closed := c.closed - if !closed { - if len(c.clusterAddrs) > 0 { - addrs = c.clusterAddrs - } else { - addrs = c.allAddrs - } - } - c.mu.RUnlock() - - if closed { - return nil, pool.ErrClosed - } - if len(addrs) == 0 { - return nil, errClusterNoNodes - } - return addrs, nil -} - -func (c *clusterNodes) NextGeneration() uint32 { - return atomic.AddUint32(&c._generation, 1) -} - -// GC removes unused nodes. -func (c *clusterNodes) GC(generation uint32) { - var collected []*clusterNode - c.mu.Lock() - for addr, node := range c.allNodes { - if node.Generation() >= generation { - continue - } - - c.clusterAddrs = remove(c.clusterAddrs, addr) - delete(c.allNodes, addr) - collected = append(collected, node) - } - c.mu.Unlock() - - for _, node := range collected { - _ = node.Client.Close() - } -} - -func (c *clusterNodes) Get(addr string) (*clusterNode, error) { - var node *clusterNode - var err error - c.mu.RLock() - if c.closed { - err = pool.ErrClosed - } else { - node = c.allNodes[addr] - } - c.mu.RUnlock() - return node, err -} - -func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { - node, err := c.Get(addr) - if err != nil { - return nil, err - } - if node != nil { - return node, nil - } - - c.mu.Lock() - defer c.mu.Unlock() - - if c.closed { - return nil, pool.ErrClosed - } - - node, ok := c.allNodes[addr] - if ok { - return node, err - } - - node = newClusterNode(c.opt, addr) - - c.allAddrs = appendIfNotExists(c.allAddrs, addr) - c.clusterAddrs = append(c.clusterAddrs, addr) - c.allNodes[addr] = node - - return node, err -} - -func (c *clusterNodes) All() ([]*clusterNode, error) { - c.mu.RLock() - defer c.mu.RUnlock() - - if c.closed { - return nil, pool.ErrClosed - } - - cp := make([]*clusterNode, 0, len(c.allNodes)) - for _, node := range c.allNodes { - cp = append(cp, node) - } - return cp, nil -} - -func (c *clusterNodes) Random() (*clusterNode, error) { - addrs, err := c.Addrs() - if err != nil { - return nil, err - } - - n := rand.Intn(len(addrs)) - return c.GetOrCreate(addrs[n]) -} - -//------------------------------------------------------------------------------ - -type clusterSlot struct { - start, end int - nodes []*clusterNode -} - -type clusterSlotSlice []*clusterSlot - -func (p clusterSlotSlice) Len() int { - return len(p) -} - -func (p clusterSlotSlice) Less(i, j int) bool { - return p[i].start < p[j].start -} - -func (p clusterSlotSlice) Swap(i, j int) { - p[i], p[j] = p[j], p[i] -} - -type clusterState struct { - nodes *clusterNodes - Masters []*clusterNode - Slaves []*clusterNode - - slots []*clusterSlot - - generation uint32 - createdAt time.Time -} - -func newClusterState( - nodes *clusterNodes, slots []ClusterSlot, origin string, -) (*clusterState, error) { - c := clusterState{ - nodes: nodes, - - slots: make([]*clusterSlot, 0, len(slots)), - - generation: nodes.NextGeneration(), - createdAt: time.Now(), - } - - originHost, _, _ := net.SplitHostPort(origin) - isLoopbackOrigin := isLoopback(originHost) - - for _, slot := range slots { - var nodes []*clusterNode - for i, slotNode := range slot.Nodes { - addr := slotNode.Addr - if !isLoopbackOrigin { - addr = replaceLoopbackHost(addr, originHost) - } - - node, err := c.nodes.GetOrCreate(addr) - if err != nil { - return nil, err - } - - node.SetGeneration(c.generation) - nodes = append(nodes, node) - - if i == 0 { - c.Masters = appendUniqueNode(c.Masters, node) - } else { - c.Slaves = appendUniqueNode(c.Slaves, node) - } - } - - c.slots = append(c.slots, &clusterSlot{ - start: slot.Start, - end: slot.End, - nodes: nodes, - }) - } - - sort.Sort(clusterSlotSlice(c.slots)) - - time.AfterFunc(time.Minute, func() { - nodes.GC(c.generation) - }) - - return &c, nil -} - -func replaceLoopbackHost(nodeAddr, originHost string) string { - nodeHost, nodePort, err := net.SplitHostPort(nodeAddr) - if err != nil { - return nodeAddr - } - - nodeIP := net.ParseIP(nodeHost) - if nodeIP == nil { - return nodeAddr - } - - if !nodeIP.IsLoopback() { - return nodeAddr - } - - // Use origin host which is not loopback and node port. - return net.JoinHostPort(originHost, nodePort) -} - -func isLoopback(host string) bool { - ip := net.ParseIP(host) - if ip == nil { - return true - } - return ip.IsLoopback() -} - -func (c *clusterState) slotMasterNode(slot int) (*clusterNode, error) { - nodes := c.slotNodes(slot) - if len(nodes) > 0 { - return nodes[0], nil - } - return c.nodes.Random() -} - -func (c *clusterState) slotSlaveNode(slot int) (*clusterNode, error) { - nodes := c.slotNodes(slot) - switch len(nodes) { - case 0: - return c.nodes.Random() - case 1: - return nodes[0], nil - case 2: - if slave := nodes[1]; !slave.Loading() { - return slave, nil - } - return nodes[0], nil - default: - var slave *clusterNode - for i := 0; i < 10; i++ { - n := rand.Intn(len(nodes)-1) + 1 - slave = nodes[n] - if !slave.Loading() { - return slave, nil - } - } - - // All slaves are loading - use master. - return nodes[0], nil - } -} - -func (c *clusterState) slotClosestNode(slot int) (*clusterNode, error) { - const threshold = time.Millisecond - - nodes := c.slotNodes(slot) - if len(nodes) == 0 { - return c.nodes.Random() - } - - var node *clusterNode - for _, n := range nodes { - if n.Loading() { - continue - } - if node == nil || node.Latency()-n.Latency() > threshold { - node = n - } - } - return node, nil -} - -func (c *clusterState) slotRandomNode(slot int) *clusterNode { - nodes := c.slotNodes(slot) - n := rand.Intn(len(nodes)) - return nodes[n] -} - -func (c *clusterState) slotNodes(slot int) []*clusterNode { - i := sort.Search(len(c.slots), func(i int) bool { - return c.slots[i].end >= slot - }) - if i >= len(c.slots) { - return nil - } - x := c.slots[i] - if slot >= x.start && slot <= x.end { - return x.nodes - } - return nil -} - -//------------------------------------------------------------------------------ - -type clusterStateHolder struct { - load func() (*clusterState, error) - - state atomic.Value - reloading uint32 // atomic -} - -func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder { - return &clusterStateHolder{ - load: fn, - } -} - -func (c *clusterStateHolder) Reload() (*clusterState, error) { - state, err := c.load() - if err != nil { - return nil, err - } - c.state.Store(state) - return state, nil -} - -func (c *clusterStateHolder) LazyReload() { - if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { - return - } - go func() { - defer atomic.StoreUint32(&c.reloading, 0) - - _, err := c.Reload() - if err != nil { - return - } - time.Sleep(100 * time.Millisecond) - }() -} - -func (c *clusterStateHolder) Get() (*clusterState, error) { - v := c.state.Load() - if v != nil { - state := v.(*clusterState) - if time.Since(state.createdAt) > time.Minute { - c.LazyReload() - } - return state, nil - } - return c.Reload() -} - -func (c *clusterStateHolder) ReloadOrGet() (*clusterState, error) { - state, err := c.Reload() - if err == nil { - return state, nil - } - return c.Get() -} - -//------------------------------------------------------------------------------ - -// ClusterClient is a Redis Cluster client representing a pool of zero -// or more underlying connections. It's safe for concurrent use by -// multiple goroutines. -type ClusterClient struct { - cmdable - - ctx context.Context - - opt *ClusterOptions - nodes *clusterNodes - state *clusterStateHolder - cmdsInfoCache *cmdsInfoCache - - process func(Cmder) error - processPipeline func([]Cmder) error - processTxPipeline func([]Cmder) error -} - -// NewClusterClient returns a Redis Cluster client as described in -// http://redis.io/topics/cluster-spec. -func NewClusterClient(opt *ClusterOptions) *ClusterClient { - opt.init() - - c := &ClusterClient{ - opt: opt, - nodes: newClusterNodes(opt), - } - c.state = newClusterStateHolder(c.loadState) - c.cmdsInfoCache = newCmdsInfoCache(c.cmdsInfo) - - c.process = c.defaultProcess - c.processPipeline = c.defaultProcessPipeline - c.processTxPipeline = c.defaultProcessTxPipeline - - c.init() - if opt.IdleCheckFrequency > 0 { - go c.reaper(opt.IdleCheckFrequency) - } - - return c -} - -func (c *ClusterClient) init() { - c.cmdable.setProcessor(c.Process) -} - -// ReloadState reloads cluster state. If available it calls ClusterSlots func -// to get cluster slots information. -func (c *ClusterClient) ReloadState() error { - _, err := c.state.Reload() - return err -} - -func (c *ClusterClient) Context() context.Context { - if c.ctx != nil { - return c.ctx - } - return context.Background() -} - -func (c *ClusterClient) WithContext(ctx context.Context) *ClusterClient { - if ctx == nil { - panic("nil context") - } - c2 := c.clone() - c2.ctx = ctx - return c2 -} - -func (c *ClusterClient) clone() *ClusterClient { - cp := *c - cp.init() - return &cp -} - -// Options returns read-only Options that were used to create the client. -func (c *ClusterClient) Options() *ClusterOptions { - return c.opt -} - -func (c *ClusterClient) retryBackoff(attempt int) time.Duration { - return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff) -} - -func (c *ClusterClient) cmdsInfo() (map[string]*CommandInfo, error) { - addrs, err := c.nodes.Addrs() - if err != nil { - return nil, err - } - - var firstErr error - for _, addr := range addrs { - node, err := c.nodes.Get(addr) - if err != nil { - return nil, err - } - if node == nil { - continue - } - - info, err := node.Client.Command().Result() - if err == nil { - return info, nil - } - if firstErr == nil { - firstErr = err - } - } - return nil, firstErr -} - -func (c *ClusterClient) cmdInfo(name string) *CommandInfo { - cmdsInfo, err := c.cmdsInfoCache.Get() - if err != nil { - return nil - } - - info := cmdsInfo[name] - if info == nil { - internal.Logf("info for cmd=%s not found", name) - } - return info -} - -func cmdSlot(cmd Cmder, pos int) int { - if pos == 0 { - return hashtag.RandomSlot() - } - firstKey := cmd.stringArg(pos) - return hashtag.Slot(firstKey) -} - -func (c *ClusterClient) cmdSlot(cmd Cmder) int { - args := cmd.Args() - if args[0] == "cluster" && args[1] == "getkeysinslot" { - return args[2].(int) - } - - cmdInfo := c.cmdInfo(cmd.Name()) - return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) -} - -func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { - state, err := c.state.Get() - if err != nil { - return 0, nil, err - } - - cmdInfo := c.cmdInfo(cmd.Name()) - slot := c.cmdSlot(cmd) - - if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly { - if c.opt.RouteByLatency { - node, err := state.slotClosestNode(slot) - return slot, node, err - } - - if c.opt.RouteRandomly { - node := state.slotRandomNode(slot) - return slot, node, nil - } - - node, err := state.slotSlaveNode(slot) - return slot, node, err - } - - node, err := state.slotMasterNode(slot) - return slot, node, err -} - -func (c *ClusterClient) slotMasterNode(slot int) (*clusterNode, error) { - state, err := c.state.Get() - if err != nil { - return nil, err - } - - nodes := state.slotNodes(slot) - if len(nodes) > 0 { - return nodes[0], nil - } - return c.nodes.Random() -} - -func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { - if len(keys) == 0 { - return fmt.Errorf("redis: Watch requires at least one key") - } - - slot := hashtag.Slot(keys[0]) - for _, key := range keys[1:] { - if hashtag.Slot(key) != slot { - err := fmt.Errorf("redis: Watch requires all keys to be in the same slot") - return err - } - } - - node, err := c.slotMasterNode(slot) - if err != nil { - return err - } - - for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { - if attempt > 0 { - time.Sleep(c.retryBackoff(attempt)) - } - - err = node.Client.Watch(fn, keys...) - if err == nil { - break - } - if err != Nil { - c.state.LazyReload() - } - - moved, ask, addr := internal.IsMovedError(err) - if moved || ask { - node, err = c.nodes.GetOrCreate(addr) - if err != nil { - return err - } - continue - } - - if err == pool.ErrClosed || internal.IsReadOnlyError(err) { - node, err = c.slotMasterNode(slot) - if err != nil { - return err - } - continue - } - - if internal.IsRetryableError(err, true) { - continue - } - - return err - } - - return err -} - -// Close closes the cluster client, releasing any open resources. -// -// It is rare to Close a ClusterClient, as the ClusterClient is meant -// to be long-lived and shared between many goroutines. -func (c *ClusterClient) Close() error { - return c.nodes.Close() -} - -// Do creates a Cmd from the args and processes the cmd. -func (c *ClusterClient) Do(args ...interface{}) *Cmd { - cmd := NewCmd(args...) - c.Process(cmd) - return cmd -} - -func (c *ClusterClient) WrapProcess( - fn func(oldProcess func(Cmder) error) func(Cmder) error, -) { - c.process = fn(c.process) -} - -func (c *ClusterClient) Process(cmd Cmder) error { - return c.process(cmd) -} - -func (c *ClusterClient) defaultProcess(cmd Cmder) error { - var node *clusterNode - var ask bool - for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { - if attempt > 0 { - time.Sleep(c.retryBackoff(attempt)) - } - - if node == nil { - var err error - _, node, err = c.cmdSlotAndNode(cmd) - if err != nil { - cmd.setErr(err) - break - } - } - - var err error - if ask { - pipe := node.Client.Pipeline() - _ = pipe.Process(NewCmd("ASKING")) - _ = pipe.Process(cmd) - _, err = pipe.Exec() - _ = pipe.Close() - ask = false - } else { - err = node.Client.Process(cmd) - } - - // If there is no error - we are done. - if err == nil { - break - } - if err != Nil { - c.state.LazyReload() - } - - // If slave is loading - pick another node. - if c.opt.ReadOnly && internal.IsLoadingError(err) { - node.MarkAsLoading() - node = nil - continue - } - - var moved bool - var addr string - moved, ask, addr = internal.IsMovedError(err) - if moved || ask { - node, err = c.nodes.GetOrCreate(addr) - if err != nil { - break - } - continue - } - - if err == pool.ErrClosed || internal.IsReadOnlyError(err) { - node = nil - continue - } - - if internal.IsRetryableError(err, true) { - // First retry the same node. - if attempt == 0 { - continue - } - - // Second try random node. - node, err = c.nodes.Random() - if err != nil { - break - } - continue - } - - break - } - - return cmd.Err() -} - -// ForEachMaster concurrently calls the fn on each master node in the cluster. -// It returns the first error if any. -func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { - state, err := c.state.ReloadOrGet() - if err != nil { - return err - } - - var wg sync.WaitGroup - errCh := make(chan error, 1) - for _, master := range state.Masters { - wg.Add(1) - go func(node *clusterNode) { - defer wg.Done() - err := fn(node.Client) - if err != nil { - select { - case errCh <- err: - default: - } - } - }(master) - } - wg.Wait() - - select { - case err := <-errCh: - return err - default: - return nil - } -} - -// ForEachSlave concurrently calls the fn on each slave node in the cluster. -// It returns the first error if any. -func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { - state, err := c.state.ReloadOrGet() - if err != nil { - return err - } - - var wg sync.WaitGroup - errCh := make(chan error, 1) - for _, slave := range state.Slaves { - wg.Add(1) - go func(node *clusterNode) { - defer wg.Done() - err := fn(node.Client) - if err != nil { - select { - case errCh <- err: - default: - } - } - }(slave) - } - wg.Wait() - - select { - case err := <-errCh: - return err - default: - return nil - } -} - -// ForEachNode concurrently calls the fn on each known node in the cluster. -// It returns the first error if any. -func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { - state, err := c.state.ReloadOrGet() - if err != nil { - return err - } - - var wg sync.WaitGroup - errCh := make(chan error, 1) - worker := func(node *clusterNode) { - defer wg.Done() - err := fn(node.Client) - if err != nil { - select { - case errCh <- err: - default: - } - } - } - - for _, node := range state.Masters { - wg.Add(1) - go worker(node) - } - for _, node := range state.Slaves { - wg.Add(1) - go worker(node) - } - - wg.Wait() - select { - case err := <-errCh: - return err - default: - return nil - } -} - -// PoolStats returns accumulated connection pool stats. -func (c *ClusterClient) PoolStats() *PoolStats { - var acc PoolStats - - state, _ := c.state.Get() - if state == nil { - return &acc - } - - for _, node := range state.Masters { - s := node.Client.connPool.Stats() - acc.Hits += s.Hits - acc.Misses += s.Misses - acc.Timeouts += s.Timeouts - - acc.TotalConns += s.TotalConns - acc.IdleConns += s.IdleConns - acc.StaleConns += s.StaleConns - } - - for _, node := range state.Slaves { - s := node.Client.connPool.Stats() - acc.Hits += s.Hits - acc.Misses += s.Misses - acc.Timeouts += s.Timeouts - - acc.TotalConns += s.TotalConns - acc.IdleConns += s.IdleConns - acc.StaleConns += s.StaleConns - } - - return &acc -} - -func (c *ClusterClient) loadState() (*clusterState, error) { - if c.opt.ClusterSlots != nil { - slots, err := c.opt.ClusterSlots() - if err != nil { - return nil, err - } - return newClusterState(c.nodes, slots, "") - } - - addrs, err := c.nodes.Addrs() - if err != nil { - return nil, err - } - - var firstErr error - for _, addr := range addrs { - node, err := c.nodes.GetOrCreate(addr) - if err != nil { - if firstErr == nil { - firstErr = err - } - continue - } - - slots, err := node.Client.ClusterSlots().Result() - if err != nil { - if firstErr == nil { - firstErr = err - } - continue - } - - return newClusterState(c.nodes, slots, node.Client.opt.Addr) - } - - return nil, firstErr -} - -// reaper closes idle connections to the cluster. -func (c *ClusterClient) reaper(idleCheckFrequency time.Duration) { - ticker := time.NewTicker(idleCheckFrequency) - defer ticker.Stop() - - for range ticker.C { - nodes, err := c.nodes.All() - if err != nil { - break - } - - for _, node := range nodes { - _, err := node.Client.connPool.(*pool.ConnPool).ReapStaleConns() - if err != nil { - internal.Logf("ReapStaleConns failed: %s", err) - } - } - } -} - -func (c *ClusterClient) Pipeline() Pipeliner { - pipe := Pipeline{ - exec: c.processPipeline, - } - pipe.statefulCmdable.setProcessor(pipe.Process) - return &pipe -} - -func (c *ClusterClient) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { - return c.Pipeline().Pipelined(fn) -} - -func (c *ClusterClient) WrapProcessPipeline( - fn func(oldProcess func([]Cmder) error) func([]Cmder) error, -) { - c.processPipeline = fn(c.processPipeline) - c.processTxPipeline = fn(c.processTxPipeline) -} - -func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error { - cmdsMap := newCmdsMap() - err := c.mapCmdsByNode(cmds, cmdsMap) - if err != nil { - setCmdsErr(cmds, err) - return err - } - - for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { - if attempt > 0 { - time.Sleep(c.retryBackoff(attempt)) - } - - failedCmds := newCmdsMap() - var wg sync.WaitGroup - - for node, cmds := range cmdsMap.m { - wg.Add(1) - go func(node *clusterNode, cmds []Cmder) { - defer wg.Done() - - cn, err := node.Client.getConn() - if err != nil { - if err == pool.ErrClosed { - c.mapCmdsByNode(cmds, failedCmds) - } else { - setCmdsErr(cmds, err) - } - return - } - - err = c.pipelineProcessCmds(node, cn, cmds, failedCmds) - node.Client.releaseConnStrict(cn, err) - }(node, cmds) - } - - wg.Wait() - if len(failedCmds.m) == 0 { - break - } - cmdsMap = failedCmds - } - - return cmdsFirstErr(cmds) -} - -type cmdsMap struct { - mu sync.Mutex - m map[*clusterNode][]Cmder -} - -func newCmdsMap() *cmdsMap { - return &cmdsMap{ - m: make(map[*clusterNode][]Cmder), - } -} - -func (c *ClusterClient) mapCmdsByNode(cmds []Cmder, cmdsMap *cmdsMap) error { - state, err := c.state.Get() - if err != nil { - setCmdsErr(cmds, err) - return err - } - - cmdsAreReadOnly := c.cmdsAreReadOnly(cmds) - for _, cmd := range cmds { - var node *clusterNode - var err error - if cmdsAreReadOnly { - _, node, err = c.cmdSlotAndNode(cmd) - } else { - slot := c.cmdSlot(cmd) - node, err = state.slotMasterNode(slot) - } - if err != nil { - return err - } - cmdsMap.mu.Lock() - cmdsMap.m[node] = append(cmdsMap.m[node], cmd) - cmdsMap.mu.Unlock() - } - return nil -} - -func (c *ClusterClient) cmdsAreReadOnly(cmds []Cmder) bool { - for _, cmd := range cmds { - cmdInfo := c.cmdInfo(cmd.Name()) - if cmdInfo == nil || !cmdInfo.ReadOnly { - return false - } - } - return true -} - -func (c *ClusterClient) pipelineProcessCmds( - node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds *cmdsMap, -) error { - err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error { - return writeCmd(wr, cmds...) - }) - if err != nil { - setCmdsErr(cmds, err) - failedCmds.mu.Lock() - failedCmds.m[node] = cmds - failedCmds.mu.Unlock() - return err - } - - err = cn.WithReader(c.opt.ReadTimeout, func(rd *proto.Reader) error { - return c.pipelineReadCmds(node, rd, cmds, failedCmds) - }) - return err -} - -func (c *ClusterClient) pipelineReadCmds( - node *clusterNode, rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap, -) error { - var firstErr error - for _, cmd := range cmds { - err := cmd.readReply(rd) - if err == nil { - continue - } - - if c.checkMovedErr(cmd, err, failedCmds) { - continue - } - - if internal.IsRedisError(err) { - continue - } - - failedCmds.mu.Lock() - failedCmds.m[node] = append(failedCmds.m[node], cmd) - failedCmds.mu.Unlock() - if firstErr == nil { - firstErr = err - } - } - return firstErr -} - -func (c *ClusterClient) checkMovedErr( - cmd Cmder, err error, failedCmds *cmdsMap, -) bool { - moved, ask, addr := internal.IsMovedError(err) - - if moved { - c.state.LazyReload() - - node, err := c.nodes.GetOrCreate(addr) - if err != nil { - return false - } - - failedCmds.mu.Lock() - failedCmds.m[node] = append(failedCmds.m[node], cmd) - failedCmds.mu.Unlock() - return true - } - - if ask { - node, err := c.nodes.GetOrCreate(addr) - if err != nil { - return false - } - - failedCmds.mu.Lock() - failedCmds.m[node] = append(failedCmds.m[node], NewCmd("ASKING"), cmd) - failedCmds.mu.Unlock() - return true - } - - return false -} - -// TxPipeline acts like Pipeline, but wraps queued commands with MULTI/EXEC. -func (c *ClusterClient) TxPipeline() Pipeliner { - pipe := Pipeline{ - exec: c.processTxPipeline, - } - pipe.statefulCmdable.setProcessor(pipe.Process) - return &pipe -} - -func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { - return c.TxPipeline().Pipelined(fn) -} - -func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error { - state, err := c.state.Get() - if err != nil { - return err - } - - cmdsMap := c.mapCmdsBySlot(cmds) - for slot, cmds := range cmdsMap { - node, err := state.slotMasterNode(slot) - if err != nil { - setCmdsErr(cmds, err) - continue - } - cmdsMap := map[*clusterNode][]Cmder{node: cmds} - - for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { - if attempt > 0 { - time.Sleep(c.retryBackoff(attempt)) - } - - failedCmds := newCmdsMap() - var wg sync.WaitGroup - - for node, cmds := range cmdsMap { - wg.Add(1) - go func(node *clusterNode, cmds []Cmder) { - defer wg.Done() - - cn, err := node.Client.getConn() - if err != nil { - if err == pool.ErrClosed { - c.mapCmdsByNode(cmds, failedCmds) - } else { - setCmdsErr(cmds, err) - } - return - } - - err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds) - node.Client.releaseConnStrict(cn, err) - }(node, cmds) - } - - wg.Wait() - if len(failedCmds.m) == 0 { - break - } - cmdsMap = failedCmds.m - } - } - - return cmdsFirstErr(cmds) -} - -func (c *ClusterClient) mapCmdsBySlot(cmds []Cmder) map[int][]Cmder { - cmdsMap := make(map[int][]Cmder) - for _, cmd := range cmds { - slot := c.cmdSlot(cmd) - cmdsMap[slot] = append(cmdsMap[slot], cmd) - } - return cmdsMap -} - -func (c *ClusterClient) txPipelineProcessCmds( - node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds *cmdsMap, -) error { - err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error { - return txPipelineWriteMulti(wr, cmds) - }) - if err != nil { - setCmdsErr(cmds, err) - failedCmds.mu.Lock() - failedCmds.m[node] = cmds - failedCmds.mu.Unlock() - return err - } - - err = cn.WithReader(c.opt.ReadTimeout, func(rd *proto.Reader) error { - err := c.txPipelineReadQueued(rd, cmds, failedCmds) - if err != nil { - setCmdsErr(cmds, err) - return err - } - return pipelineReadCmds(rd, cmds) - }) - return err -} - -func (c *ClusterClient) txPipelineReadQueued( - rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap, -) error { - // Parse queued replies. - var statusCmd StatusCmd - if err := statusCmd.readReply(rd); err != nil { - return err - } - - for _, cmd := range cmds { - err := statusCmd.readReply(rd) - if err == nil { - continue - } - - if c.checkMovedErr(cmd, err, failedCmds) || internal.IsRedisError(err) { - continue - } - - return err - } - - // Parse number of replies. - line, err := rd.ReadLine() - if err != nil { - if err == Nil { - err = TxFailedErr - } - return err - } - - switch line[0] { - case proto.ErrorReply: - err := proto.ParseErrorReply(line) - for _, cmd := range cmds { - if !c.checkMovedErr(cmd, err, failedCmds) { - break - } - } - return err - case proto.ArrayReply: - // ok - default: - err := fmt.Errorf("redis: expected '*', but got line %q", line) - return err - } - - return nil -} - -func (c *ClusterClient) pubSub() *PubSub { - var node *clusterNode - pubsub := &PubSub{ - opt: c.opt.clientOptions(), - - newConn: func(channels []string) (*pool.Conn, error) { - if node != nil { - panic("node != nil") - } - - var err error - if len(channels) > 0 { - slot := hashtag.Slot(channels[0]) - node, err = c.slotMasterNode(slot) - } else { - node, err = c.nodes.Random() - } - if err != nil { - return nil, err - } - - cn, err := node.Client.newConn() - if err != nil { - node = nil - - return nil, err - } - - return cn, nil - }, - closeConn: func(cn *pool.Conn) error { - err := node.Client.connPool.CloseConn(cn) - node = nil - return err - }, - } - pubsub.init() - - return pubsub -} - -// Subscribe subscribes the client to the specified channels. -// Channels can be omitted to create empty subscription. -func (c *ClusterClient) Subscribe(channels ...string) *PubSub { - pubsub := c.pubSub() - if len(channels) > 0 { - _ = pubsub.Subscribe(channels...) - } - return pubsub -} - -// PSubscribe subscribes the client to the given patterns. -// Patterns can be omitted to create empty subscription. -func (c *ClusterClient) PSubscribe(channels ...string) *PubSub { - pubsub := c.pubSub() - if len(channels) > 0 { - _ = pubsub.PSubscribe(channels...) - } - return pubsub -} - -func appendUniqueNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { - for _, n := range nodes { - if n == node { - return nodes - } - } - return append(nodes, node) -} - -func appendIfNotExists(ss []string, es ...string) []string { -loop: - for _, e := range es { - for _, s := range ss { - if s == e { - continue loop - } - } - ss = append(ss, e) - } - return ss -} - -func remove(ss []string, es ...string) []string { - if len(es) == 0 { - return ss[:0] - } - for _, e := range es { - for i, s := range ss { - if s == e { - ss = append(ss[:i], ss[i+1:]...) - break - } - } - } - return ss -} diff --git a/vendor/github.com/go-redis/redis/cluster_commands.go b/vendor/github.com/go-redis/redis/cluster_commands.go deleted file mode 100644 index dff62c902d..0000000000 --- a/vendor/github.com/go-redis/redis/cluster_commands.go +++ /dev/null @@ -1,22 +0,0 @@ -package redis - -import "sync/atomic" - -func (c *ClusterClient) DBSize() *IntCmd { - cmd := NewIntCmd("dbsize") - var size int64 - err := c.ForEachMaster(func(master *Client) error { - n, err := master.DBSize().Result() - if err != nil { - return err - } - atomic.AddInt64(&size, n) - return nil - }) - if err != nil { - cmd.setErr(err) - return cmd - } - cmd.val = size - return cmd -} diff --git a/vendor/github.com/go-redis/redis/command.go b/vendor/github.com/go-redis/redis/command.go deleted file mode 100644 index c70973d3bf..0000000000 --- a/vendor/github.com/go-redis/redis/command.go +++ /dev/null @@ -1,1972 +0,0 @@ -package redis - -import ( - "fmt" - "net" - "strconv" - "strings" - "time" - - "github.com/go-redis/redis/internal" - "github.com/go-redis/redis/internal/proto" -) - -type Cmder interface { - Name() string - Args() []interface{} - stringArg(int) string - - readReply(rd *proto.Reader) error - setErr(error) - - readTimeout() *time.Duration - - Err() error -} - -func setCmdsErr(cmds []Cmder, e error) { - for _, cmd := range cmds { - if cmd.Err() == nil { - cmd.setErr(e) - } - } -} - -func cmdsFirstErr(cmds []Cmder) error { - for _, cmd := range cmds { - if err := cmd.Err(); err != nil { - return err - } - } - return nil -} - -func writeCmd(wr *proto.Writer, cmds ...Cmder) error { - for _, cmd := range cmds { - err := wr.WriteArgs(cmd.Args()) - if err != nil { - return err - } - } - return nil -} - -func cmdString(cmd Cmder, val interface{}) string { - var ss []string - for _, arg := range cmd.Args() { - ss = append(ss, fmt.Sprint(arg)) - } - s := strings.Join(ss, " ") - if err := cmd.Err(); err != nil { - return s + ": " + err.Error() - } - if val != nil { - switch vv := val.(type) { - case []byte: - return s + ": " + string(vv) - default: - return s + ": " + fmt.Sprint(val) - } - } - return s - -} - -func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int { - switch cmd.Name() { - case "eval", "evalsha": - if cmd.stringArg(2) != "0" { - return 3 - } - - return 0 - case "publish": - return 1 - } - if info == nil { - return 0 - } - return int(info.FirstKeyPos) -} - -//------------------------------------------------------------------------------ - -type baseCmd struct { - _args []interface{} - err error - - _readTimeout *time.Duration -} - -var _ Cmder = (*Cmd)(nil) - -func (cmd *baseCmd) Err() error { - return cmd.err -} - -func (cmd *baseCmd) Args() []interface{} { - return cmd._args -} - -func (cmd *baseCmd) stringArg(pos int) string { - if pos < 0 || pos >= len(cmd._args) { - return "" - } - s, _ := cmd._args[pos].(string) - return s -} - -func (cmd *baseCmd) Name() string { - if len(cmd._args) > 0 { - // Cmd name must be lower cased. - s := internal.ToLower(cmd.stringArg(0)) - cmd._args[0] = s - return s - } - return "" -} - -func (cmd *baseCmd) readTimeout() *time.Duration { - return cmd._readTimeout -} - -func (cmd *baseCmd) setReadTimeout(d time.Duration) { - cmd._readTimeout = &d -} - -func (cmd *baseCmd) setErr(e error) { - cmd.err = e -} - -//------------------------------------------------------------------------------ - -type Cmd struct { - baseCmd - - val interface{} -} - -func NewCmd(args ...interface{}) *Cmd { - return &Cmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *Cmd) Val() interface{} { - return cmd.val -} - -func (cmd *Cmd) Result() (interface{}, error) { - return cmd.val, cmd.err -} - -func (cmd *Cmd) String() (string, error) { - if cmd.err != nil { - return "", cmd.err - } - switch val := cmd.val.(type) { - case string: - return val, nil - default: - err := fmt.Errorf("redis: unexpected type=%T for String", val) - return "", err - } -} - -func (cmd *Cmd) Int() (int, error) { - if cmd.err != nil { - return 0, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return int(val), nil - case string: - return strconv.Atoi(val) - default: - err := fmt.Errorf("redis: unexpected type=%T for Int", val) - return 0, err - } -} - -func (cmd *Cmd) Int64() (int64, error) { - if cmd.err != nil { - return 0, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return val, nil - case string: - return strconv.ParseInt(val, 10, 64) - default: - err := fmt.Errorf("redis: unexpected type=%T for Int64", val) - return 0, err - } -} - -func (cmd *Cmd) Uint64() (uint64, error) { - if cmd.err != nil { - return 0, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return uint64(val), nil - case string: - return strconv.ParseUint(val, 10, 64) - default: - err := fmt.Errorf("redis: unexpected type=%T for Uint64", val) - return 0, err - } -} - -func (cmd *Cmd) Float32() (float32, error) { - if cmd.err != nil { - return 0, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return float32(val), nil - case string: - f, err := strconv.ParseFloat(val, 32) - if err != nil { - return 0, err - } - return float32(f), nil - default: - err := fmt.Errorf("redis: unexpected type=%T for Float32", val) - return 0, err - } -} - -func (cmd *Cmd) Float64() (float64, error) { - if cmd.err != nil { - return 0, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return float64(val), nil - case string: - return strconv.ParseFloat(val, 64) - default: - err := fmt.Errorf("redis: unexpected type=%T for Float64", val) - return 0, err - } -} - -func (cmd *Cmd) Bool() (bool, error) { - if cmd.err != nil { - return false, cmd.err - } - switch val := cmd.val.(type) { - case int64: - return val != 0, nil - case string: - return strconv.ParseBool(val) - default: - err := fmt.Errorf("redis: unexpected type=%T for Bool", val) - return false, err - } -} - -func (cmd *Cmd) readReply(rd *proto.Reader) error { - cmd.val, cmd.err = rd.ReadReply(sliceParser) - return cmd.err -} - -// Implements proto.MultiBulkParse -func sliceParser(rd *proto.Reader, n int64) (interface{}, error) { - vals := make([]interface{}, 0, n) - for i := int64(0); i < n; i++ { - v, err := rd.ReadReply(sliceParser) - if err != nil { - if err == Nil { - vals = append(vals, nil) - continue - } - if err, ok := err.(proto.RedisError); ok { - vals = append(vals, err) - continue - } - return nil, err - } - - switch v := v.(type) { - case string: - vals = append(vals, v) - default: - vals = append(vals, v) - } - } - return vals, nil -} - -//------------------------------------------------------------------------------ - -type SliceCmd struct { - baseCmd - - val []interface{} -} - -var _ Cmder = (*SliceCmd)(nil) - -func NewSliceCmd(args ...interface{}) *SliceCmd { - return &SliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *SliceCmd) Val() []interface{} { - return cmd.val -} - -func (cmd *SliceCmd) Result() ([]interface{}, error) { - return cmd.val, cmd.err -} - -func (cmd *SliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *SliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(sliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]interface{}) - return nil -} - -//------------------------------------------------------------------------------ - -type StatusCmd struct { - baseCmd - - val string -} - -var _ Cmder = (*StatusCmd)(nil) - -func NewStatusCmd(args ...interface{}) *StatusCmd { - return &StatusCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StatusCmd) Val() string { - return cmd.val -} - -func (cmd *StatusCmd) Result() (string, error) { - return cmd.val, cmd.err -} - -func (cmd *StatusCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StatusCmd) readReply(rd *proto.Reader) error { - cmd.val, cmd.err = rd.ReadString() - return cmd.err -} - -//------------------------------------------------------------------------------ - -type IntCmd struct { - baseCmd - - val int64 -} - -var _ Cmder = (*IntCmd)(nil) - -func NewIntCmd(args ...interface{}) *IntCmd { - return &IntCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *IntCmd) Val() int64 { - return cmd.val -} - -func (cmd *IntCmd) Result() (int64, error) { - return cmd.val, cmd.err -} - -func (cmd *IntCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *IntCmd) readReply(rd *proto.Reader) error { - cmd.val, cmd.err = rd.ReadIntReply() - return cmd.err -} - -//------------------------------------------------------------------------------ - -type DurationCmd struct { - baseCmd - - val time.Duration - precision time.Duration -} - -var _ Cmder = (*DurationCmd)(nil) - -func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd { - return &DurationCmd{ - baseCmd: baseCmd{_args: args}, - precision: precision, - } -} - -func (cmd *DurationCmd) Val() time.Duration { - return cmd.val -} - -func (cmd *DurationCmd) Result() (time.Duration, error) { - return cmd.val, cmd.err -} - -func (cmd *DurationCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *DurationCmd) readReply(rd *proto.Reader) error { - var n int64 - n, cmd.err = rd.ReadIntReply() - if cmd.err != nil { - return cmd.err - } - cmd.val = time.Duration(n) * cmd.precision - return nil -} - -//------------------------------------------------------------------------------ - -type TimeCmd struct { - baseCmd - - val time.Time -} - -var _ Cmder = (*TimeCmd)(nil) - -func NewTimeCmd(args ...interface{}) *TimeCmd { - return &TimeCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *TimeCmd) Val() time.Time { - return cmd.val -} - -func (cmd *TimeCmd) Result() (time.Time, error) { - return cmd.val, cmd.err -} - -func (cmd *TimeCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *TimeCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(timeParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(time.Time) - return nil -} - -// Implements proto.MultiBulkParse -func timeParser(rd *proto.Reader, n int64) (interface{}, error) { - if n != 2 { - return nil, fmt.Errorf("got %d elements, expected 2", n) - } - - sec, err := rd.ReadInt() - if err != nil { - return nil, err - } - - microsec, err := rd.ReadInt() - if err != nil { - return nil, err - } - - return time.Unix(sec, microsec*1000), nil -} - -//------------------------------------------------------------------------------ - -type BoolCmd struct { - baseCmd - - val bool -} - -var _ Cmder = (*BoolCmd)(nil) - -func NewBoolCmd(args ...interface{}) *BoolCmd { - return &BoolCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *BoolCmd) Val() bool { - return cmd.val -} - -func (cmd *BoolCmd) Result() (bool, error) { - return cmd.val, cmd.err -} - -func (cmd *BoolCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *BoolCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadReply(nil) - // `SET key value NX` returns nil when key already exists. But - // `SETNX key value` returns bool (0/1). So convert nil to bool. - // TODO: is this okay? - if cmd.err == Nil { - cmd.val = false - cmd.err = nil - return nil - } - if cmd.err != nil { - return cmd.err - } - switch v := v.(type) { - case int64: - cmd.val = v == 1 - return nil - case string: - cmd.val = v == "OK" - return nil - default: - cmd.err = fmt.Errorf("got %T, wanted int64 or string", v) - return cmd.err - } -} - -//------------------------------------------------------------------------------ - -type StringCmd struct { - baseCmd - - val string -} - -var _ Cmder = (*StringCmd)(nil) - -func NewStringCmd(args ...interface{}) *StringCmd { - return &StringCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StringCmd) Val() string { - return cmd.val -} - -func (cmd *StringCmd) Result() (string, error) { - return cmd.Val(), cmd.err -} - -func (cmd *StringCmd) Bytes() ([]byte, error) { - return []byte(cmd.val), cmd.err -} - -func (cmd *StringCmd) Int() (int, error) { - if cmd.err != nil { - return 0, cmd.err - } - return strconv.Atoi(cmd.Val()) -} - -func (cmd *StringCmd) Int64() (int64, error) { - if cmd.err != nil { - return 0, cmd.err - } - return strconv.ParseInt(cmd.Val(), 10, 64) -} - -func (cmd *StringCmd) Uint64() (uint64, error) { - if cmd.err != nil { - return 0, cmd.err - } - return strconv.ParseUint(cmd.Val(), 10, 64) -} - -func (cmd *StringCmd) Float32() (float32, error) { - if cmd.err != nil { - return 0, cmd.err - } - f, err := strconv.ParseFloat(cmd.Val(), 32) - if err != nil { - return 0, err - } - return float32(f), nil -} - -func (cmd *StringCmd) Float64() (float64, error) { - if cmd.err != nil { - return 0, cmd.err - } - return strconv.ParseFloat(cmd.Val(), 64) -} - -func (cmd *StringCmd) Scan(val interface{}) error { - if cmd.err != nil { - return cmd.err - } - return proto.Scan([]byte(cmd.val), val) -} - -func (cmd *StringCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StringCmd) readReply(rd *proto.Reader) error { - cmd.val, cmd.err = rd.ReadString() - return cmd.err -} - -//------------------------------------------------------------------------------ - -type FloatCmd struct { - baseCmd - - val float64 -} - -var _ Cmder = (*FloatCmd)(nil) - -func NewFloatCmd(args ...interface{}) *FloatCmd { - return &FloatCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *FloatCmd) Val() float64 { - return cmd.val -} - -func (cmd *FloatCmd) Result() (float64, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *FloatCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *FloatCmd) readReply(rd *proto.Reader) error { - cmd.val, cmd.err = rd.ReadFloatReply() - return cmd.err -} - -//------------------------------------------------------------------------------ - -type StringSliceCmd struct { - baseCmd - - val []string -} - -var _ Cmder = (*StringSliceCmd)(nil) - -func NewStringSliceCmd(args ...interface{}) *StringSliceCmd { - return &StringSliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StringSliceCmd) Val() []string { - return cmd.val -} - -func (cmd *StringSliceCmd) Result() ([]string, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *StringSliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StringSliceCmd) ScanSlice(container interface{}) error { - return proto.ScanSlice(cmd.Val(), container) -} - -func (cmd *StringSliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(stringSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]string) - return nil -} - -// Implements proto.MultiBulkParse -func stringSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - ss := make([]string, 0, n) - for i := int64(0); i < n; i++ { - switch s, err := rd.ReadString(); { - case err == Nil: - ss = append(ss, "") - case err != nil: - return nil, err - default: - ss = append(ss, s) - } - } - return ss, nil -} - -//------------------------------------------------------------------------------ - -type BoolSliceCmd struct { - baseCmd - - val []bool -} - -var _ Cmder = (*BoolSliceCmd)(nil) - -func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd { - return &BoolSliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *BoolSliceCmd) Val() []bool { - return cmd.val -} - -func (cmd *BoolSliceCmd) Result() ([]bool, error) { - return cmd.val, cmd.err -} - -func (cmd *BoolSliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *BoolSliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(boolSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]bool) - return nil -} - -// Implements proto.MultiBulkParse -func boolSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - bools := make([]bool, 0, n) - for i := int64(0); i < n; i++ { - n, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - bools = append(bools, n == 1) - } - return bools, nil -} - -//------------------------------------------------------------------------------ - -type StringStringMapCmd struct { - baseCmd - - val map[string]string -} - -var _ Cmder = (*StringStringMapCmd)(nil) - -func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd { - return &StringStringMapCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StringStringMapCmd) Val() map[string]string { - return cmd.val -} - -func (cmd *StringStringMapCmd) Result() (map[string]string, error) { - return cmd.val, cmd.err -} - -func (cmd *StringStringMapCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StringStringMapCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(stringStringMapParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(map[string]string) - return nil -} - -// Implements proto.MultiBulkParse -func stringStringMapParser(rd *proto.Reader, n int64) (interface{}, error) { - m := make(map[string]string, n/2) - for i := int64(0); i < n; i += 2 { - key, err := rd.ReadString() - if err != nil { - return nil, err - } - - value, err := rd.ReadString() - if err != nil { - return nil, err - } - - m[key] = value - } - return m, nil -} - -//------------------------------------------------------------------------------ - -type StringIntMapCmd struct { - baseCmd - - val map[string]int64 -} - -var _ Cmder = (*StringIntMapCmd)(nil) - -func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd { - return &StringIntMapCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StringIntMapCmd) Val() map[string]int64 { - return cmd.val -} - -func (cmd *StringIntMapCmd) Result() (map[string]int64, error) { - return cmd.val, cmd.err -} - -func (cmd *StringIntMapCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StringIntMapCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(stringIntMapParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(map[string]int64) - return nil -} - -// Implements proto.MultiBulkParse -func stringIntMapParser(rd *proto.Reader, n int64) (interface{}, error) { - m := make(map[string]int64, n/2) - for i := int64(0); i < n; i += 2 { - key, err := rd.ReadString() - if err != nil { - return nil, err - } - - n, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - - m[key] = n - } - return m, nil -} - -//------------------------------------------------------------------------------ - -type StringStructMapCmd struct { - baseCmd - - val map[string]struct{} -} - -var _ Cmder = (*StringStructMapCmd)(nil) - -func NewStringStructMapCmd(args ...interface{}) *StringStructMapCmd { - return &StringStructMapCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *StringStructMapCmd) Val() map[string]struct{} { - return cmd.val -} - -func (cmd *StringStructMapCmd) Result() (map[string]struct{}, error) { - return cmd.val, cmd.err -} - -func (cmd *StringStructMapCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *StringStructMapCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(stringStructMapParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(map[string]struct{}) - return nil -} - -// Implements proto.MultiBulkParse -func stringStructMapParser(rd *proto.Reader, n int64) (interface{}, error) { - m := make(map[string]struct{}, n) - for i := int64(0); i < n; i++ { - key, err := rd.ReadString() - if err != nil { - return nil, err - } - - m[key] = struct{}{} - } - return m, nil -} - -//------------------------------------------------------------------------------ - -type XMessage struct { - ID string - Values map[string]interface{} -} - -type XMessageSliceCmd struct { - baseCmd - - val []XMessage -} - -var _ Cmder = (*XMessageSliceCmd)(nil) - -func NewXMessageSliceCmd(args ...interface{}) *XMessageSliceCmd { - return &XMessageSliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *XMessageSliceCmd) Val() []XMessage { - return cmd.val -} - -func (cmd *XMessageSliceCmd) Result() ([]XMessage, error) { - return cmd.val, cmd.err -} - -func (cmd *XMessageSliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *XMessageSliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(xMessageSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]XMessage) - return nil -} - -// Implements proto.MultiBulkParse -func xMessageSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - msgs := make([]XMessage, 0, n) - for i := int64(0); i < n; i++ { - _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { - id, err := rd.ReadString() - if err != nil { - return nil, err - } - - var values map[string]interface{} - - v, err := rd.ReadArrayReply(stringInterfaceMapParser) - if err != nil { - if err != proto.Nil { - return nil, err - } - } else { - values = v.(map[string]interface{}) - } - - msgs = append(msgs, XMessage{ - ID: id, - Values: values, - }) - return nil, nil - }) - if err != nil { - return nil, err - } - } - return msgs, nil -} - -// Implements proto.MultiBulkParse -func stringInterfaceMapParser(rd *proto.Reader, n int64) (interface{}, error) { - m := make(map[string]interface{}, n/2) - for i := int64(0); i < n; i += 2 { - key, err := rd.ReadString() - if err != nil { - return nil, err - } - - value, err := rd.ReadString() - if err != nil { - return nil, err - } - - m[key] = value - } - return m, nil -} - -//------------------------------------------------------------------------------ - -type XStream struct { - Stream string - Messages []XMessage -} - -type XStreamSliceCmd struct { - baseCmd - - val []XStream -} - -var _ Cmder = (*XStreamSliceCmd)(nil) - -func NewXStreamSliceCmd(args ...interface{}) *XStreamSliceCmd { - return &XStreamSliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *XStreamSliceCmd) Val() []XStream { - return cmd.val -} - -func (cmd *XStreamSliceCmd) Result() ([]XStream, error) { - return cmd.val, cmd.err -} - -func (cmd *XStreamSliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *XStreamSliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(xStreamSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]XStream) - return nil -} - -// Implements proto.MultiBulkParse -func xStreamSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - ret := make([]XStream, 0, n) - for i := int64(0); i < n; i++ { - _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { - if n != 2 { - return nil, fmt.Errorf("got %d, wanted 2", n) - } - - stream, err := rd.ReadString() - if err != nil { - return nil, err - } - - v, err := rd.ReadArrayReply(xMessageSliceParser) - if err != nil { - return nil, err - } - - ret = append(ret, XStream{ - Stream: stream, - Messages: v.([]XMessage), - }) - return nil, nil - }) - if err != nil { - return nil, err - } - } - return ret, nil -} - -//------------------------------------------------------------------------------ - -type XPending struct { - Count int64 - Lower string - Higher string - Consumers map[string]int64 -} - -type XPendingCmd struct { - baseCmd - val *XPending -} - -var _ Cmder = (*XPendingCmd)(nil) - -func NewXPendingCmd(args ...interface{}) *XPendingCmd { - return &XPendingCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *XPendingCmd) Val() *XPending { - return cmd.val -} - -func (cmd *XPendingCmd) Result() (*XPending, error) { - return cmd.val, cmd.err -} - -func (cmd *XPendingCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *XPendingCmd) readReply(rd *proto.Reader) error { - var info interface{} - info, cmd.err = rd.ReadArrayReply(xPendingParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = info.(*XPending) - return nil -} - -func xPendingParser(rd *proto.Reader, n int64) (interface{}, error) { - if n != 4 { - return nil, fmt.Errorf("got %d, wanted 4", n) - } - - count, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - - lower, err := rd.ReadString() - if err != nil && err != Nil { - return nil, err - } - - higher, err := rd.ReadString() - if err != nil && err != Nil { - return nil, err - } - - pending := &XPending{ - Count: count, - Lower: lower, - Higher: higher, - } - _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { - for i := int64(0); i < n; i++ { - _, err = rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { - if n != 2 { - return nil, fmt.Errorf("got %d, wanted 2", n) - } - - consumerName, err := rd.ReadString() - if err != nil { - return nil, err - } - - consumerPending, err := rd.ReadInt() - if err != nil { - return nil, err - } - - if pending.Consumers == nil { - pending.Consumers = make(map[string]int64) - } - pending.Consumers[consumerName] = consumerPending - - return nil, nil - }) - if err != nil { - return nil, err - } - } - return nil, nil - }) - if err != nil && err != Nil { - return nil, err - } - - return pending, nil -} - -//------------------------------------------------------------------------------ - -type XPendingExt struct { - Id string - Consumer string - Idle time.Duration - RetryCount int64 -} - -type XPendingExtCmd struct { - baseCmd - val []XPendingExt -} - -var _ Cmder = (*XPendingExtCmd)(nil) - -func NewXPendingExtCmd(args ...interface{}) *XPendingExtCmd { - return &XPendingExtCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *XPendingExtCmd) Val() []XPendingExt { - return cmd.val -} - -func (cmd *XPendingExtCmd) Result() ([]XPendingExt, error) { - return cmd.val, cmd.err -} - -func (cmd *XPendingExtCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error { - var info interface{} - info, cmd.err = rd.ReadArrayReply(xPendingExtSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = info.([]XPendingExt) - return nil -} - -func xPendingExtSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - ret := make([]XPendingExt, 0, n) - for i := int64(0); i < n; i++ { - _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { - if n != 4 { - return nil, fmt.Errorf("got %d, wanted 4", n) - } - - id, err := rd.ReadString() - if err != nil { - return nil, err - } - - consumer, err := rd.ReadString() - if err != nil && err != Nil { - return nil, err - } - - idle, err := rd.ReadIntReply() - if err != nil && err != Nil { - return nil, err - } - - retryCount, err := rd.ReadIntReply() - if err != nil && err != Nil { - return nil, err - } - - ret = append(ret, XPendingExt{ - Id: id, - Consumer: consumer, - Idle: time.Duration(idle) * time.Millisecond, - RetryCount: retryCount, - }) - return nil, nil - }) - if err != nil { - return nil, err - } - } - return ret, nil -} - -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ - -type ZSliceCmd struct { - baseCmd - - val []Z -} - -var _ Cmder = (*ZSliceCmd)(nil) - -func NewZSliceCmd(args ...interface{}) *ZSliceCmd { - return &ZSliceCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *ZSliceCmd) Val() []Z { - return cmd.val -} - -func (cmd *ZSliceCmd) Result() ([]Z, error) { - return cmd.val, cmd.err -} - -func (cmd *ZSliceCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(zSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]Z) - return nil -} - -// Implements proto.MultiBulkParse -func zSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - zz := make([]Z, n/2) - for i := int64(0); i < n; i += 2 { - var err error - - z := &zz[i/2] - - z.Member, err = rd.ReadString() - if err != nil { - return nil, err - } - - z.Score, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - } - return zz, nil -} - -//------------------------------------------------------------------------------ - -type ZWithKeyCmd struct { - baseCmd - - val ZWithKey -} - -var _ Cmder = (*ZWithKeyCmd)(nil) - -func NewZWithKeyCmd(args ...interface{}) *ZWithKeyCmd { - return &ZWithKeyCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *ZWithKeyCmd) Val() ZWithKey { - return cmd.val -} - -func (cmd *ZWithKeyCmd) Result() (ZWithKey, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *ZWithKeyCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *ZWithKeyCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(zWithKeyParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(ZWithKey) - return nil -} - -// Implements proto.MultiBulkParse -func zWithKeyParser(rd *proto.Reader, n int64) (interface{}, error) { - if n != 3 { - return nil, fmt.Errorf("got %d elements, expected 3", n) - } - - var z ZWithKey - var err error - - z.Key, err = rd.ReadString() - if err != nil { - return nil, err - } - z.Member, err = rd.ReadString() - if err != nil { - return nil, err - } - z.Score, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - return z, nil -} - -//------------------------------------------------------------------------------ - -type ScanCmd struct { - baseCmd - - page []string - cursor uint64 - - process func(cmd Cmder) error -} - -var _ Cmder = (*ScanCmd)(nil) - -func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd { - return &ScanCmd{ - baseCmd: baseCmd{_args: args}, - process: process, - } -} - -func (cmd *ScanCmd) Val() (keys []string, cursor uint64) { - return cmd.page, cmd.cursor -} - -func (cmd *ScanCmd) Result() (keys []string, cursor uint64, err error) { - return cmd.page, cmd.cursor, cmd.err -} - -func (cmd *ScanCmd) String() string { - return cmdString(cmd, cmd.page) -} - -func (cmd *ScanCmd) readReply(rd *proto.Reader) error { - cmd.page, cmd.cursor, cmd.err = rd.ReadScanReply() - return cmd.err -} - -// Iterator creates a new ScanIterator. -func (cmd *ScanCmd) Iterator() *ScanIterator { - return &ScanIterator{ - cmd: cmd, - } -} - -//------------------------------------------------------------------------------ - -type ClusterNode struct { - Id string - Addr string -} - -type ClusterSlot struct { - Start int - End int - Nodes []ClusterNode -} - -type ClusterSlotsCmd struct { - baseCmd - - val []ClusterSlot -} - -var _ Cmder = (*ClusterSlotsCmd)(nil) - -func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd { - return &ClusterSlotsCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *ClusterSlotsCmd) Val() []ClusterSlot { - return cmd.val -} - -func (cmd *ClusterSlotsCmd) Result() ([]ClusterSlot, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *ClusterSlotsCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *ClusterSlotsCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(clusterSlotsParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.([]ClusterSlot) - return nil -} - -// Implements proto.MultiBulkParse -func clusterSlotsParser(rd *proto.Reader, n int64) (interface{}, error) { - slots := make([]ClusterSlot, n) - for i := 0; i < len(slots); i++ { - n, err := rd.ReadArrayLen() - if err != nil { - return nil, err - } - if n < 2 { - err := fmt.Errorf("redis: got %d elements in cluster info, expected at least 2", n) - return nil, err - } - - start, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - - end, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - - nodes := make([]ClusterNode, n-2) - for j := 0; j < len(nodes); j++ { - n, err := rd.ReadArrayLen() - if err != nil { - return nil, err - } - if n != 2 && n != 3 { - err := fmt.Errorf("got %d elements in cluster info address, expected 2 or 3", n) - return nil, err - } - - ip, err := rd.ReadString() - if err != nil { - return nil, err - } - - port, err := rd.ReadString() - if err != nil { - return nil, err - } - - nodes[j].Addr = net.JoinHostPort(ip, port) - - if n == 3 { - id, err := rd.ReadString() - if err != nil { - return nil, err - } - nodes[j].Id = id - } - } - - slots[i] = ClusterSlot{ - Start: int(start), - End: int(end), - Nodes: nodes, - } - } - return slots, nil -} - -//------------------------------------------------------------------------------ - -// GeoLocation is used with GeoAdd to add geospatial location. -type GeoLocation struct { - Name string - Longitude, Latitude, Dist float64 - GeoHash int64 -} - -// GeoRadiusQuery is used with GeoRadius to query geospatial index. -type GeoRadiusQuery struct { - Radius float64 - // Can be m, km, ft, or mi. Default is km. - Unit string - WithCoord bool - WithDist bool - WithGeoHash bool - Count int - // Can be ASC or DESC. Default is no sort order. - Sort string - Store string - StoreDist string -} - -type GeoLocationCmd struct { - baseCmd - - q *GeoRadiusQuery - locations []GeoLocation -} - -var _ Cmder = (*GeoLocationCmd)(nil) - -func NewGeoLocationCmd(q *GeoRadiusQuery, args ...interface{}) *GeoLocationCmd { - args = append(args, q.Radius) - if q.Unit != "" { - args = append(args, q.Unit) - } else { - args = append(args, "km") - } - if q.WithCoord { - args = append(args, "withcoord") - } - if q.WithDist { - args = append(args, "withdist") - } - if q.WithGeoHash { - args = append(args, "withhash") - } - if q.Count > 0 { - args = append(args, "count", q.Count) - } - if q.Sort != "" { - args = append(args, q.Sort) - } - if q.Store != "" { - args = append(args, "store") - args = append(args, q.Store) - } - if q.StoreDist != "" { - args = append(args, "storedist") - args = append(args, q.StoreDist) - } - return &GeoLocationCmd{ - baseCmd: baseCmd{_args: args}, - q: q, - } -} - -func (cmd *GeoLocationCmd) Val() []GeoLocation { - return cmd.locations -} - -func (cmd *GeoLocationCmd) Result() ([]GeoLocation, error) { - return cmd.locations, cmd.err -} - -func (cmd *GeoLocationCmd) String() string { - return cmdString(cmd, cmd.locations) -} - -func (cmd *GeoLocationCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(newGeoLocationSliceParser(cmd.q)) - if cmd.err != nil { - return cmd.err - } - cmd.locations = v.([]GeoLocation) - return nil -} - -func newGeoLocationParser(q *GeoRadiusQuery) proto.MultiBulkParse { - return func(rd *proto.Reader, n int64) (interface{}, error) { - var loc GeoLocation - var err error - - loc.Name, err = rd.ReadString() - if err != nil { - return nil, err - } - if q.WithDist { - loc.Dist, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - } - if q.WithGeoHash { - loc.GeoHash, err = rd.ReadIntReply() - if err != nil { - return nil, err - } - } - if q.WithCoord { - n, err := rd.ReadArrayLen() - if err != nil { - return nil, err - } - if n != 2 { - return nil, fmt.Errorf("got %d coordinates, expected 2", n) - } - - loc.Longitude, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - loc.Latitude, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - } - - return &loc, nil - } -} - -func newGeoLocationSliceParser(q *GeoRadiusQuery) proto.MultiBulkParse { - return func(rd *proto.Reader, n int64) (interface{}, error) { - locs := make([]GeoLocation, 0, n) - for i := int64(0); i < n; i++ { - v, err := rd.ReadReply(newGeoLocationParser(q)) - if err != nil { - return nil, err - } - switch vv := v.(type) { - case string: - locs = append(locs, GeoLocation{ - Name: vv, - }) - case *GeoLocation: - locs = append(locs, *vv) - default: - return nil, fmt.Errorf("got %T, expected string or *GeoLocation", v) - } - } - return locs, nil - } -} - -//------------------------------------------------------------------------------ - -type GeoPos struct { - Longitude, Latitude float64 -} - -type GeoPosCmd struct { - baseCmd - - positions []*GeoPos -} - -var _ Cmder = (*GeoPosCmd)(nil) - -func NewGeoPosCmd(args ...interface{}) *GeoPosCmd { - return &GeoPosCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *GeoPosCmd) Val() []*GeoPos { - return cmd.positions -} - -func (cmd *GeoPosCmd) Result() ([]*GeoPos, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *GeoPosCmd) String() string { - return cmdString(cmd, cmd.positions) -} - -func (cmd *GeoPosCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(geoPosSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.positions = v.([]*GeoPos) - return nil -} - -func geoPosSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - positions := make([]*GeoPos, 0, n) - for i := int64(0); i < n; i++ { - v, err := rd.ReadReply(geoPosParser) - if err != nil { - if err == Nil { - positions = append(positions, nil) - continue - } - return nil, err - } - switch v := v.(type) { - case *GeoPos: - positions = append(positions, v) - default: - return nil, fmt.Errorf("got %T, expected *GeoPos", v) - } - } - return positions, nil -} - -func geoPosParser(rd *proto.Reader, n int64) (interface{}, error) { - var pos GeoPos - var err error - - pos.Longitude, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - - pos.Latitude, err = rd.ReadFloatReply() - if err != nil { - return nil, err - } - - return &pos, nil -} - -//------------------------------------------------------------------------------ - -type CommandInfo struct { - Name string - Arity int8 - Flags []string - FirstKeyPos int8 - LastKeyPos int8 - StepCount int8 - ReadOnly bool -} - -type CommandsInfoCmd struct { - baseCmd - - val map[string]*CommandInfo -} - -var _ Cmder = (*CommandsInfoCmd)(nil) - -func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd { - return &CommandsInfoCmd{ - baseCmd: baseCmd{_args: args}, - } -} - -func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo { - return cmd.val -} - -func (cmd *CommandsInfoCmd) Result() (map[string]*CommandInfo, error) { - return cmd.Val(), cmd.Err() -} - -func (cmd *CommandsInfoCmd) String() string { - return cmdString(cmd, cmd.val) -} - -func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error { - var v interface{} - v, cmd.err = rd.ReadArrayReply(commandInfoSliceParser) - if cmd.err != nil { - return cmd.err - } - cmd.val = v.(map[string]*CommandInfo) - return nil -} - -// Implements proto.MultiBulkParse -func commandInfoSliceParser(rd *proto.Reader, n int64) (interface{}, error) { - m := make(map[string]*CommandInfo, n) - for i := int64(0); i < n; i++ { - v, err := rd.ReadReply(commandInfoParser) - if err != nil { - return nil, err - } - vv := v.(*CommandInfo) - m[vv.Name] = vv - - } - return m, nil -} - -func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) { - var cmd CommandInfo - var err error - - if n != 6 { - return nil, fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6", n) - } - - cmd.Name, err = rd.ReadString() - if err != nil { - return nil, err - } - - arity, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - cmd.Arity = int8(arity) - - flags, err := rd.ReadReply(stringSliceParser) - if err != nil { - return nil, err - } - cmd.Flags = flags.([]string) - - firstKeyPos, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - cmd.FirstKeyPos = int8(firstKeyPos) - - lastKeyPos, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - cmd.LastKeyPos = int8(lastKeyPos) - - stepCount, err := rd.ReadIntReply() - if err != nil { - return nil, err - } - cmd.StepCount = int8(stepCount) - - for _, flag := range cmd.Flags { - if flag == "readonly" { - cmd.ReadOnly = true - break - } - } - - return &cmd, nil -} - -//------------------------------------------------------------------------------ - -type cmdsInfoCache struct { - fn func() (map[string]*CommandInfo, error) - - once internal.Once - cmds map[string]*CommandInfo -} - -func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache { - return &cmdsInfoCache{ - fn: fn, - } -} - -func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) { - err := c.once.Do(func() error { - cmds, err := c.fn() - if err != nil { - return err - } - c.cmds = cmds - return nil - }) - return c.cmds, err -} diff --git a/vendor/github.com/go-redis/redis/commands.go b/vendor/github.com/go-redis/redis/commands.go deleted file mode 100644 index 653e4abe96..0000000000 --- a/vendor/github.com/go-redis/redis/commands.go +++ /dev/null @@ -1,2583 +0,0 @@ -package redis - -import ( - "errors" - "io" - "time" - - "github.com/go-redis/redis/internal" -) - -func usePrecise(dur time.Duration) bool { - return dur < time.Second || dur%time.Second != 0 -} - -func formatMs(dur time.Duration) int64 { - if dur > 0 && dur < time.Millisecond { - internal.Logf( - "specified duration is %s, but minimal supported value is %s", - dur, time.Millisecond, - ) - } - return int64(dur / time.Millisecond) -} - -func formatSec(dur time.Duration) int64 { - if dur > 0 && dur < time.Second { - internal.Logf( - "specified duration is %s, but minimal supported value is %s", - dur, time.Second, - ) - } - return int64(dur / time.Second) -} - -func appendArgs(dst, src []interface{}) []interface{} { - if len(src) == 1 { - if ss, ok := src[0].([]string); ok { - for _, s := range ss { - dst = append(dst, s) - } - return dst - } - } - - for _, v := range src { - dst = append(dst, v) - } - return dst -} - -type Cmdable interface { - Pipeline() Pipeliner - Pipelined(fn func(Pipeliner) error) ([]Cmder, error) - - TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) - TxPipeline() Pipeliner - - Command() *CommandsInfoCmd - ClientGetName() *StringCmd - Echo(message interface{}) *StringCmd - Ping() *StatusCmd - Quit() *StatusCmd - Del(keys ...string) *IntCmd - Unlink(keys ...string) *IntCmd - Dump(key string) *StringCmd - Exists(keys ...string) *IntCmd - Expire(key string, expiration time.Duration) *BoolCmd - ExpireAt(key string, tm time.Time) *BoolCmd - Keys(pattern string) *StringSliceCmd - Migrate(host, port, key string, db int64, timeout time.Duration) *StatusCmd - Move(key string, db int64) *BoolCmd - ObjectRefCount(key string) *IntCmd - ObjectEncoding(key string) *StringCmd - ObjectIdleTime(key string) *DurationCmd - Persist(key string) *BoolCmd - PExpire(key string, expiration time.Duration) *BoolCmd - PExpireAt(key string, tm time.Time) *BoolCmd - PTTL(key string) *DurationCmd - RandomKey() *StringCmd - Rename(key, newkey string) *StatusCmd - RenameNX(key, newkey string) *BoolCmd - Restore(key string, ttl time.Duration, value string) *StatusCmd - RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd - Sort(key string, sort *Sort) *StringSliceCmd - SortStore(key, store string, sort *Sort) *IntCmd - SortInterfaces(key string, sort *Sort) *SliceCmd - Touch(keys ...string) *IntCmd - TTL(key string) *DurationCmd - Type(key string) *StatusCmd - Scan(cursor uint64, match string, count int64) *ScanCmd - SScan(key string, cursor uint64, match string, count int64) *ScanCmd - HScan(key string, cursor uint64, match string, count int64) *ScanCmd - ZScan(key string, cursor uint64, match string, count int64) *ScanCmd - Append(key, value string) *IntCmd - BitCount(key string, bitCount *BitCount) *IntCmd - BitOpAnd(destKey string, keys ...string) *IntCmd - BitOpOr(destKey string, keys ...string) *IntCmd - BitOpXor(destKey string, keys ...string) *IntCmd - BitOpNot(destKey string, key string) *IntCmd - BitPos(key string, bit int64, pos ...int64) *IntCmd - Decr(key string) *IntCmd - DecrBy(key string, decrement int64) *IntCmd - Get(key string) *StringCmd - GetBit(key string, offset int64) *IntCmd - GetRange(key string, start, end int64) *StringCmd - GetSet(key string, value interface{}) *StringCmd - Incr(key string) *IntCmd - IncrBy(key string, value int64) *IntCmd - IncrByFloat(key string, value float64) *FloatCmd - MGet(keys ...string) *SliceCmd - MSet(pairs ...interface{}) *StatusCmd - MSetNX(pairs ...interface{}) *BoolCmd - Set(key string, value interface{}, expiration time.Duration) *StatusCmd - SetBit(key string, offset int64, value int) *IntCmd - SetNX(key string, value interface{}, expiration time.Duration) *BoolCmd - SetXX(key string, value interface{}, expiration time.Duration) *BoolCmd - SetRange(key string, offset int64, value string) *IntCmd - StrLen(key string) *IntCmd - HDel(key string, fields ...string) *IntCmd - HExists(key, field string) *BoolCmd - HGet(key, field string) *StringCmd - HGetAll(key string) *StringStringMapCmd - HIncrBy(key, field string, incr int64) *IntCmd - HIncrByFloat(key, field string, incr float64) *FloatCmd - HKeys(key string) *StringSliceCmd - HLen(key string) *IntCmd - HMGet(key string, fields ...string) *SliceCmd - HMSet(key string, fields map[string]interface{}) *StatusCmd - HSet(key, field string, value interface{}) *BoolCmd - HSetNX(key, field string, value interface{}) *BoolCmd - HVals(key string) *StringSliceCmd - BLPop(timeout time.Duration, keys ...string) *StringSliceCmd - BRPop(timeout time.Duration, keys ...string) *StringSliceCmd - BRPopLPush(source, destination string, timeout time.Duration) *StringCmd - LIndex(key string, index int64) *StringCmd - LInsert(key, op string, pivot, value interface{}) *IntCmd - LInsertBefore(key string, pivot, value interface{}) *IntCmd - LInsertAfter(key string, pivot, value interface{}) *IntCmd - LLen(key string) *IntCmd - LPop(key string) *StringCmd - LPush(key string, values ...interface{}) *IntCmd - LPushX(key string, value interface{}) *IntCmd - LRange(key string, start, stop int64) *StringSliceCmd - LRem(key string, count int64, value interface{}) *IntCmd - LSet(key string, index int64, value interface{}) *StatusCmd - LTrim(key string, start, stop int64) *StatusCmd - RPop(key string) *StringCmd - RPopLPush(source, destination string) *StringCmd - RPush(key string, values ...interface{}) *IntCmd - RPushX(key string, value interface{}) *IntCmd - SAdd(key string, members ...interface{}) *IntCmd - SCard(key string) *IntCmd - SDiff(keys ...string) *StringSliceCmd - SDiffStore(destination string, keys ...string) *IntCmd - SInter(keys ...string) *StringSliceCmd - SInterStore(destination string, keys ...string) *IntCmd - SIsMember(key string, member interface{}) *BoolCmd - SMembers(key string) *StringSliceCmd - SMembersMap(key string) *StringStructMapCmd - SMove(source, destination string, member interface{}) *BoolCmd - SPop(key string) *StringCmd - SPopN(key string, count int64) *StringSliceCmd - SRandMember(key string) *StringCmd - SRandMemberN(key string, count int64) *StringSliceCmd - SRem(key string, members ...interface{}) *IntCmd - SUnion(keys ...string) *StringSliceCmd - SUnionStore(destination string, keys ...string) *IntCmd - XAdd(a *XAddArgs) *StringCmd - XDel(stream string, ids ...string) *IntCmd - XLen(stream string) *IntCmd - XRange(stream, start, stop string) *XMessageSliceCmd - XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd - XRevRange(stream string, start, stop string) *XMessageSliceCmd - XRevRangeN(stream string, start, stop string, count int64) *XMessageSliceCmd - XRead(a *XReadArgs) *XStreamSliceCmd - XReadStreams(streams ...string) *XStreamSliceCmd - XGroupCreate(stream, group, start string) *StatusCmd - XGroupCreateMkStream(stream, group, start string) *StatusCmd - XGroupSetID(stream, group, start string) *StatusCmd - XGroupDestroy(stream, group string) *IntCmd - XGroupDelConsumer(stream, group, consumer string) *IntCmd - XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd - XAck(stream, group string, ids ...string) *IntCmd - XPending(stream, group string) *XPendingCmd - XPendingExt(a *XPendingExtArgs) *XPendingExtCmd - XClaim(a *XClaimArgs) *XMessageSliceCmd - XClaimJustID(a *XClaimArgs) *StringSliceCmd - XTrim(key string, maxLen int64) *IntCmd - XTrimApprox(key string, maxLen int64) *IntCmd - BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd - BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd - ZAdd(key string, members ...Z) *IntCmd - ZAddNX(key string, members ...Z) *IntCmd - ZAddXX(key string, members ...Z) *IntCmd - ZAddCh(key string, members ...Z) *IntCmd - ZAddNXCh(key string, members ...Z) *IntCmd - ZAddXXCh(key string, members ...Z) *IntCmd - ZIncr(key string, member Z) *FloatCmd - ZIncrNX(key string, member Z) *FloatCmd - ZIncrXX(key string, member Z) *FloatCmd - ZCard(key string) *IntCmd - ZCount(key, min, max string) *IntCmd - ZLexCount(key, min, max string) *IntCmd - ZIncrBy(key string, increment float64, member string) *FloatCmd - ZInterStore(destination string, store ZStore, keys ...string) *IntCmd - ZPopMax(key string, count ...int64) *ZSliceCmd - ZPopMin(key string, count ...int64) *ZSliceCmd - ZRange(key string, start, stop int64) *StringSliceCmd - ZRangeWithScores(key string, start, stop int64) *ZSliceCmd - ZRangeByScore(key string, opt ZRangeBy) *StringSliceCmd - ZRangeByLex(key string, opt ZRangeBy) *StringSliceCmd - ZRangeByScoreWithScores(key string, opt ZRangeBy) *ZSliceCmd - ZRank(key, member string) *IntCmd - ZRem(key string, members ...interface{}) *IntCmd - ZRemRangeByRank(key string, start, stop int64) *IntCmd - ZRemRangeByScore(key, min, max string) *IntCmd - ZRemRangeByLex(key, min, max string) *IntCmd - ZRevRange(key string, start, stop int64) *StringSliceCmd - ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd - ZRevRangeByScore(key string, opt ZRangeBy) *StringSliceCmd - ZRevRangeByLex(key string, opt ZRangeBy) *StringSliceCmd - ZRevRangeByScoreWithScores(key string, opt ZRangeBy) *ZSliceCmd - ZRevRank(key, member string) *IntCmd - ZScore(key, member string) *FloatCmd - ZUnionStore(dest string, store ZStore, keys ...string) *IntCmd - PFAdd(key string, els ...interface{}) *IntCmd - PFCount(keys ...string) *IntCmd - PFMerge(dest string, keys ...string) *StatusCmd - BgRewriteAOF() *StatusCmd - BgSave() *StatusCmd - ClientKill(ipPort string) *StatusCmd - ClientKillByFilter(keys ...string) *IntCmd - ClientList() *StringCmd - ClientPause(dur time.Duration) *BoolCmd - ClientID() *IntCmd - ConfigGet(parameter string) *SliceCmd - ConfigResetStat() *StatusCmd - ConfigSet(parameter, value string) *StatusCmd - ConfigRewrite() *StatusCmd - DBSize() *IntCmd - FlushAll() *StatusCmd - FlushAllAsync() *StatusCmd - FlushDB() *StatusCmd - FlushDBAsync() *StatusCmd - Info(section ...string) *StringCmd - LastSave() *IntCmd - Save() *StatusCmd - Shutdown() *StatusCmd - ShutdownSave() *StatusCmd - ShutdownNoSave() *StatusCmd - SlaveOf(host, port string) *StatusCmd - Time() *TimeCmd - Eval(script string, keys []string, args ...interface{}) *Cmd - EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(hashes ...string) *BoolSliceCmd - ScriptFlush() *StatusCmd - ScriptKill() *StatusCmd - ScriptLoad(script string) *StringCmd - DebugObject(key string) *StringCmd - Publish(channel string, message interface{}) *IntCmd - PubSubChannels(pattern string) *StringSliceCmd - PubSubNumSub(channels ...string) *StringIntMapCmd - PubSubNumPat() *IntCmd - ClusterSlots() *ClusterSlotsCmd - ClusterNodes() *StringCmd - ClusterMeet(host, port string) *StatusCmd - ClusterForget(nodeID string) *StatusCmd - ClusterReplicate(nodeID string) *StatusCmd - ClusterResetSoft() *StatusCmd - ClusterResetHard() *StatusCmd - ClusterInfo() *StringCmd - ClusterKeySlot(key string) *IntCmd - ClusterGetKeysInSlot(slot int, count int) *StringSliceCmd - ClusterCountFailureReports(nodeID string) *IntCmd - ClusterCountKeysInSlot(slot int) *IntCmd - ClusterDelSlots(slots ...int) *StatusCmd - ClusterDelSlotsRange(min, max int) *StatusCmd - ClusterSaveConfig() *StatusCmd - ClusterSlaves(nodeID string) *StringSliceCmd - ClusterFailover() *StatusCmd - ClusterAddSlots(slots ...int) *StatusCmd - ClusterAddSlotsRange(min, max int) *StatusCmd - GeoAdd(key string, geoLocation ...*GeoLocation) *IntCmd - GeoPos(key string, members ...string) *GeoPosCmd - GeoRadius(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd - GeoRadiusRO(key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd - GeoRadiusByMember(key, member string, query *GeoRadiusQuery) *GeoLocationCmd - GeoRadiusByMemberRO(key, member string, query *GeoRadiusQuery) *GeoLocationCmd - GeoDist(key string, member1, member2, unit string) *FloatCmd - GeoHash(key string, members ...string) *StringSliceCmd - ReadOnly() *StatusCmd - ReadWrite() *StatusCmd - MemoryUsage(key string, samples ...int) *IntCmd -} - -type StatefulCmdable interface { - Cmdable - Auth(password string) *StatusCmd - Select(index int) *StatusCmd - SwapDB(index1, index2 int) *StatusCmd - ClientSetName(name string) *BoolCmd -} - -var _ Cmdable = (*Client)(nil) -var _ Cmdable = (*Tx)(nil) -var _ Cmdable = (*Ring)(nil) -var _ Cmdable = (*ClusterClient)(nil) - -type cmdable struct { - process func(cmd Cmder) error -} - -func (c *cmdable) setProcessor(fn func(Cmder) error) { - c.process = fn -} - -type statefulCmdable struct { - cmdable - process func(cmd Cmder) error -} - -func (c *statefulCmdable) setProcessor(fn func(Cmder) error) { - c.process = fn - c.cmdable.setProcessor(fn) -} - -//------------------------------------------------------------------------------ - -func (c *statefulCmdable) Auth(password string) *StatusCmd { - cmd := NewStatusCmd("auth", password) - c.process(cmd) - return cmd -} - -func (c *cmdable) Echo(message interface{}) *StringCmd { - cmd := NewStringCmd("echo", message) - c.process(cmd) - return cmd -} - -func (c *cmdable) Ping() *StatusCmd { - cmd := NewStatusCmd("ping") - c.process(cmd) - return cmd -} - -func (c *cmdable) Wait(numSlaves int, timeout time.Duration) *IntCmd { - cmd := NewIntCmd("wait", numSlaves, int(timeout/time.Millisecond)) - c.process(cmd) - return cmd -} - -func (c *cmdable) Quit() *StatusCmd { - panic("not implemented") -} - -func (c *statefulCmdable) Select(index int) *StatusCmd { - cmd := NewStatusCmd("select", index) - c.process(cmd) - return cmd -} - -func (c *statefulCmdable) SwapDB(index1, index2 int) *StatusCmd { - cmd := NewStatusCmd("swapdb", index1, index2) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) Command() *CommandsInfoCmd { - cmd := NewCommandsInfoCmd("command") - c.process(cmd) - return cmd -} - -func (c *cmdable) Del(keys ...string) *IntCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "del" - for i, key := range keys { - args[1+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) Unlink(keys ...string) *IntCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "unlink" - for i, key := range keys { - args[1+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) Dump(key string) *StringCmd { - cmd := NewStringCmd("dump", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) Exists(keys ...string) *IntCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "exists" - for i, key := range keys { - args[1+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) Expire(key string, expiration time.Duration) *BoolCmd { - cmd := NewBoolCmd("expire", key, formatSec(expiration)) - c.process(cmd) - return cmd -} - -func (c *cmdable) ExpireAt(key string, tm time.Time) *BoolCmd { - cmd := NewBoolCmd("expireat", key, tm.Unix()) - c.process(cmd) - return cmd -} - -func (c *cmdable) Keys(pattern string) *StringSliceCmd { - cmd := NewStringSliceCmd("keys", pattern) - c.process(cmd) - return cmd -} - -func (c *cmdable) Migrate(host, port, key string, db int64, timeout time.Duration) *StatusCmd { - cmd := NewStatusCmd( - "migrate", - host, - port, - key, - db, - formatMs(timeout), - ) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -func (c *cmdable) Move(key string, db int64) *BoolCmd { - cmd := NewBoolCmd("move", key, db) - c.process(cmd) - return cmd -} - -func (c *cmdable) ObjectRefCount(key string) *IntCmd { - cmd := NewIntCmd("object", "refcount", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) ObjectEncoding(key string) *StringCmd { - cmd := NewStringCmd("object", "encoding", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) ObjectIdleTime(key string) *DurationCmd { - cmd := NewDurationCmd(time.Second, "object", "idletime", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) Persist(key string) *BoolCmd { - cmd := NewBoolCmd("persist", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) PExpire(key string, expiration time.Duration) *BoolCmd { - cmd := NewBoolCmd("pexpire", key, formatMs(expiration)) - c.process(cmd) - return cmd -} - -func (c *cmdable) PExpireAt(key string, tm time.Time) *BoolCmd { - cmd := NewBoolCmd( - "pexpireat", - key, - tm.UnixNano()/int64(time.Millisecond), - ) - c.process(cmd) - return cmd -} - -func (c *cmdable) PTTL(key string) *DurationCmd { - cmd := NewDurationCmd(time.Millisecond, "pttl", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) RandomKey() *StringCmd { - cmd := NewStringCmd("randomkey") - c.process(cmd) - return cmd -} - -func (c *cmdable) Rename(key, newkey string) *StatusCmd { - cmd := NewStatusCmd("rename", key, newkey) - c.process(cmd) - return cmd -} - -func (c *cmdable) RenameNX(key, newkey string) *BoolCmd { - cmd := NewBoolCmd("renamenx", key, newkey) - c.process(cmd) - return cmd -} - -func (c *cmdable) Restore(key string, ttl time.Duration, value string) *StatusCmd { - cmd := NewStatusCmd( - "restore", - key, - formatMs(ttl), - value, - ) - c.process(cmd) - return cmd -} - -func (c *cmdable) RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd { - cmd := NewStatusCmd( - "restore", - key, - formatMs(ttl), - value, - "replace", - ) - c.process(cmd) - return cmd -} - -type Sort struct { - By string - Offset, Count int64 - Get []string - Order string - Alpha bool -} - -func (sort *Sort) args(key string) []interface{} { - args := []interface{}{"sort", key} - if sort.By != "" { - args = append(args, "by", sort.By) - } - if sort.Offset != 0 || sort.Count != 0 { - args = append(args, "limit", sort.Offset, sort.Count) - } - for _, get := range sort.Get { - args = append(args, "get", get) - } - if sort.Order != "" { - args = append(args, sort.Order) - } - if sort.Alpha { - args = append(args, "alpha") - } - return args -} - -func (c *cmdable) Sort(key string, sort *Sort) *StringSliceCmd { - cmd := NewStringSliceCmd(sort.args(key)...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SortStore(key, store string, sort *Sort) *IntCmd { - args := sort.args(key) - if store != "" { - args = append(args, "store", store) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SortInterfaces(key string, sort *Sort) *SliceCmd { - cmd := NewSliceCmd(sort.args(key)...) - c.process(cmd) - return cmd -} - -func (c *cmdable) Touch(keys ...string) *IntCmd { - args := make([]interface{}, len(keys)+1) - args[0] = "touch" - for i, key := range keys { - args[i+1] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) TTL(key string) *DurationCmd { - cmd := NewDurationCmd(time.Second, "ttl", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) Type(key string) *StatusCmd { - cmd := NewStatusCmd("type", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) Scan(cursor uint64, match string, count int64) *ScanCmd { - args := []interface{}{"scan", cursor} - if match != "" { - args = append(args, "match", match) - } - if count > 0 { - args = append(args, "count", count) - } - cmd := NewScanCmd(c.process, args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SScan(key string, cursor uint64, match string, count int64) *ScanCmd { - args := []interface{}{"sscan", key, cursor} - if match != "" { - args = append(args, "match", match) - } - if count > 0 { - args = append(args, "count", count) - } - cmd := NewScanCmd(c.process, args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) HScan(key string, cursor uint64, match string, count int64) *ScanCmd { - args := []interface{}{"hscan", key, cursor} - if match != "" { - args = append(args, "match", match) - } - if count > 0 { - args = append(args, "count", count) - } - cmd := NewScanCmd(c.process, args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZScan(key string, cursor uint64, match string, count int64) *ScanCmd { - args := []interface{}{"zscan", key, cursor} - if match != "" { - args = append(args, "match", match) - } - if count > 0 { - args = append(args, "count", count) - } - cmd := NewScanCmd(c.process, args...) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) Append(key, value string) *IntCmd { - cmd := NewIntCmd("append", key, value) - c.process(cmd) - return cmd -} - -type BitCount struct { - Start, End int64 -} - -func (c *cmdable) BitCount(key string, bitCount *BitCount) *IntCmd { - args := []interface{}{"bitcount", key} - if bitCount != nil { - args = append( - args, - bitCount.Start, - bitCount.End, - ) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) bitOp(op, destKey string, keys ...string) *IntCmd { - args := make([]interface{}, 3+len(keys)) - args[0] = "bitop" - args[1] = op - args[2] = destKey - for i, key := range keys { - args[3+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) BitOpAnd(destKey string, keys ...string) *IntCmd { - return c.bitOp("and", destKey, keys...) -} - -func (c *cmdable) BitOpOr(destKey string, keys ...string) *IntCmd { - return c.bitOp("or", destKey, keys...) -} - -func (c *cmdable) BitOpXor(destKey string, keys ...string) *IntCmd { - return c.bitOp("xor", destKey, keys...) -} - -func (c *cmdable) BitOpNot(destKey string, key string) *IntCmd { - return c.bitOp("not", destKey, key) -} - -func (c *cmdable) BitPos(key string, bit int64, pos ...int64) *IntCmd { - args := make([]interface{}, 3+len(pos)) - args[0] = "bitpos" - args[1] = key - args[2] = bit - switch len(pos) { - case 0: - case 1: - args[3] = pos[0] - case 2: - args[3] = pos[0] - args[4] = pos[1] - default: - panic("too many arguments") - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) Decr(key string) *IntCmd { - cmd := NewIntCmd("decr", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) DecrBy(key string, decrement int64) *IntCmd { - cmd := NewIntCmd("decrby", key, decrement) - c.process(cmd) - return cmd -} - -// Redis `GET key` command. It returns redis.Nil error when key does not exist. -func (c *cmdable) Get(key string) *StringCmd { - cmd := NewStringCmd("get", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) GetBit(key string, offset int64) *IntCmd { - cmd := NewIntCmd("getbit", key, offset) - c.process(cmd) - return cmd -} - -func (c *cmdable) GetRange(key string, start, end int64) *StringCmd { - cmd := NewStringCmd("getrange", key, start, end) - c.process(cmd) - return cmd -} - -func (c *cmdable) GetSet(key string, value interface{}) *StringCmd { - cmd := NewStringCmd("getset", key, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) Incr(key string) *IntCmd { - cmd := NewIntCmd("incr", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) IncrBy(key string, value int64) *IntCmd { - cmd := NewIntCmd("incrby", key, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) IncrByFloat(key string, value float64) *FloatCmd { - cmd := NewFloatCmd("incrbyfloat", key, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) MGet(keys ...string) *SliceCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "mget" - for i, key := range keys { - args[1+i] = key - } - cmd := NewSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) MSet(pairs ...interface{}) *StatusCmd { - args := make([]interface{}, 1, 1+len(pairs)) - args[0] = "mset" - args = appendArgs(args, pairs) - cmd := NewStatusCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) MSetNX(pairs ...interface{}) *BoolCmd { - args := make([]interface{}, 1, 1+len(pairs)) - args[0] = "msetnx" - args = appendArgs(args, pairs) - cmd := NewBoolCmd(args...) - c.process(cmd) - return cmd -} - -// Redis `SET key value [expiration]` command. -// -// Use expiration for `SETEX`-like behavior. -// Zero expiration means the key has no expiration time. -func (c *cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd { - args := make([]interface{}, 3, 4) - args[0] = "set" - args[1] = key - args[2] = value - if expiration > 0 { - if usePrecise(expiration) { - args = append(args, "px", formatMs(expiration)) - } else { - args = append(args, "ex", formatSec(expiration)) - } - } - cmd := NewStatusCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SetBit(key string, offset int64, value int) *IntCmd { - cmd := NewIntCmd( - "setbit", - key, - offset, - value, - ) - c.process(cmd) - return cmd -} - -// Redis `SET key value [expiration] NX` command. -// -// Zero expiration means the key has no expiration time. -func (c *cmdable) SetNX(key string, value interface{}, expiration time.Duration) *BoolCmd { - var cmd *BoolCmd - if expiration == 0 { - // Use old `SETNX` to support old Redis versions. - cmd = NewBoolCmd("setnx", key, value) - } else { - if usePrecise(expiration) { - cmd = NewBoolCmd("set", key, value, "px", formatMs(expiration), "nx") - } else { - cmd = NewBoolCmd("set", key, value, "ex", formatSec(expiration), "nx") - } - } - c.process(cmd) - return cmd -} - -// Redis `SET key value [expiration] XX` command. -// -// Zero expiration means the key has no expiration time. -func (c *cmdable) SetXX(key string, value interface{}, expiration time.Duration) *BoolCmd { - var cmd *BoolCmd - if expiration == 0 { - cmd = NewBoolCmd("set", key, value, "xx") - } else { - if usePrecise(expiration) { - cmd = NewBoolCmd("set", key, value, "px", formatMs(expiration), "xx") - } else { - cmd = NewBoolCmd("set", key, value, "ex", formatSec(expiration), "xx") - } - } - c.process(cmd) - return cmd -} - -func (c *cmdable) SetRange(key string, offset int64, value string) *IntCmd { - cmd := NewIntCmd("setrange", key, offset, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) StrLen(key string) *IntCmd { - cmd := NewIntCmd("strlen", key) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) HDel(key string, fields ...string) *IntCmd { - args := make([]interface{}, 2+len(fields)) - args[0] = "hdel" - args[1] = key - for i, field := range fields { - args[2+i] = field - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) HExists(key, field string) *BoolCmd { - cmd := NewBoolCmd("hexists", key, field) - c.process(cmd) - return cmd -} - -func (c *cmdable) HGet(key, field string) *StringCmd { - cmd := NewStringCmd("hget", key, field) - c.process(cmd) - return cmd -} - -func (c *cmdable) HGetAll(key string) *StringStringMapCmd { - cmd := NewStringStringMapCmd("hgetall", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) HIncrBy(key, field string, incr int64) *IntCmd { - cmd := NewIntCmd("hincrby", key, field, incr) - c.process(cmd) - return cmd -} - -func (c *cmdable) HIncrByFloat(key, field string, incr float64) *FloatCmd { - cmd := NewFloatCmd("hincrbyfloat", key, field, incr) - c.process(cmd) - return cmd -} - -func (c *cmdable) HKeys(key string) *StringSliceCmd { - cmd := NewStringSliceCmd("hkeys", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) HLen(key string) *IntCmd { - cmd := NewIntCmd("hlen", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) HMGet(key string, fields ...string) *SliceCmd { - args := make([]interface{}, 2+len(fields)) - args[0] = "hmget" - args[1] = key - for i, field := range fields { - args[2+i] = field - } - cmd := NewSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) HMSet(key string, fields map[string]interface{}) *StatusCmd { - args := make([]interface{}, 2+len(fields)*2) - args[0] = "hmset" - args[1] = key - i := 2 - for k, v := range fields { - args[i] = k - args[i+1] = v - i += 2 - } - cmd := NewStatusCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) HSet(key, field string, value interface{}) *BoolCmd { - cmd := NewBoolCmd("hset", key, field, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) HSetNX(key, field string, value interface{}) *BoolCmd { - cmd := NewBoolCmd("hsetnx", key, field, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) HVals(key string) *StringSliceCmd { - cmd := NewStringSliceCmd("hvals", key) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) BLPop(timeout time.Duration, keys ...string) *StringSliceCmd { - args := make([]interface{}, 1+len(keys)+1) - args[0] = "blpop" - for i, key := range keys { - args[1+i] = key - } - args[len(args)-1] = formatSec(timeout) - cmd := NewStringSliceCmd(args...) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -func (c *cmdable) BRPop(timeout time.Duration, keys ...string) *StringSliceCmd { - args := make([]interface{}, 1+len(keys)+1) - args[0] = "brpop" - for i, key := range keys { - args[1+i] = key - } - args[len(keys)+1] = formatSec(timeout) - cmd := NewStringSliceCmd(args...) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -func (c *cmdable) BRPopLPush(source, destination string, timeout time.Duration) *StringCmd { - cmd := NewStringCmd( - "brpoplpush", - source, - destination, - formatSec(timeout), - ) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -func (c *cmdable) LIndex(key string, index int64) *StringCmd { - cmd := NewStringCmd("lindex", key, index) - c.process(cmd) - return cmd -} - -func (c *cmdable) LInsert(key, op string, pivot, value interface{}) *IntCmd { - cmd := NewIntCmd("linsert", key, op, pivot, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LInsertBefore(key string, pivot, value interface{}) *IntCmd { - cmd := NewIntCmd("linsert", key, "before", pivot, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LInsertAfter(key string, pivot, value interface{}) *IntCmd { - cmd := NewIntCmd("linsert", key, "after", pivot, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LLen(key string) *IntCmd { - cmd := NewIntCmd("llen", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) LPop(key string) *StringCmd { - cmd := NewStringCmd("lpop", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) LPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(values)) - args[0] = "lpush" - args[1] = key - args = appendArgs(args, values) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) LPushX(key string, value interface{}) *IntCmd { - cmd := NewIntCmd("lpushx", key, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LRange(key string, start, stop int64) *StringSliceCmd { - cmd := NewStringSliceCmd( - "lrange", - key, - start, - stop, - ) - c.process(cmd) - return cmd -} - -func (c *cmdable) LRem(key string, count int64, value interface{}) *IntCmd { - cmd := NewIntCmd("lrem", key, count, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LSet(key string, index int64, value interface{}) *StatusCmd { - cmd := NewStatusCmd("lset", key, index, value) - c.process(cmd) - return cmd -} - -func (c *cmdable) LTrim(key string, start, stop int64) *StatusCmd { - cmd := NewStatusCmd( - "ltrim", - key, - start, - stop, - ) - c.process(cmd) - return cmd -} - -func (c *cmdable) RPop(key string) *StringCmd { - cmd := NewStringCmd("rpop", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) RPopLPush(source, destination string) *StringCmd { - cmd := NewStringCmd("rpoplpush", source, destination) - c.process(cmd) - return cmd -} - -func (c *cmdable) RPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(values)) - args[0] = "rpush" - args[1] = key - args = appendArgs(args, values) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) RPushX(key string, value interface{}) *IntCmd { - cmd := NewIntCmd("rpushx", key, value) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) SAdd(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(members)) - args[0] = "sadd" - args[1] = key - args = appendArgs(args, members) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SCard(key string) *IntCmd { - cmd := NewIntCmd("scard", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) SDiff(keys ...string) *StringSliceCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "sdiff" - for i, key := range keys { - args[1+i] = key - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SDiffStore(destination string, keys ...string) *IntCmd { - args := make([]interface{}, 2+len(keys)) - args[0] = "sdiffstore" - args[1] = destination - for i, key := range keys { - args[2+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SInter(keys ...string) *StringSliceCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "sinter" - for i, key := range keys { - args[1+i] = key - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SInterStore(destination string, keys ...string) *IntCmd { - args := make([]interface{}, 2+len(keys)) - args[0] = "sinterstore" - args[1] = destination - for i, key := range keys { - args[2+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SIsMember(key string, member interface{}) *BoolCmd { - cmd := NewBoolCmd("sismember", key, member) - c.process(cmd) - return cmd -} - -// Redis `SMEMBERS key` command output as a slice -func (c *cmdable) SMembers(key string) *StringSliceCmd { - cmd := NewStringSliceCmd("smembers", key) - c.process(cmd) - return cmd -} - -// Redis `SMEMBERS key` command output as a map -func (c *cmdable) SMembersMap(key string) *StringStructMapCmd { - cmd := NewStringStructMapCmd("smembers", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) SMove(source, destination string, member interface{}) *BoolCmd { - cmd := NewBoolCmd("smove", source, destination, member) - c.process(cmd) - return cmd -} - -// Redis `SPOP key` command. -func (c *cmdable) SPop(key string) *StringCmd { - cmd := NewStringCmd("spop", key) - c.process(cmd) - return cmd -} - -// Redis `SPOP key count` command. -func (c *cmdable) SPopN(key string, count int64) *StringSliceCmd { - cmd := NewStringSliceCmd("spop", key, count) - c.process(cmd) - return cmd -} - -// Redis `SRANDMEMBER key` command. -func (c *cmdable) SRandMember(key string) *StringCmd { - cmd := NewStringCmd("srandmember", key) - c.process(cmd) - return cmd -} - -// Redis `SRANDMEMBER key count` command. -func (c *cmdable) SRandMemberN(key string, count int64) *StringSliceCmd { - cmd := NewStringSliceCmd("srandmember", key, count) - c.process(cmd) - return cmd -} - -func (c *cmdable) SRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(members)) - args[0] = "srem" - args[1] = key - args = appendArgs(args, members) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SUnion(keys ...string) *StringSliceCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "sunion" - for i, key := range keys { - args[1+i] = key - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) SUnionStore(destination string, keys ...string) *IntCmd { - args := make([]interface{}, 2+len(keys)) - args[0] = "sunionstore" - args[1] = destination - for i, key := range keys { - args[2+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -type XAddArgs struct { - Stream string - MaxLen int64 // MAXLEN N - MaxLenApprox int64 // MAXLEN ~ N - ID string - Values map[string]interface{} -} - -func (c *cmdable) XAdd(a *XAddArgs) *StringCmd { - args := make([]interface{}, 0, 6+len(a.Values)*2) - args = append(args, "xadd") - args = append(args, a.Stream) - if a.MaxLen > 0 { - args = append(args, "maxlen", a.MaxLen) - } else if a.MaxLenApprox > 0 { - args = append(args, "maxlen", "~", a.MaxLenApprox) - } - if a.ID != "" { - args = append(args, a.ID) - } else { - args = append(args, "*") - } - for k, v := range a.Values { - args = append(args, k) - args = append(args, v) - } - - cmd := NewStringCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) XDel(stream string, ids ...string) *IntCmd { - args := []interface{}{"xdel", stream} - for _, id := range ids { - args = append(args, id) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) XLen(stream string) *IntCmd { - cmd := NewIntCmd("xlen", stream) - c.process(cmd) - return cmd -} - -func (c *cmdable) XRange(stream, start, stop string) *XMessageSliceCmd { - cmd := NewXMessageSliceCmd("xrange", stream, start, stop) - c.process(cmd) - return cmd -} - -func (c *cmdable) XRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { - cmd := NewXMessageSliceCmd("xrange", stream, start, stop, "count", count) - c.process(cmd) - return cmd -} - -func (c *cmdable) XRevRange(stream, start, stop string) *XMessageSliceCmd { - cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop) - c.process(cmd) - return cmd -} - -func (c *cmdable) XRevRangeN(stream, start, stop string, count int64) *XMessageSliceCmd { - cmd := NewXMessageSliceCmd("xrevrange", stream, start, stop, "count", count) - c.process(cmd) - return cmd -} - -type XReadArgs struct { - Streams []string - Count int64 - Block time.Duration -} - -func (c *cmdable) XRead(a *XReadArgs) *XStreamSliceCmd { - args := make([]interface{}, 0, 5+len(a.Streams)) - args = append(args, "xread") - if a.Count > 0 { - args = append(args, "count") - args = append(args, a.Count) - } - if a.Block >= 0 { - args = append(args, "block") - args = append(args, int64(a.Block/time.Millisecond)) - } - args = append(args, "streams") - for _, s := range a.Streams { - args = append(args, s) - } - - cmd := NewXStreamSliceCmd(args...) - if a.Block >= 0 { - cmd.setReadTimeout(a.Block) - } - c.process(cmd) - return cmd -} - -func (c *cmdable) XReadStreams(streams ...string) *XStreamSliceCmd { - return c.XRead(&XReadArgs{ - Streams: streams, - Block: -1, - }) -} - -func (c *cmdable) XGroupCreate(stream, group, start string) *StatusCmd { - cmd := NewStatusCmd("xgroup", "create", stream, group, start) - c.process(cmd) - return cmd -} - -func (c *cmdable) XGroupCreateMkStream(stream, group, start string) *StatusCmd { - cmd := NewStatusCmd("xgroup", "create", stream, group, start, "mkstream") - c.process(cmd) - return cmd -} - -func (c *cmdable) XGroupSetID(stream, group, start string) *StatusCmd { - cmd := NewStatusCmd("xgroup", "setid", stream, group, start) - c.process(cmd) - return cmd -} - -func (c *cmdable) XGroupDestroy(stream, group string) *IntCmd { - cmd := NewIntCmd("xgroup", "destroy", stream, group) - c.process(cmd) - return cmd -} - -func (c *cmdable) XGroupDelConsumer(stream, group, consumer string) *IntCmd { - cmd := NewIntCmd("xgroup", "delconsumer", stream, group, consumer) - c.process(cmd) - return cmd -} - -type XReadGroupArgs struct { - Group string - Consumer string - // List of streams and ids. - Streams []string - Count int64 - Block time.Duration - NoAck bool -} - -func (c *cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd { - args := make([]interface{}, 0, 8+len(a.Streams)) - args = append(args, "xreadgroup", "group", a.Group, a.Consumer) - if a.Count > 0 { - args = append(args, "count", a.Count) - } - if a.Block >= 0 { - args = append(args, "block", int64(a.Block/time.Millisecond)) - } - if a.NoAck { - args = append(args, "noack") - } - args = append(args, "streams") - for _, s := range a.Streams { - args = append(args, s) - } - - cmd := NewXStreamSliceCmd(args...) - if a.Block >= 0 { - cmd.setReadTimeout(a.Block) - } - c.process(cmd) - return cmd -} - -func (c *cmdable) XAck(stream, group string, ids ...string) *IntCmd { - args := []interface{}{"xack", stream, group} - for _, id := range ids { - args = append(args, id) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) XPending(stream, group string) *XPendingCmd { - cmd := NewXPendingCmd("xpending", stream, group) - c.process(cmd) - return cmd -} - -type XPendingExtArgs struct { - Stream string - Group string - Start string - End string - Count int64 - Consumer string -} - -func (c *cmdable) XPendingExt(a *XPendingExtArgs) *XPendingExtCmd { - args := make([]interface{}, 0, 7) - args = append(args, "xpending", a.Stream, a.Group, a.Start, a.End, a.Count) - if a.Consumer != "" { - args = append(args, a.Consumer) - } - cmd := NewXPendingExtCmd(args...) - c.process(cmd) - return cmd -} - -type XClaimArgs struct { - Stream string - Group string - Consumer string - MinIdle time.Duration - Messages []string -} - -func (c *cmdable) XClaim(a *XClaimArgs) *XMessageSliceCmd { - args := xClaimArgs(a) - cmd := NewXMessageSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) XClaimJustID(a *XClaimArgs) *StringSliceCmd { - args := xClaimArgs(a) - args = append(args, "justid") - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func xClaimArgs(a *XClaimArgs) []interface{} { - args := make([]interface{}, 0, 4+len(a.Messages)) - args = append(args, - "xclaim", - a.Stream, - a.Group, a.Consumer, - int64(a.MinIdle/time.Millisecond)) - for _, id := range a.Messages { - args = append(args, id) - } - return args -} - -func (c *cmdable) XTrim(key string, maxLen int64) *IntCmd { - cmd := NewIntCmd("xtrim", key, "maxlen", maxLen) - c.process(cmd) - return cmd -} - -func (c *cmdable) XTrimApprox(key string, maxLen int64) *IntCmd { - cmd := NewIntCmd("xtrim", key, "maxlen", "~", maxLen) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -// Z represents sorted set member. -type Z struct { - Score float64 - Member interface{} -} - -// ZWithKey represents sorted set member including the name of the key where it was popped. -type ZWithKey struct { - Z - Key string -} - -// ZStore is used as an arg to ZInterStore and ZUnionStore. -type ZStore struct { - Weights []float64 - // Can be SUM, MIN or MAX. - Aggregate string -} - -// Redis `BZPOPMAX key [key ...] timeout` command. -func (c *cmdable) BZPopMax(timeout time.Duration, keys ...string) *ZWithKeyCmd { - args := make([]interface{}, 1+len(keys)+1) - args[0] = "bzpopmax" - for i, key := range keys { - args[1+i] = key - } - args[len(args)-1] = formatSec(timeout) - cmd := NewZWithKeyCmd(args...) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -// Redis `BZPOPMIN key [key ...] timeout` command. -func (c *cmdable) BZPopMin(timeout time.Duration, keys ...string) *ZWithKeyCmd { - args := make([]interface{}, 1+len(keys)+1) - args[0] = "bzpopmin" - for i, key := range keys { - args[1+i] = key - } - args[len(args)-1] = formatSec(timeout) - cmd := NewZWithKeyCmd(args...) - cmd.setReadTimeout(timeout) - c.process(cmd) - return cmd -} - -func (c *cmdable) zAdd(a []interface{}, n int, members ...Z) *IntCmd { - for i, m := range members { - a[n+2*i] = m.Score - a[n+2*i+1] = m.Member - } - cmd := NewIntCmd(a...) - c.process(cmd) - return cmd -} - -// Redis `ZADD key score member [score member ...]` command. -func (c *cmdable) ZAdd(key string, members ...Z) *IntCmd { - const n = 2 - a := make([]interface{}, n+2*len(members)) - a[0], a[1] = "zadd", key - return c.zAdd(a, n, members...) -} - -// Redis `ZADD key NX score member [score member ...]` command. -func (c *cmdable) ZAddNX(key string, members ...Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "nx" - return c.zAdd(a, n, members...) -} - -// Redis `ZADD key XX score member [score member ...]` command. -func (c *cmdable) ZAddXX(key string, members ...Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "xx" - return c.zAdd(a, n, members...) -} - -// Redis `ZADD key CH score member [score member ...]` command. -func (c *cmdable) ZAddCh(key string, members ...Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "ch" - return c.zAdd(a, n, members...) -} - -// Redis `ZADD key NX CH score member [score member ...]` command. -func (c *cmdable) ZAddNXCh(key string, members ...Z) *IntCmd { - const n = 4 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2], a[3] = "zadd", key, "nx", "ch" - return c.zAdd(a, n, members...) -} - -// Redis `ZADD key XX CH score member [score member ...]` command. -func (c *cmdable) ZAddXXCh(key string, members ...Z) *IntCmd { - const n = 4 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2], a[3] = "zadd", key, "xx", "ch" - return c.zAdd(a, n, members...) -} - -func (c *cmdable) zIncr(a []interface{}, n int, members ...Z) *FloatCmd { - for i, m := range members { - a[n+2*i] = m.Score - a[n+2*i+1] = m.Member - } - cmd := NewFloatCmd(a...) - c.process(cmd) - return cmd -} - -// Redis `ZADD key INCR score member` command. -func (c *cmdable) ZIncr(key string, member Z) *FloatCmd { - const n = 3 - a := make([]interface{}, n+2) - a[0], a[1], a[2] = "zadd", key, "incr" - return c.zIncr(a, n, member) -} - -// Redis `ZADD key NX INCR score member` command. -func (c *cmdable) ZIncrNX(key string, member Z) *FloatCmd { - const n = 4 - a := make([]interface{}, n+2) - a[0], a[1], a[2], a[3] = "zadd", key, "incr", "nx" - return c.zIncr(a, n, member) -} - -// Redis `ZADD key XX INCR score member` command. -func (c *cmdable) ZIncrXX(key string, member Z) *FloatCmd { - const n = 4 - a := make([]interface{}, n+2) - a[0], a[1], a[2], a[3] = "zadd", key, "incr", "xx" - return c.zIncr(a, n, member) -} - -func (c *cmdable) ZCard(key string) *IntCmd { - cmd := NewIntCmd("zcard", key) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZCount(key, min, max string) *IntCmd { - cmd := NewIntCmd("zcount", key, min, max) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZLexCount(key, min, max string) *IntCmd { - cmd := NewIntCmd("zlexcount", key, min, max) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZIncrBy(key string, increment float64, member string) *FloatCmd { - cmd := NewFloatCmd("zincrby", key, increment, member) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZInterStore(destination string, store ZStore, keys ...string) *IntCmd { - args := make([]interface{}, 3+len(keys)) - args[0] = "zinterstore" - args[1] = destination - args[2] = len(keys) - for i, key := range keys { - args[3+i] = key - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weight := range store.Weights { - args = append(args, weight) - } - } - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZPopMax(key string, count ...int64) *ZSliceCmd { - args := []interface{}{ - "zpopmax", - key, - } - - switch len(count) { - case 0: - break - case 1: - args = append(args, count[0]) - default: - panic("too many arguments") - } - - cmd := NewZSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZPopMin(key string, count ...int64) *ZSliceCmd { - args := []interface{}{ - "zpopmin", - key, - } - - switch len(count) { - case 0: - break - case 1: - args = append(args, count[0]) - default: - panic("too many arguments") - } - - cmd := NewZSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) zRange(key string, start, stop int64, withScores bool) *StringSliceCmd { - args := []interface{}{ - "zrange", - key, - start, - stop, - } - if withScores { - args = append(args, "withscores") - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRange(key string, start, stop int64) *StringSliceCmd { - return c.zRange(key, start, stop, false) -} - -func (c *cmdable) ZRangeWithScores(key string, start, stop int64) *ZSliceCmd { - cmd := NewZSliceCmd("zrange", key, start, stop, "withscores") - c.process(cmd) - return cmd -} - -type ZRangeBy struct { - Min, Max string - Offset, Count int64 -} - -func (c *cmdable) zRangeBy(zcmd, key string, opt ZRangeBy, withScores bool) *StringSliceCmd { - args := []interface{}{zcmd, key, opt.Min, opt.Max} - if withScores { - args = append(args, "withscores") - } - if opt.Offset != 0 || opt.Count != 0 { - args = append( - args, - "limit", - opt.Offset, - opt.Count, - ) - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRangeByScore(key string, opt ZRangeBy) *StringSliceCmd { - return c.zRangeBy("zrangebyscore", key, opt, false) -} - -func (c *cmdable) ZRangeByLex(key string, opt ZRangeBy) *StringSliceCmd { - return c.zRangeBy("zrangebylex", key, opt, false) -} - -func (c *cmdable) ZRangeByScoreWithScores(key string, opt ZRangeBy) *ZSliceCmd { - args := []interface{}{"zrangebyscore", key, opt.Min, opt.Max, "withscores"} - if opt.Offset != 0 || opt.Count != 0 { - args = append( - args, - "limit", - opt.Offset, - opt.Count, - ) - } - cmd := NewZSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRank(key, member string) *IntCmd { - cmd := NewIntCmd("zrank", key, member) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(members)) - args[0] = "zrem" - args[1] = key - args = appendArgs(args, members) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRemRangeByRank(key string, start, stop int64) *IntCmd { - cmd := NewIntCmd( - "zremrangebyrank", - key, - start, - stop, - ) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRemRangeByScore(key, min, max string) *IntCmd { - cmd := NewIntCmd("zremrangebyscore", key, min, max) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRemRangeByLex(key, min, max string) *IntCmd { - cmd := NewIntCmd("zremrangebylex", key, min, max) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRevRange(key string, start, stop int64) *StringSliceCmd { - cmd := NewStringSliceCmd("zrevrange", key, start, stop) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd { - cmd := NewZSliceCmd("zrevrange", key, start, stop, "withscores") - c.process(cmd) - return cmd -} - -func (c *cmdable) zRevRangeBy(zcmd, key string, opt ZRangeBy) *StringSliceCmd { - args := []interface{}{zcmd, key, opt.Max, opt.Min} - if opt.Offset != 0 || opt.Count != 0 { - args = append( - args, - "limit", - opt.Offset, - opt.Count, - ) - } - cmd := NewStringSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRevRangeByScore(key string, opt ZRangeBy) *StringSliceCmd { - return c.zRevRangeBy("zrevrangebyscore", key, opt) -} - -func (c *cmdable) ZRevRangeByLex(key string, opt ZRangeBy) *StringSliceCmd { - return c.zRevRangeBy("zrevrangebylex", key, opt) -} - -func (c *cmdable) ZRevRangeByScoreWithScores(key string, opt ZRangeBy) *ZSliceCmd { - args := []interface{}{"zrevrangebyscore", key, opt.Max, opt.Min, "withscores"} - if opt.Offset != 0 || opt.Count != 0 { - args = append( - args, - "limit", - opt.Offset, - opt.Count, - ) - } - cmd := NewZSliceCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZRevRank(key, member string) *IntCmd { - cmd := NewIntCmd("zrevrank", key, member) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZScore(key, member string) *FloatCmd { - cmd := NewFloatCmd("zscore", key, member) - c.process(cmd) - return cmd -} - -func (c *cmdable) ZUnionStore(dest string, store ZStore, keys ...string) *IntCmd { - args := make([]interface{}, 3+len(keys)) - args[0] = "zunionstore" - args[1] = dest - args[2] = len(keys) - for i, key := range keys { - args[3+i] = key - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weight := range store.Weights { - args = append(args, weight) - } - } - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) PFAdd(key string, els ...interface{}) *IntCmd { - args := make([]interface{}, 2, 2+len(els)) - args[0] = "pfadd" - args[1] = key - args = appendArgs(args, els) - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) PFCount(keys ...string) *IntCmd { - args := make([]interface{}, 1+len(keys)) - args[0] = "pfcount" - for i, key := range keys { - args[1+i] = key - } - cmd := NewIntCmd(args...) - c.process(cmd) - return cmd -} - -func (c *cmdable) PFMerge(dest string, keys ...string) *StatusCmd { - args := make([]interface{}, 2+len(keys)) - args[0] = "pfmerge" - args[1] = dest - for i, key := range keys { - args[2+i] = key - } - cmd := NewStatusCmd(args...) - c.process(cmd) - return cmd -} - -//------------------------------------------------------------------------------ - -func (c *cmdable) BgRewriteAOF() *StatusCmd { - cmd := NewStatusCmd("bgrewriteaof") - c.process(cmd) - return cmd -} - -func (c *cmdable) BgSave() *StatusCmd { - cmd := NewStatusCmd("bgsave") - c.process(cmd) - return cmd -} - -func (c *cmdable) ClientKill(ipPort string) *StatusCmd { - cmd := NewStatusCmd("client", "kill", ipPort) - c.process(cmd) - return cmd -} - -// ClientKillByFilter is new style synx, while the ClientKill is old -// CLIENT KILL