mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-10 04:47:53 +00:00
variety of cleanup in api and handler
don't export QueryValidationSpecRequired add docs to some methods simplify /debug/vars handling using expvar.Handler() implement Version in API and simplify
This commit is contained in:
parent
dd5b38f4ef
commit
07ca6d57ad
2 changed files with 35 additions and 39 deletions
22
api.go
22
api.go
|
|
@ -31,6 +31,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// API provides the top level programmatic interface to Pilosa. It is usually
|
||||
// wrapped by a handler which provides an external interface (e.g. HTTP).
|
||||
type API struct {
|
||||
Holder *Holder
|
||||
// The execution engine for running queries.
|
||||
|
|
@ -46,6 +48,7 @@ type API struct {
|
|||
Logger Logger
|
||||
}
|
||||
|
||||
// NewAPI returns a new API instance.
|
||||
func NewAPI() *API {
|
||||
return &API{
|
||||
Broadcaster: NopBroadcaster,
|
||||
|
|
@ -55,7 +58,8 @@ func NewAPI() *API {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *API) ExecuteQuery(ctx context.Context, req *QueryRequest) (QueryResponse, error) {
|
||||
// ExecuteQuery parses a PQL query out of the request and executes it.
|
||||
func (api *API) ExecuteQuery(ctx context.Context, req *QueryRequest) (QueryResponse, error) {
|
||||
resp := QueryResponse{}
|
||||
|
||||
q, err := pql.NewParser(strings.NewReader(req.Query)).Parse()
|
||||
|
|
@ -67,7 +71,7 @@ func (a *API) ExecuteQuery(ctx context.Context, req *QueryRequest) (QueryRespons
|
|||
ExcludeAttrs: req.ExcludeAttrs,
|
||||
ExcludeBits: req.ExcludeBits,
|
||||
}
|
||||
results, err := a.Executor.Execute(ctx, req.Index, q, req.Slices, execOpts)
|
||||
results, err := api.Executor.Execute(ctx, req.Index, q, req.Slices, execOpts)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
|
@ -86,7 +90,7 @@ func (a *API) ExecuteQuery(ctx context.Context, req *QueryRequest) (QueryRespons
|
|||
}
|
||||
|
||||
// Retrieve column attributes across all calls.
|
||||
columnAttrSets, err := a.readColumnAttrSets(a.Holder.Index(req.Index), columnIDs)
|
||||
columnAttrSets, err := api.readColumnAttrSets(api.Holder.Index(req.Index), columnIDs)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
|
@ -118,6 +122,7 @@ func (api *API) readColumnAttrSets(index *Index, ids []uint64) ([]*ColumnAttrSet
|
|||
return ax, nil
|
||||
}
|
||||
|
||||
// CreateIndex makes a new Pilosa index.
|
||||
func (api *API) CreateIndex(ctx context.Context, indexName string, options IndexOptions) (*Index, error) {
|
||||
// Create index.
|
||||
index, err := api.Holder.CreateIndex(indexName, options)
|
||||
|
|
@ -845,6 +850,7 @@ func (api *API) inputJSONDataParser(req map[string]interface{}, index *Index, na
|
|||
return setBits, nil
|
||||
}
|
||||
|
||||
// SetCoordinator makes a new Node the cluster coordinator.
|
||||
func (api *API) SetCoordinator(ctx context.Context, id string) (oldNode, newNode *Node, err error) {
|
||||
oldNode = api.Cluster.nodeByID(api.Cluster.Coordinator)
|
||||
newNode = api.Cluster.nodeByID(id)
|
||||
|
|
@ -869,6 +875,8 @@ func (api *API) SetCoordinator(ctx context.Context, id string) (oldNode, newNode
|
|||
return oldNode, newNode, nil
|
||||
}
|
||||
|
||||
// RemoveNode puts the cluster into the "RESIZING" state and begins the job of
|
||||
// removing the given node.
|
||||
func (api *API) RemoveNode(id string) (*Node, error) {
|
||||
removeNode := api.Cluster.nodeByID(id)
|
||||
if removeNode == nil {
|
||||
|
|
@ -891,6 +899,14 @@ func (api *API) ResizeAbort() error {
|
|||
return errors.Wrap(err, "complete current job")
|
||||
}
|
||||
|
||||
// State returns the cluster state which is usually "NORMAL", but could be
|
||||
// "STARTING", "RESIZING", or potentially others. See cluster.go for more
|
||||
// details.
|
||||
func (api *API) State() string {
|
||||
return api.Cluster.State()
|
||||
}
|
||||
|
||||
// Version returns the Pilosa version.
|
||||
func (api *API) Version() string {
|
||||
return strings.TrimPrefix(Version, "v")
|
||||
}
|
||||
|
|
|
|||
52
handler.go
52
handler.go
|
|
@ -108,14 +108,14 @@ func BuildRouters(handler *Handler) {
|
|||
|
||||
func (h *Handler) populateValidators() {
|
||||
h.validators = map[string]*queryValidationSpec{}
|
||||
h.validators["GetFragmentNodes"] = QueryValidationSpecRequired("slice").Optional("index")
|
||||
h.validators["GetSliceMax"] = QueryValidationSpecRequired().Optional("inverse")
|
||||
h.validators["PostQuery"] = QueryValidationSpecRequired().Optional("slices", "columnAttrs", "excludeAttrs", "excludeBits")
|
||||
h.validators["GetExport"] = QueryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["GetFragmentData"] = QueryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["PostFragmentData"] = QueryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["GetFragmentBlocks"] = QueryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["PostFrameRestore"] = QueryValidationSpecRequired("host")
|
||||
h.validators["GetFragmentNodes"] = queryValidationSpecRequired("slice").Optional("index")
|
||||
h.validators["GetSliceMax"] = queryValidationSpecRequired().Optional("inverse")
|
||||
h.validators["PostQuery"] = queryValidationSpecRequired().Optional("slices", "columnAttrs", "excludeAttrs", "excludeBits")
|
||||
h.validators["GetExport"] = queryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["GetFragmentData"] = queryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["PostFragmentData"] = queryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["GetFragmentBlocks"] = queryValidationSpecRequired("index", "frame", "view", "slice")
|
||||
h.validators["PostFrameRestore"] = queryValidationSpecRequired("host")
|
||||
}
|
||||
|
||||
func (h *Handler) queryArgValidator(next http.Handler) http.Handler {
|
||||
|
|
@ -154,7 +154,7 @@ func loadCommon(router *mux.Router, handler *Handler) {
|
|||
router.HandleFunc("/cluster/message", handler.handlePostClusterMessage).Methods("POST")
|
||||
router.HandleFunc("/cluster/resize/set-coordinator", handler.handlePostClusterResizeSetCoordinator).Methods("POST")
|
||||
router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux).Methods("GET")
|
||||
router.HandleFunc("/debug/vars", handler.handleExpvar).Methods("GET")
|
||||
router.Handle("/debug/vars", expvar.Handler()).Methods("GET")
|
||||
router.HandleFunc("/fragment/data", handler.handleGetFragmentData).Methods("GET").Name("GetFragmentData")
|
||||
router.HandleFunc("/hosts", handler.handleGetHosts).Methods("GET")
|
||||
router.HandleFunc("/id", handler.handleGetID).Methods("GET")
|
||||
|
|
@ -174,7 +174,7 @@ func loadRestricted(router *mux.Router, handler *Handler) {
|
|||
func loadNormal(router *mux.Router, handler *Handler) {
|
||||
router.HandleFunc("/cluster/resize/remove-node", handler.handlePostClusterResizeRemoveNode).Methods("POST")
|
||||
router.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux).Methods("GET")
|
||||
router.HandleFunc("/debug/vars", handler.handleExpvar).Methods("GET")
|
||||
router.Handle("/debug/vars", expvar.Handler()).Methods("GET")
|
||||
router.HandleFunc("/export", handler.handleGetExport).Methods("GET").Name("GetExport")
|
||||
router.HandleFunc("/fragment/block/data", handler.handleGetFragmentBlockData).Methods("GET")
|
||||
router.HandleFunc("/fragment/blocks", handler.handleGetFragmentBlocks).Methods("GET").Name("GetFragmentBlocks")
|
||||
|
|
@ -270,7 +270,7 @@ func (h *Handler) handleWebUI(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
filesystem, err := h.FileSystem.New()
|
||||
if err != nil {
|
||||
h.writeQueryResponse(w, r, &QueryResponse{Err: err})
|
||||
_ = h.writeQueryResponse(w, r, &QueryResponse{Err: err})
|
||||
h.Logger.Printf("Pilosa WebUI is not available. Please run `make generate-statik` before building Pilosa with `make install`.")
|
||||
return
|
||||
}
|
||||
|
|
@ -1337,36 +1337,16 @@ func (h *Handler) handleGetHosts(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// handleGetVersion handles /version requests.
|
||||
func (h *Handler) handleGetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
version := Version
|
||||
if strings.HasPrefix(version, "v") {
|
||||
// make the version string semver-compatible
|
||||
version = version[1:]
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(struct {
|
||||
err := json.NewEncoder(w).Encode(struct {
|
||||
Version string `json:"version"`
|
||||
}{
|
||||
Version: version,
|
||||
}); err != nil {
|
||||
Version: h.API.Version(),
|
||||
})
|
||||
if err != nil {
|
||||
h.Logger.Printf("write version response error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// handleExpvar handles /debug/vars requests.
|
||||
func (h *Handler) handleExpvar(w http.ResponseWriter, r *http.Request) {
|
||||
// Copied from $GOROOT/src/expvar/expvar.go
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
fmt.Fprintf(w, "{\n")
|
||||
first := true
|
||||
expvar.Do(func(kv expvar.KeyValue) {
|
||||
if !first {
|
||||
fmt.Fprintf(w, ",\n")
|
||||
}
|
||||
first = false
|
||||
fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
|
||||
})
|
||||
fmt.Fprintf(w, "\n}\n")
|
||||
}
|
||||
|
||||
// QueryResult types.
|
||||
const (
|
||||
QueryResultTypeNil uint32 = iota
|
||||
|
|
@ -1809,7 +1789,7 @@ type queryValidationSpec struct {
|
|||
args map[string]struct{}
|
||||
}
|
||||
|
||||
func QueryValidationSpecRequired(requiredArgs ...string) *queryValidationSpec {
|
||||
func queryValidationSpecRequired(requiredArgs ...string) *queryValidationSpec {
|
||||
args := map[string]struct{}{}
|
||||
for _, arg := range requiredArgs {
|
||||
args[arg] = struct{}{}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue