-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(actions): added new repo actions package to encapsulate repo biz…
… logic For some time I've been longing for a package that encapsulates the business logic for "doing stuff with repos". This is lower level than core (which has to deal with the question of when to touch the p2p network), and higher level than repo implementations to avoid duplicating this code everywhere. This actions package comes from refactoring methods like CreateDataset _out_ of the Repo interface, and adjusting these business logic-heavy methods to work only with Repo interface methods. Already feels better. I've named the package actions for anyone who's coming to qri from the world of react & redux, where the concept of an action plays a similar role. In this version actions don't emit events to work on stores, but instead work directly on stores (repos) to do their work. This analogy gives more insight into the role repos should play moving forward. In frontend dev, the store is _a_ store of truth, but the role of being _the_ store of truth is always the server. In our case, repos serve a similar purpose, only this time the "server" is the distributed web. In both cases the store/repo is comparitively cheap to query, at the expense of being potentially out of date. So it kinda like a "necessary cache". Dope.
- Loading branch information
Showing
18 changed files
with
633 additions
and
484 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Package actions provides canonical business logic that operates on Repos | ||
// to get higher-order functionality. Actions use only Repo methods | ||
// to do their work, allowing them to be used across any repo.Repo implementation | ||
package actions | ||
|
||
import ( | ||
golog "github.com/ipfs/go-log" | ||
) | ||
|
||
var log = golog.Logger("actions") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package actions | ||
|
||
import ( | ||
"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" | ||
"github.com/qri-io/qri/repo/profile" | ||
) | ||
|
||
// Dataset wraps a repo.Repo, adding actions related to working | ||
// with datasets | ||
type Dataset struct { | ||
repo.Repo | ||
} | ||
|
||
// CreateDataset initializes a dataset from a dataset pointer and data file | ||
func (act Dataset) CreateDataset(name string, ds *dataset.Dataset, data cafs.File, pin bool) (ref repo.DatasetRef, err error) { | ||
var ( | ||
path datastore.Key | ||
pro *profile.Profile | ||
) | ||
pro, err = act.Profile() | ||
if err != nil { | ||
return | ||
} | ||
|
||
path, err = dsfs.CreateDataset(act.Store(), ds, data, act.PrivateKey(), pin) | ||
if err != nil { | ||
return | ||
} | ||
|
||
if ds.PreviousPath != "" && ds.PreviousPath != "/" { | ||
prev := repo.DatasetRef{ | ||
PeerID: pro.ID, | ||
Peername: pro.Peername, | ||
Name: name, | ||
Path: ds.PreviousPath, | ||
} | ||
if err = act.DeleteRef(prev); err != nil { | ||
log.Error(err.Error()) | ||
err = nil | ||
} | ||
} | ||
|
||
ref = repo.DatasetRef{ | ||
PeerID: pro.ID, | ||
Peername: pro.Peername, | ||
Name: name, | ||
Path: path.String(), | ||
} | ||
|
||
if err = act.PutRef(ref); err != nil { | ||
log.Error(err.Error()) | ||
return | ||
} | ||
|
||
if err = act.LogEvent(repo.ETDsCreated, ref); err != nil { | ||
return | ||
} | ||
|
||
_, storeIsPinner := act.Store().(cafs.Pinner) | ||
if pin && storeIsPinner { | ||
act.LogEvent(repo.ETDsPinned, ref) | ||
} | ||
return | ||
} | ||
|
||
// ReadDataset grabs a dataset from the store | ||
func (act Dataset) ReadDataset(ref *repo.DatasetRef) (err error) { | ||
if act.Repo.Store() != nil { | ||
ref.Dataset, err = dsfs.LoadDataset(act.Store(), datastore.NewKey(ref.Path)) | ||
return | ||
} | ||
|
||
return datastore.ErrNotFound | ||
} | ||
|
||
// RenameDataset alters a dataset name | ||
func (act Dataset) RenameDataset(a, b repo.DatasetRef) (err error) { | ||
if err = act.DeleteRef(a); err != nil { | ||
return err | ||
} | ||
if err = act.PutRef(b); err != nil { | ||
return err | ||
} | ||
|
||
return act.LogEvent(repo.ETDsRenamed, b) | ||
} | ||
|
||
// PinDataset marks a dataset for retention in a store | ||
func (act Dataset) PinDataset(ref repo.DatasetRef) error { | ||
if pinner, ok := act.Store().(cafs.Pinner); ok { | ||
pinner.Pin(datastore.NewKey(ref.Path), true) | ||
return act.LogEvent(repo.ETDsPinned, ref) | ||
} | ||
return repo.ErrNotPinner | ||
} | ||
|
||
// UnpinDataset unmarks a dataset for retention in a store | ||
func (act Dataset) UnpinDataset(ref repo.DatasetRef) error { | ||
if pinner, ok := act.Store().(cafs.Pinner); ok { | ||
pinner.Unpin(datastore.NewKey(ref.Path), true) | ||
return act.LogEvent(repo.ETDsUnpinned, ref) | ||
} | ||
return repo.ErrNotPinner | ||
} | ||
|
||
// DeleteDataset removes a dataset from the store | ||
func (act Dataset) DeleteDataset(ref repo.DatasetRef) error { | ||
if err := act.DeleteRef(ref); err != nil { | ||
return err | ||
} | ||
if err := act.UnpinDataset(ref); err != nil && err != repo.ErrNotPinner { | ||
return err | ||
} | ||
|
||
return act.LogEvent(repo.ETDsDeleted, ref) | ||
} |
Oops, something went wrong.