Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use context #13

Merged
merged 14 commits into from
Jun 23, 2023
86 changes: 49 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,92 @@

[![release](https://github.com/steviebps/realm/actions/workflows/go.yml/badge.svg)](https://github.com/steviebps/realm/actions/workflows/go.yml)

```go install github.com/steviebps/realm```


## starter configs

### a basic chamber file
```wget -O $HOME/.realm/masterChamber.json https://raw.githubusercontent.com/steviebps/realm/master/configs/masterChamber.json```

```bash
go install github.com/steviebps/realm
```

## example commands

### build
```realm build -o /path/to/your/directory```

with forced directory creation
### server

```realm build -o /path/to/your/directory --force```

### print

#### Pretty prints your global chamber to stdout:
```realm print -p```

#### Print your global chamber to file:
```realm print -o /path/to/your/file.json```
#### start a local realm server

```bash
realm server --config ./configs/realm.json
```

## example code snippets

```go
package main

import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"

"github.com/steviebps/realm/client"
realm "github.com/steviebps/realm/pkg"
)

type CustomStruct struct {
Foo string `json:"foo,omitempty"`
}

func main() {
// because realm configurations contain overrides based on the version of your application, specify it here
realm.SetVersion("v1.0.0")
var err error

// tell realm where to look for realm configuration
if err := realm.AddConfigPath("./"); err != nil {
// create a realm client for retrieving your chamber from your local or remote host
client, err := client.NewClient(&client.ClientConfig{Address: "http://localhost"})
if err != nil {
log.Fatal(err)
}

// tell realm what file name it should look for in the specified paths
if err := realm.SetConfigName("chambers.json"); err != nil {
// initialize your realm
rlm, err := realm.NewRealm(realm.RealmOptions{Client: client, ApplicationVersion: "v1.0.0", Path: "root"})
if err != nil {
log.Fatal(err)
}

// look for and read in the realm configuration
// passing "true" will tell realm to watch the file for changes
if err := realm.ReadInConfig(true); err != nil {
// start fetching your chamber from the local or remote host
err = rlm.Start()
if err != nil {
log.Fatal(err)
}

// return a float64 value from the config and specify a default value if it does not exist
port, _ := realm.Float64Value("port", 3000)

// create a realm context
bootCtx := rlm.NewContext(context.Background())
// retrieve your first config value
port, _ := rlm.Float64(bootCtx, "port", 3000)

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// retrieve a string value from your realm config and specify a default value if it does not exist
message, _ := realm.StringValue("message", "DEFAULT")
// retrieve the message value with a new context
// note: use the same context value throughout the request for consistency
message, _ := rlm.String(rlm.NewContext(r.Context()), "message", "DEFAULT")
w.Write([]byte(message))
})


mux.HandleFunc("/custom", func(w http.ResponseWriter, r *http.Request) {
var custom *CustomStruct
// retrieve a custom value and unmarshal it
if err := rlm.CustomValue(rlm.NewContext(r.Context()), "custom", &custom); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(custom)
})

log.Println("Listening on :", port)
err := http.ListenAndServe(fmt.Sprintf(":%d", int(port)), mux)
err = http.ListenAndServe(fmt.Sprintf(":%d", int(port)), mux)
if err != nil {
log.Fatal(err)
}
}
```


46 changes: 0 additions & 46 deletions cmd/print.go

This file was deleted.

4 changes: 0 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ import (

"github.com/hashicorp/go-hclog"
"github.com/spf13/cobra"

realm "github.com/steviebps/realm/pkg"
)

var globalChamber = realm.Chamber{Toggles: map[string]*realm.OverrideableToggle{}}

// Version the version of realm
var Version = "development"

Expand Down
2 changes: 1 addition & 1 deletion cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ var serverCmd = &cobra.Command{
logger.Error(fmt.Sprintf("storage type %q does not exist", storageType))
os.Exit(1)
}
stg, err := strgCreator(serverConfig.StorageOptions, logger)
stg, err := strgCreator(serverConfig.StorageOptions)
if err != nil {
logger.Error(err.Error())
os.Exit(1)
Expand Down
File renamed without changes.
7 changes: 5 additions & 2 deletions configs/realm.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"options": {
"path": "./.realm",
"cache": "bigcache",
"source": "file"
"source": "file",
"life_window": "",
"shards": "",
"clean_window": ""
}
}
}
}
9 changes: 5 additions & 4 deletions examples/go/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"encoding/json"
"fmt"
"log"
Expand Down Expand Up @@ -30,18 +31,18 @@ func main() {
log.Fatal(err)
}

port, _ := rlm.Float64("port", 3000)
bootCtx := rlm.NewContext(context.Background())
port, _ := rlm.Float64(bootCtx, "port", 3000)

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
message, _ := rlm.String("message", "DEFAULT")
message, _ := rlm.String(rlm.NewContext(r.Context()), "message", "DEFAULT")
w.Write([]byte(message))
})

mux.HandleFunc("/custom", func(w http.ResponseWriter, r *http.Request) {
var custom *CustomStruct

if err := rlm.CustomValue("custom", &custom); err != nil {
if err := rlm.CustomValue(rlm.NewContext(r.Context()), "custom", &custom); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ require (
require (
github.com/fatih/color v1.15.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
)

require (
github.com/hashicorp/go-hclog v1.5.0
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/sys v0.8.0 // indirect
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
Expand All @@ -39,8 +39,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
61 changes: 33 additions & 28 deletions pkg/chamber.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package realm

import (
"encoding/json"
"sync"
)

Expand Down Expand Up @@ -56,16 +55,6 @@ func NewChamberEntry(c *Chamber, version string) *ChamberEntry {
}
}

// GetToggleValue returns the toggle with the specified toggleName at the specified version.
// Will return nil if the toggle does not exist
func (c *ChamberEntry) GetToggleValue(toggleName string) interface{} {
t := c.Get(toggleName)
if t == nil {
return nil
}
return t.GetValueAt(c.version)
}

// Get returns the toggle with the specified toggleName.
// Will return nil if the toggle does not exist
func (c *ChamberEntry) Get(toggleName string) *OverrideableToggle {
Expand All @@ -79,40 +68,56 @@ func (c *ChamberEntry) Get(toggleName string) *OverrideableToggle {

// StringValue retrieves a string by the key of the toggle
// and returns the default value if it does not exist and a bool on whether or not the toggle exists
func (c *ChamberEntry) StringValue(toggleKey string, defaultValue string) (string, bool) {
cStr, ok := c.GetToggleValue(toggleKey).(string)
func (c *ChamberEntry) StringValue(toggleKey string, defaultValue string) (string, error) {
t := c.Get(toggleKey)
if t == nil {
return defaultValue, &ErrToggleNotFound{toggleKey}
}
v, ok := t.StringValue(c.version, defaultValue)
if !ok {
return defaultValue, ok
return defaultValue, &ErrCouldNotConvertToggle{toggleKey, t.Type}
}
return cStr, ok
return v, nil
}

// BoolValue retrieves a bool by the key of the toggle
// and returns the default value if it does not exist and a bool on whether or not the toggle exists
func (c *ChamberEntry) BoolValue(toggleKey string, defaultValue bool) (bool, bool) {
cBool, ok := c.GetToggleValue(toggleKey).(bool)
func (c *ChamberEntry) BoolValue(toggleKey string, defaultValue bool) (bool, error) {
t := c.Get(toggleKey)
if t == nil {
return defaultValue, &ErrToggleNotFound{toggleKey}
}
v, ok := t.BoolValue(c.version, defaultValue)
if !ok {
return defaultValue, ok
return defaultValue, &ErrCouldNotConvertToggle{toggleKey, t.Type}
}
return cBool, ok
return v, nil
}

// Float64Value retrieves a float64 by the key of the toggle
// and returns the default value if it does not exist and a bool on whether or not the toggle exists
func (c *ChamberEntry) Float64Value(toggleKey string, defaultValue float64) (float64, bool) {
cFloat64, ok := c.GetToggleValue(toggleKey).(float64)
func (c *ChamberEntry) Float64Value(toggleKey string, defaultValue float64) (float64, error) {
t := c.Get(toggleKey)
if t == nil {
return defaultValue, &ErrToggleNotFound{toggleKey}
}
v, ok := t.Float64Value(c.version, defaultValue)
if !ok {
return defaultValue, ok
return defaultValue, &ErrCouldNotConvertToggle{toggleKey, t.Type}
}
return cFloat64, ok
return v, nil
}

// CustomValue retrieves a json.RawMessage by the key of the toggle
// and returns a bool on whether or not the toggle exists and is the proper type
func (c *ChamberEntry) CustomValue(toggleKey string, version string) (*json.RawMessage, bool) {
t, ok := c.GetToggleValue(toggleKey).(*json.RawMessage)
if !ok {
return nil, ok
func (c *ChamberEntry) CustomValue(toggleKey string, v any) error {
t := c.Get(toggleKey)
if t == nil {
return &ErrToggleNotFound{toggleKey}
}
err := t.CustomValue(c.version, v)
if err != nil {
return &ErrCouldNotConvertToggle{toggleKey, t.Type}
}
return t, ok
return nil
}
Loading