Files
fn-serverless/api/models/config.go
Reed Allman 46dfbd362d mask models.Call blank fields in api, sqlx
sqlx has nice facilities for using structs to do queries and using their
fields, so decided to move us all over to this. now when you take a look at
models.Call it's really obvious what's in db and what's not. added omitempty
to some json fields that were bleeding through api too.

deletes a lot of code in the sql package for scanning and made some queries
use struct based sqlx methods now which seem easier to read than what we
previously had. moves all json stuff into sql.Valuer and sql.Scanner methods
in models/config.go, these are the only 2 types that ever need this. sadly,
sqlx would have done this marshaling for us, but to keep compat, I added json.
we can do some migrations later maybe for a more efficient encoding, but did
not want to fuss with it today.

it seems like we should probably aim to keep models.Call as small as possible
in the db as there will be a lot of them. interestingly, most functions
platforms I looked at do not seem to expose this kind of information that I
could find. so, i think only having timestamps, status, id, app, path and
maybe docker stats is really all that should be in here (agree w/ Denys on
284 as these and logs will end up taking up most db space in prod. notably,
payload, headers, and env vars could be extremely large and in the general
case they are always a copy of the routes (this breaks apart when routes are
updated, which would be useful considering we don't have versioning --
versioning may be cheaper).

removed unused field in apps too

this is lined up behind #349 so that I could use the tests...

closes #345
closes #142
closes #284
2017-09-21 03:18:24 -07:00

97 lines
1.8 KiB
Go

package models
import (
"bytes"
"database/sql/driver"
"encoding/json"
"fmt"
"net/http"
)
type Config map[string]string
func (c *Config) Validate() error {
return nil
}
// implements sql.Valuer, returning a string
func (c Config) Value() (driver.Value, error) {
if len(c) < 1 {
return driver.Value(string("")), nil
}
var b bytes.Buffer
err := json.NewEncoder(&b).Encode(c)
// return a string type
return driver.Value(b.String()), err
}
// implements sql.Scanner
func (c *Config) Scan(value interface{}) error {
if value == nil {
*c = nil
return nil
}
bv, err := driver.String.ConvertValue(value)
if err == nil {
var b []byte
switch x := bv.(type) {
case []byte:
b = x
case string:
b = []byte(x)
}
if len(b) > 0 {
return json.Unmarshal(b, c)
} else {
*c = nil
return nil
}
}
// otherwise, return an error
return fmt.Errorf("config invalid db format: %T %T value, err: %v", value, bv, err)
}
// Headers is an http.Header that implements additional methods.
type Headers http.Header
// implements sql.Valuer, returning a string
func (h Headers) Value() (driver.Value, error) {
if len(h) < 1 {
return driver.Value(string("")), nil
}
var b bytes.Buffer
err := json.NewEncoder(&b).Encode(h)
// return a string type
return driver.Value(b.String()), err
}
// implements sql.Scanner
func (h *Headers) Scan(value interface{}) error {
if value == nil {
*h = nil
return nil
}
bv, err := driver.String.ConvertValue(value)
if err == nil {
var b []byte
switch x := bv.(type) {
case []byte:
b = x
case string:
b = []byte(x)
}
if len(b) > 0 {
return json.Unmarshal(b, h)
} else {
*h = nil
return nil
}
}
// otherwise, return an error
return fmt.Errorf("headers invalid db format: %T %T value, err: %v", value, bv, err)
}