Skip to content

Commit

Permalink
feat(history): add support for dataset history logs
Browse files Browse the repository at this point in the history
datasets now have an endpoint to surface histories of datasets.
  • Loading branch information
b5 committed Nov 7, 2017
1 parent 4d5647b commit f9a3938
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
56 changes: 56 additions & 0 deletions api/handlers/history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package handlers

import (
"net/http"

util "github.com/datatogether/api/apiutil"
"github.com/ipfs/go-datastore"
"github.com/qri-io/cafs"
"github.com/qri-io/dataset"
"github.com/qri-io/qri/core"
"github.com/qri-io/qri/logging"
"github.com/qri-io/qri/repo"
)

// HistoryHandlers wraps a HistoryRequests with http.HandlerFuncs
type HistoryHandlers struct {
core.HistoryRequests
log logging.Logger
}

func NewHistoryHandlers(log logging.Logger, r repo.Repo, store cafs.Filestore) *HistoryHandlers {
req := core.NewHistoryRequests(r, store)
h := HistoryHandlers{*req, log}
return &h
}

func (h *HistoryHandlers) LogHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "OPTIONS":
util.EmptyOkHandler(w, r)
case "GET":
h.logHandler(w, r)
default:
util.NotFoundHandler(w, r)
}
}

func (h *HistoryHandlers) logHandler(w http.ResponseWriter, r *http.Request) {
p := util.PageFromRequest(r)
params := &core.LogParams{
ListParams: core.ListParams{
Limit: p.Limit(),
Offset: p.Offset(),
},
Path: datastore.NewKey(r.URL.Path[len("/history/"):]),
}

res := []*dataset.Dataset{}
if err := h.Log(params, &res); err != nil {
h.log.Infof("")
util.WriteErrResponse(w, http.StatusInternalServerError, err)
return
}

util.WritePageResponse(w, res, r, p)
}
3 changes: 3 additions & 0 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ func NewServerRoutes(s *Server) *http.ServeMux {
m.Handle("/data/ipfs/", s.middleware(dsh.StructuredDataHandler))
m.Handle("/download/", s.middleware(dsh.ZipDatasetHandler))

hh := handlers.NewHistoryHandlers(s.log, s.qriNode.Repo, s.qriNode.Store)
m.Handle("/history/", s.middleware(hh.LogHandler))

qh := handlers.NewQueryHandlers(s.log, s.qriNode.Store, s.qriNode.Repo)
m.Handle("/queries", s.middleware(qh.ListHandler))
m.Handle("/run", s.middleware(qh.RunHandler))
Expand Down
58 changes: 58 additions & 0 deletions core/history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package core

import (
"fmt"

"github.com/ipfs/go-datastore"
"github.com/qri-io/cafs"
"github.com/qri-io/dataset"
"github.com/qri-io/dataset/dsfs"
"github.com/qri-io/qri/repo"
)

type HistoryRequests struct {
repo repo.Repo
store cafs.Filestore
}

func NewHistoryRequests(r repo.Repo, store cafs.Filestore) *HistoryRequests {
return &HistoryRequests{
repo: r,
store: store,
}
}

type LogParams struct {
Path datastore.Key
ListParams
}

func (d *HistoryRequests) Log(params *LogParams, log *[]*dataset.Dataset) (err error) {
dss := []*dataset.Dataset{}
limit := params.Limit
ds := &dataset.Dataset{Previous: params.Path}

if params.Path.String() == "" {
return fmt.Errorf("path is required")
}

for {
if ds.Previous.String() == "" {
break
}

ds, err = dsfs.LoadDataset(d.store, ds.Previous)
if err != nil {
return err
}
dss = append(dss, ds)

limit--
if limit == 0 {
break
}
}

*log = dss
return nil
}
47 changes: 47 additions & 0 deletions core/history_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package core

import (
"testing"

"github.com/ipfs/go-datastore"
"github.com/qri-io/dataset"
)

func TestHistoryRequestsLog(t *testing.T) {
mr, ms, err := NewTestRepo()
if err != nil {
t.Errorf("error allocating test repo: %s", err.Error())
return
}
path, err := mr.GetPath("movies")
if err != nil {
t.Errorf("error getting path: %s", err.Error())
return
}

cases := []struct {
p *LogParams
res []*dataset.Dataset
err string
}{
{&LogParams{}, nil, "path is required"},
{&LogParams{Path: datastore.NewKey("/badpath")}, nil, "error getting file bytes: datastore: key not found"},
{&LogParams{Path: path}, []*dataset.Dataset{&dataset.Dataset{}}, ""},
}

req := NewHistoryRequests(mr, ms)
for i, c := range cases {
got := []*dataset.Dataset{}
err := req.Log(c.p, &got)

if !(err == nil && c.err == "" || err != nil && err.Error() == c.err) {
t.Errorf("case %d error mismatch: expected: %s, got: %s", i, c.err, err)
continue
}

if len(c.res) != len(got) {
t.Errorf("case %d log count mismatch. expected: %d, got: %d", len(c.res), len(got))
continue
}
}
}

0 comments on commit f9a3938

Please sign in to comment.