1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-09 17:44:59 +09:00

components first iteration

This commit is contained in:
Sergey Cherepanov 2021-03-11 12:41:41 +03:00
parent 6279f8c45f
commit e189434f93
No known key found for this signature in database
GPG key ID: 085319C64294F576
46 changed files with 556 additions and 474 deletions

View file

@ -30,11 +30,11 @@ type ComponentRunnable interface {
Component
// Run will be called after init stage
// Non-nil error also will be aborted app start
Run() error
Run() (err error)
// Close will be called when app shutting down
// Also will be called when service return error on Init or Run stage
// Non-nil error will be printed to log
Close() error
Close() (err error)
}
// App is the central part of the application

View file

@ -17,14 +17,11 @@ import (
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/wallet"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/libp2p/go-libp2p-core/peer"
)
const cafeUrl = "https://cafe1.anytype.io"
@ -120,10 +117,8 @@ func (mw *Middleware) AccountCreate(req *pb.RpcAccountCreateRequest) *pb.RpcAcco
return m
}
if mw.Anytype != nil {
if err := mw.stop(); err != nil {
response(nil, pb.RpcAccountCreateResponseError_FAILED_TO_STOP_RUNNING_NODE, err)
}
if err := mw.stop(); err != nil {
response(nil, pb.RpcAccountCreateResponseError_FAILED_TO_STOP_RUNNING_NODE, err)
}
index := len(mw.foundAccounts)
@ -158,48 +153,27 @@ func (mw *Middleware) AccountCreate(req *pb.RpcAccountCreateRequest) *pb.RpcAcco
return response(nil, pb.RpcAccountCreateResponseError_UNKNOWN_ERROR, err)
}
if mw.Anytype, err = core.New(
at, err := core.New(
core.WithRootPathAndAccount(mw.rootPath, account.Address()),
core.WithSnapshotMarshalerFunc(change.NewSnapshotChange),
); err != nil {
)
if err != nil {
return response(nil, pb.RpcAccountCreateResponseError_UNKNOWN_ERROR, err)
}
newAcc := &model.Account{Id: account.Address()}
if err = mw.start(); err != nil {
if mw.app, err = anytype.StartNewApp(at, mw.EventSender); err != nil {
return response(newAcc, pb.RpcAccountCreateResponseError_ACCOUNT_CREATED_BUT_FAILED_TO_START_NODE, err)
}
if err = mw.Anytype.InitPredefinedBlocks(context.TODO(), false); err != nil {
if err = at.InitPredefinedBlocks(context.TODO(), false); err != nil {
return response(newAcc, pb.RpcAccountCreateResponseError_ACCOUNT_CREATED_BUT_FAILED_TO_START_NODE, err)
}
newAcc.Name = req.Name
var (
cafePid, _ = peer.Decode(cafePeerId)
ownDevice = mw.Anytype.Device()
profileInfo = mw.Anytype
fileStatus = mw.Anytype.FileStatus()
syncStatus = mw.Anytype.SyncStatus()
eventSender = mw.EventSender.Send
details = []*pb.RpcBlockSetDetailsDetail{{Key: "name", Value: pbtypes.String(req.Name)}}
ss = status.NewService(syncStatus, fileStatus, profileInfo, eventSender, cafePid.String(), ownDevice)
bs = block.NewService(newAcc.Id, anytype.NewService(mw.Anytype), mw.linkPreview, ss, eventSender)
)
is, err := indexer.NewIndexer(anytype.NewService(mw.Anytype), bs)
if err != nil {
panic(err)
}
if err := ss.Start(); err != nil {
// app misconfiguration
panic(err)
}
bs := mw.app.MustComponent(block.CName).(block.Service)
details := []*pb.RpcBlockSetDetailsDetail{{Key: "name", Value: pbtypes.String(req.Name)}}
if req.GetAvatarLocalPath() != "" {
hash, err := bs.UploadFile(pb.RpcUploadFileRequest{
LocalPath: req.GetAvatarLocalPath(),
@ -223,16 +197,13 @@ func (mw *Middleware) AccountCreate(req *pb.RpcAccountCreateRequest) *pb.RpcAcco
}
if err = bs.SetDetails(nil, pb.RpcBlockSetDetailsRequest{
ContextId: mw.Anytype.PredefinedBlocks().Profile,
ContextId: at.PredefinedBlocks().Profile,
Details: details,
}); err != nil {
return response(newAcc, pb.RpcAccountCreateResponseError_ACCOUNT_CREATED_BUT_FAILED_TO_SET_NAME, err)
}
mw.foundAccounts = append(mw.foundAccounts, newAcc)
mw.setStatusService(ss)
mw.setBlockService(bs)
mw.setIndexer(is)
return response(newAcc, pb.RpcAccountCreateResponseError_NULL, nil)
}
@ -306,10 +277,11 @@ func (mw *Middleware) AccountRecover(_ *pb.RpcAccountRecoverRequest) *pb.RpcAcco
// do not unlock on defer because client may do AccountSelect before all remote accounts arrives
// it is ok to unlock just after we've started with the 1st account
if mw.Anytype, err = core.New(
at, err := core.New(
core.WithRootPathAndAccount(mw.rootPath, zeroAccount.Address()),
core.WithSnapshotMarshalerFunc(change.NewSnapshotChange),
); err != nil {
)
if err != nil {
return response(pb.RpcAccountRecoverResponseError_LOCAL_REPO_EXISTS_BUT_CORRUPTED, err)
}
@ -320,7 +292,7 @@ func (mw *Middleware) AccountRecover(_ *pb.RpcAccountRecoverRequest) *pb.RpcAcco
mw.accountSearchCancel = func() { searchQueryCancel() }
defer searchQueryCancel()
if err = mw.start(); err != nil {
if mw.app, err = anytype.StartNewApp(at, mw.EventSender); err != nil {
if strings.Contains(err.Error(), errSubstringMultipleAnytypeInstance) {
return response(pb.RpcAccountRecoverResponseError_ANOTHER_ANYTYPE_PROCESS_IS_RUNNING, err)
}
@ -385,7 +357,7 @@ func (mw *Middleware) AccountRecover(_ *pb.RpcAccountRecoverRequest) *pb.RpcAcco
}()
findProfilesErr := mw.Anytype.FindProfilesByAccountIDs(ctx, keypairsToAddresses(accounts), profilesCh)
findProfilesErr := at.FindProfilesByAccountIDs(ctx, keypairsToAddresses(accounts), profilesCh)
if findProfilesErr != nil {
log.Errorf("remote profiles request failed: %s", findProfilesErr.Error())
@ -434,16 +406,11 @@ func (mw *Middleware) AccountSelect(req *pb.RpcAccountSelectRequest) *pb.RpcAcco
mw.m.Lock()
defer mw.m.Unlock()
if mw.Anytype == nil || req.Id != mw.Anytype.Account() || !mw.Anytype.IsStarted() {
if mw.app == nil || req.Id != mw.app.MustComponent(core.CName).(core.Service).Account() {
// in case user selected account other than the first one(used to perform search)
// or this is the first time in this session we run the Anytype node
if mw.Anytype != nil {
log.Debugf("AccountSelect wrong account %s instead of %s. stop it", mw.Anytype.Account(), req.Id)
// user chose account other than the first one
// we need to stop the first node that what used to search other accounts and then start the right one
if err := mw.stop(); err != nil {
return response(nil, pb.RpcAccountSelectResponseError_FAILED_TO_STOP_SEARCHER_NODE, err)
}
if err := mw.stop(); err != nil {
return response(nil, pb.RpcAccountSelectResponseError_FAILED_TO_STOP_SEARCHER_NODE, err)
}
if req.RootPath != "" {
@ -488,15 +455,15 @@ func (mw *Middleware) AccountSelect(req *pb.RpcAccountSelectRequest) *pb.RpcAcco
}
}
var err error
if mw.Anytype, err = core.New(
at, err := core.New(
core.WithRootPathAndAccount(mw.rootPath, req.Id),
core.WithSnapshotMarshalerFunc(change.NewSnapshotChange),
); err != nil {
)
if err != nil {
return response(nil, pb.RpcAccountSelectResponseError_UNKNOWN_ERROR, err)
}
if err := mw.start(); err != nil {
if mw.app, err = anytype.StartNewApp(at, mw.EventSender); err != nil {
if err == core.ErrRepoCorrupted {
return response(nil, pb.RpcAccountSelectResponseError_LOCAL_REPO_EXISTS_BUT_CORRUPTED, err)
}
@ -507,38 +474,11 @@ func (mw *Middleware) AccountSelect(req *pb.RpcAccountSelectRequest) *pb.RpcAcco
return response(nil, pb.RpcAccountSelectResponseError_FAILED_TO_RUN_NODE, err)
}
if err := at.InitPredefinedBlocks(context.TODO(), true); err != nil {
return response(nil, pb.RpcAccountSelectResponseError_FAILED_TO_RECOVER_PREDEFINED_BLOCKS, err)
}
}
if err := mw.Anytype.InitPredefinedBlocks(context.TODO(), true); err != nil {
return response(nil, pb.RpcAccountSelectResponseError_FAILED_TO_RECOVER_PREDEFINED_BLOCKS, err)
}
var (
acc = model.Account{Id: req.Id}
cafePid, _ = peer.Decode(cafePeerId)
ownDevice = mw.Anytype.Device()
profileInfo = mw.Anytype
fileStatus = mw.Anytype.FileStatus()
syncStatus = mw.Anytype.SyncStatus()
eventSender = mw.EventSender.Send
ss = status.NewService(syncStatus, fileStatus, profileInfo, eventSender, cafePid.String(), ownDevice)
bs = block.NewService(acc.Id, mw.Anytype, mw.linkPreview, ss, eventSender)
)
is, err := indexer.NewIndexer(anytype.NewService(mw.Anytype), bs)
if err != nil {
panic(err)
}
if err := ss.Start(); err != nil {
// app misconfiguration
panic(err)
}
mw.setIndexer(is)
mw.setStatusService(ss)
mw.setBlockService(bs)
return response(&acc, pb.RpcAccountSelectResponseError_NULL, nil)
return response(&model.Account{Id: req.Id}, pb.RpcAccountSelectResponseError_NULL, nil)
}
func (mw *Middleware) AccountStop(req *pb.RpcAccountStopRequest) *pb.RpcAccountStopResponse {
@ -555,11 +495,11 @@ func (mw *Middleware) AccountStop(req *pb.RpcAccountStopRequest) *pb.RpcAccountS
return m
}
if mw.Anytype == nil {
if mw.app == nil {
return response(pb.RpcAccountStopResponseError_ACCOUNT_IS_NOT_RUNNING, fmt.Errorf("anytype node not set"))
}
address := mw.Anytype.Account()
address := mw.app.MustComponent(core.CName).(core.Service).Account()
err := mw.stop()
if err != nil {
return response(pb.RpcAccountStopResponseError_FAILED_TO_STOP_NODE, err)

View file

@ -1,51 +0,0 @@
package anytype
import (
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
)
func NewService(c core.Service) Service {
return &service{c}
}
type service struct {
core.Service
}
func SmartBlockTypeToProto(t coresb.SmartBlockType) pb.SmartBlockType {
switch t {
case coresb.SmartBlockTypePage:
return pb.SmartBlockType_Page
case coresb.SmartBlockTypeArchive:
return pb.SmartBlockType_Archive
case coresb.SmartBlockTypeHome:
return pb.SmartBlockType_Home
case coresb.SmartBlockTypeProfilePage:
return pb.SmartBlockType_ProfilePage
case coresb.SmartBlockTypeSet:
return pb.SmartBlockType_Set
case coresb.SmartBlockTypeObjectType:
return pb.SmartBlockType_ObjectType
}
return 0
}
func SmartBlockTypeToCore(t pb.SmartBlockType) coresb.SmartBlockType {
switch t {
case pb.SmartBlockType_Page:
return coresb.SmartBlockTypePage
case pb.SmartBlockType_Archive:
return coresb.SmartBlockTypeArchive
case pb.SmartBlockType_Home:
return coresb.SmartBlockTypeHome
case pb.SmartBlockType_ProfilePage:
return coresb.SmartBlockTypeProfilePage
case pb.SmartBlockType_Set:
return coresb.SmartBlockTypeSet
case pb.SmartBlockType_ObjectType:
return coresb.SmartBlockTypeObjectType
}
return 0
}

39
core/anytype/bootstrap.go Normal file
View file

@ -0,0 +1,39 @@
package anytype
import (
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/export"
"github.com/anytypeio/go-anytype-middleware/core/block/meta"
"github.com/anytypeio/go-anytype-middleware/core/block/process"
"github.com/anytypeio/go-anytype-middleware/core/history"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/gateway"
"github.com/anytypeio/go-anytype-middleware/util/linkpreview"
)
func StartNewApp(components ...app.Component) (a *app.App, err error) {
a = new(app.App)
Bootstrap(a, components...)
if err = a.Start(); err != nil {
return
}
return
}
func Bootstrap(a *app.App, components ...app.Component) {
for _, c := range components {
a.Register(c)
}
a.Register(indexer.New()).
Register(status.New()).
Register(meta.New()).
Register(block.New()).
Register(process.New()).
Register(history.New()).
Register(gateway.New()).
Register(export.New()).
Register(linkpreview.New())
return
}

View file

@ -1,30 +0,0 @@
package anytype
import (
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/localstore"
)
type Service interface {
core.Service
}
type SmartBlock interface {
core.SmartBlock
}
type SmartBlockSnapshot interface {
core.SmartBlockSnapshot
}
type File interface {
core.File
}
type Image interface {
core.Image
}
type ObjectStore interface {
localstore.ObjectStore
}

View file

@ -7,6 +7,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/source"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
@ -108,7 +109,7 @@ func (mw *Middleware) BlockOpen(req *pb.RpcBlockOpenRequest) *pb.RpcBlockOpenRes
}
err = mw.doBlockService(func(bs block.Service) error {
return mw.indexer.SetDetail(req.BlockId, bundle.RelationKeyLastOpenedDate.String(), pbtypes.Float64(float64(time.Now().Unix())))
return mw.app.MustComponent(indexer.CName).(indexer.Indexer).SetDetail(req.BlockId, bundle.RelationKeyLastOpenedDate.String(), pbtypes.Float64(float64(time.Now().Unix())))
})
if err != nil {
log.Errorf("failed to update last opened for the object %s: %s", req.BlockId, err.Error())

View file

@ -1,10 +1,10 @@
package database
import (
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/database/objects"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/database"
pbrelation "github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/relation"
@ -13,7 +13,7 @@ import (
)
type Ctrl interface {
Anytype() anytype.Service
Anytype() core.Service
SetDetails(ctx *state.Context, req pb.RpcBlockSetDetailsRequest) error
GetRelations(objectId string) (relations []*pbrelation.Relation, err error)

View file

@ -9,13 +9,13 @@ import (
"sync"
"sync/atomic"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/process"
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
"github.com/anytypeio/go-anytype-middleware/core/block/simple/file"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
@ -38,7 +38,7 @@ type BlockService interface {
DoFile(id string, apply func(f File) error) error
CreatePage(ctx *state.Context, groupId string, req pb.RpcBlockCreatePageRequest) (linkId string, pageId string, err error)
ProcessAdd(p process.Process) (err error)
Anytype() anytype.Service
Anytype() core.Service
}
type File interface {

View file

@ -14,9 +14,9 @@ import (
"strings"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
"github.com/anytypeio/go-anytype-middleware/core/block/simple/file"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/files"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/uri"
@ -90,7 +90,7 @@ func (ur UploadResult) ToBlock() file.Block {
type uploader struct {
service BlockService
anytype anytype.Service
anytype core.Service
block file.Block
getReader func(ctx context.Context) (*bufioSeekClose, error)
name string

View file

@ -8,7 +8,6 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/database/objects"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/meta"
@ -74,7 +73,7 @@ type SmartBlock interface {
SetEventFunc(f func(e *pb.Event))
Apply(s *state.State, flags ...ApplyFlag) error
History() undo.History
Anytype() anytype.Service
Anytype() core.Service
SetDetails(ctx *state.Context, details []*pb.RpcBlockSetDetailsDetail) (err error)
Relations() []*pbrelation.Relation
HasRelation(relationKey string) bool
@ -519,7 +518,7 @@ func (sb *smartBlock) History() undo.History {
return sb.undo
}
func (sb *smartBlock) Anytype() anytype.Service {
func (sb *smartBlock) Anytype() core.Service {
return sb.source.Anytype()
}

View file

@ -4,7 +4,6 @@ import (
"fmt"
"sync"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/meta"
@ -277,7 +276,7 @@ func (st *SmartTest) History() undo.History {
return st.hist
}
func (st *SmartTest) Anytype() anytype.Service {
func (st *SmartTest) Anytype() core.Service {
return st.anytype
}

View file

@ -5,34 +5,45 @@ import (
"path/filepath"
"strings"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/block"
sb "github.com/anytypeio/go-anytype-middleware/core/block/editor/smartblock"
"github.com/anytypeio/go-anytype-middleware/core/block/process"
"github.com/anytypeio/go-anytype-middleware/core/converter/md"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/database"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
"github.com/globalsign/mgo/bson"
)
const CName = "export"
var log = logging.Logger("anytype-mw-export")
func NewExport(a anytype.Service, bs block.Service) Export {
return &export{
bs: bs,
a: a,
}
func New() Export {
return new(export)
}
type Export interface {
Export(req pb.RpcExportRequest) (path string, err error)
app.Component
}
type export struct {
bs block.Service
a anytype.Service
a core.Service
}
func (e *export) Init(a *app.App) (err error) {
e.bs = a.MustComponent(block.CName).(block.Service)
e.a = a.MustComponent(core.CName).(core.Service)
return
}
func (e *export) Name() (name string) {
return CName
}
func (e *export) Export(req pb.RpcExportRequest) (path string, err error) {

View file

@ -5,7 +5,6 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/source"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
@ -43,7 +42,7 @@ type Subscriber interface {
Close()
}
func newPubSub(a anytype.Service, ss status.Service) *pubSub {
func newPubSub(a core.Service, ss status.Service) *pubSub {
ps := &pubSub{
subscribers: make(map[string]map[Subscriber]struct{}),
collectors: make(map[string]*collector),
@ -58,7 +57,7 @@ func newPubSub(a anytype.Service, ss status.Service) *pubSub {
}
type pubSub struct {
anytype anytype.Service
anytype core.Service
subscribers map[string]map[Subscriber]struct{}
collectors map[string]*collector
lastUsage map[string]time.Time

View file

@ -5,7 +5,7 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/block/database/objects"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
@ -14,6 +14,8 @@ import (
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
)
const CName = "meta"
type Meta struct {
BlockId string
core.SmartBlockMeta
@ -22,27 +24,39 @@ type Meta struct {
type Service interface {
PubSub() PubSub
ReportChange(m Meta)
Close() (err error)
FetchMeta(ids []string) (metas []Meta)
FetchObjectTypes(objectTypeUrls []string) []*pbrelation.ObjectType
app.ComponentRunnable
}
func NewService(a anytype.Service, ss status.Service) Service {
s := &service{
ps: newPubSub(a, ss),
}
func New() Service {
return new(service)
}
type service struct {
anytype core.Service
ps *pubSub
m sync.Mutex
}
func (s *service) Init(a *app.App) (err error) {
s.anytype = a.MustComponent(core.CName).(core.Service)
s.ps = newPubSub(s.anytype, a.MustComponent(status.CName).(status.Service))
return
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run() (err error) {
var newSmartblockCh = make(chan string)
if err := a.InitNewSmartblocksChan(newSmartblockCh); err != nil {
if err := s.anytype.InitNewSmartblocksChan(newSmartblockCh); err != nil {
log.Errorf("can't init new smartblock chan: %v", err)
} else {
go s.newSmartblockListener(newSmartblockCh)
}
return s
}
type service struct {
ps *pubSub
m sync.Mutex
return
}
func (s *service) PubSub() PubSub {

View file

@ -7,9 +7,13 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/event"
"github.com/anytypeio/go-anytype-middleware/pb"
)
const CName = "process"
var (
ErrNotFound = errors.New("process not found")
)
@ -28,16 +32,11 @@ type Service interface {
Cancel(id string) (err error)
// NewQueue creates new queue with given workers count
NewQueue(info pb.ModelProcess, workers int) Queue
// Close closes pool and cancel all running processes
Close() (err error)
app.ComponentRunnable
}
func NewService(sendEvent func(e *pb.Event)) Service {
return &service{
processes: make(map[string]Process),
waiters: make(map[string]chan struct{}),
sendEvent: sendEvent,
}
func New() Service {
return &service{}
}
type service struct {
@ -47,6 +46,21 @@ type service struct {
m sync.Mutex
}
func (s *service) Init(a *app.App) (err error) {
s.processes = make(map[string]Process)
s.waiters = make(map[string]chan struct{})
s.sendEvent = a.MustComponent(event.CName).(event.Sender).Send
return nil
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) Run() (err error) {
return
}
func (s *service) monitor(p Process) {
ticker := time.NewTicker(time.Second / 2)
defer ticker.Stop()

View file

@ -8,12 +8,14 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/event"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
pbrelation "github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/relation"
"github.com/globalsign/mgo/bson"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/database/objects"
"github.com/anytypeio/go-anytype-middleware/core/block/editor"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/basic"
@ -33,7 +35,6 @@ import (
_ "github.com/anytypeio/go-anytype-middleware/core/block/simple/link"
"github.com/anytypeio/go-anytype-middleware/core/block/simple/text"
"github.com/anytypeio/go-anytype-middleware/core/block/source"
"github.com/anytypeio/go-anytype-middleware/core/history"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pb"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
@ -46,6 +47,8 @@ import (
"github.com/textileio/go-threads/core/thread"
)
const CName = "blockService"
var (
ErrBlockNotFound = errors.New("block not found")
ErrBlockAlreadyOpen = errors.New("block already open")
@ -181,9 +184,7 @@ type Service interface {
GetSearchInfo(id string) (info indexer.SearchInfo, err error)
History() history.History
Close() error
app.ComponentRunnable
}
func newOpenedBlock(sb smartblock.SmartBlock, setLastUsage bool) *openedBlock {
@ -210,48 +211,38 @@ type openedBlock struct {
refs int32
}
func NewService(
accountId string,
a anytype.Service,
lp linkpreview.LinkPreview,
ss status.Service,
sendEvent func(event *pb.Event),
) Service {
s := &service{
accountId: accountId,
anytype: a,
status: ss,
meta: meta.NewService(a, ss),
sendEvent: func(event *pb.Event) {
sendEvent(event)
},
openedBlocks: make(map[string]*openedBlock),
linkPreview: lp,
process: process.NewService(sendEvent),
}
s.history = history.NewHistory(a, s, s.meta)
go s.cleanupTicker()
s.init()
log.Info("block service started")
return s
func New() Service {
return new(service)
}
type service struct {
anytype anytype.Service
anytype core.Service
meta meta.Service
status status.Service
accountId string
sendEvent func(event *pb.Event)
openedBlocks map[string]*openedBlock
closed bool
linkPreview linkpreview.LinkPreview
process process.Service
history history.History
m sync.Mutex
}
func (s *service) init() {
func (s *service) Name() string {
return CName
}
func (s *service) Init(a *app.App) (err error) {
s.anytype = a.MustComponent(core.CName).(core.Service)
s.meta = a.MustComponent(meta.CName).(meta.Service)
s.status = a.MustComponent(status.CName).(status.Service)
s.linkPreview = a.MustComponent(linkpreview.CName).(linkpreview.LinkPreview)
s.process = a.MustComponent(process.CName).(process.Service)
s.openedBlocks = make(map[string]*openedBlock)
s.sendEvent = a.MustComponent(event.CName).(event.Sender).Send
return
}
func (s *service) Run() (err error) {
s.Do(s.anytype.PredefinedBlocks().Archive, func(b smartblock.SmartBlock) error {
return nil
})
@ -259,9 +250,11 @@ func (s *service) init() {
s.Do(s.anytype.PredefinedBlocks().SetPages, func(b smartblock.SmartBlock) error {
return nil
})
go s.cleanupTicker()
return
}
func (s *service) Anytype() anytype.Service {
func (s *service) Anytype() core.Service {
return s.anytype
}
@ -1657,7 +1650,3 @@ func (s *service) ResetToState(pageId string, state *state.State) (err error) {
return sb.ResetToVersion(state)
})
}
func (s *service) History() history.History {
return s.history
}

View file

@ -11,10 +11,10 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/simple"
"github.com/anytypeio/go-anytype-middleware/core/block/simple/base"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/files"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/linkpreview"
@ -47,7 +47,7 @@ type Block interface {
type FetchParams struct {
Url string
Anytype anytype.Service
Anytype core.Service
Updater Updater
LinkPreview linkpreview.LinkPreview
Sync bool
@ -228,7 +228,7 @@ func (f *Bookmark) FillFileHashes(hashes []string) []string {
return hashes
}
func loadImage(stor anytype.Service, url string) (hash string, err error) {
func loadImage(stor core.Service, url string) (hash string, err error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

View file

@ -6,17 +6,17 @@ import (
"time"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/gogo/protobuf/types"
)
var getFileTimeout = time.Second * 5
func NewFiles(a anytype.Service, id string) (s Source) {
func NewFiles(a core.Service, id string) (s Source) {
return &files{
id: id,
a: a,
@ -25,14 +25,14 @@ func NewFiles(a anytype.Service, id string) (s Source) {
type files struct {
id string
a anytype.Service
a core.Service
}
func (v *files) Id() string {
return v.id
}
func (v *files) Anytype() anytype.Service {
func (v *files) Anytype() core.Service {
return v.a
}
@ -44,7 +44,7 @@ func (v *files) Virtual() bool {
return false
}
func getDetailsForFileOrImage(ctx context.Context, a anytype.Service, id string) (p *types.Struct, isImage bool, err error) {
func getDetailsForFileOrImage(ctx context.Context, a core.Service, id string) (p *types.Struct, isImage bool, err error) {
f, err := a.FileByHash(ctx, id)
if err != nil {
return nil, false, err

View file

@ -8,7 +8,6 @@ import (
"time"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pb"
@ -34,7 +33,7 @@ type ChangeReceiver interface {
type Source interface {
Id() string
Anytype() anytype.Service
Anytype() core.Service
Type() pb.SmartBlockType
Virtual() bool
ReadDoc(receiver ChangeReceiver, empty bool) (doc state.Doc, err error)
@ -46,7 +45,7 @@ type Source interface {
var ErrUnknownDataFormat = fmt.Errorf("unknown data format: you may need to upgrade anytype in order to open this page")
func NewSource(a anytype.Service, ss status.Service, id string) (s Source, err error) {
func NewSource(a core.Service, ss status.Service, id string) (s Source, err error) {
st, err := smartblock.SmartBlockTypeFromID(id)
if st == smartblock.SmartBlockTypeFile {
return NewFiles(a, id), nil
@ -54,7 +53,7 @@ func NewSource(a anytype.Service, ss status.Service, id string) (s Source, err e
return newSource(a, ss, id)
}
func newSource(a anytype.Service, ss status.Service, id string) (s Source, err error) {
func newSource(a core.Service, ss status.Service, id string) (s Source, err error) {
sb, err := a.GetBlock(id)
if err != nil {
err = fmt.Errorf("anytype.GetBlock error: %w", err)
@ -81,7 +80,7 @@ func newSource(a anytype.Service, ss status.Service, id string) (s Source, err e
type source struct {
id, logId string
tid thread.ID
a anytype.Service
a core.Service
ss status.Service
sb core.SmartBlock
tree *change.Tree
@ -97,12 +96,12 @@ func (s *source) Id() string {
return s.id
}
func (s *source) Anytype() anytype.Service {
func (s *source) Anytype() core.Service {
return s.a
}
func (s *source) Type() pb.SmartBlockType {
return anytype.SmartBlockTypeToProto(s.sb.Type())
return smartblock.SmartBlockTypeToProto(s.sb.Type())
}
func (s *source) Virtual() bool {

View file

@ -4,13 +4,13 @@ import (
"context"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/google/uuid"
)
func NewVirtual(a anytype.Service, t pb.SmartBlockType) (s Source) {
func NewVirtual(a core.Service, t pb.SmartBlockType) (s Source) {
return &virtual{
id: uuid.New().String(),
a: a,
@ -20,7 +20,7 @@ func NewVirtual(a anytype.Service, t pb.SmartBlockType) (s Source) {
type virtual struct {
id string
a anytype.Service
a core.Service
sbType pb.SmartBlockType
}
@ -28,7 +28,7 @@ func (v *virtual) Id() string {
return v.id
}
func (v *virtual) Anytype() anytype.Service {
func (v *virtual) Anytype() core.Service {
return v.a
}

View file

@ -2,21 +2,22 @@ package core
import (
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
)
func (mw *Middleware) ConfigGet(*pb.RpcConfigGetRequest) *pb.RpcConfigGetResponse {
mw.m.RLock()
defer mw.m.RUnlock()
if mw.Anytype == nil {
if mw.app == nil {
return &pb.RpcConfigGetResponse{Error: &pb.RpcConfigGetResponseError{pb.RpcConfigGetResponseError_NODE_NOT_STARTED, "account not started"}}
}
at := mw.app.MustComponent(core.CName).(core.Service)
return &pb.RpcConfigGetResponse{
Error: &pb.RpcConfigGetResponseError{pb.RpcConfigGetResponseError_NULL, ""},
HomeBlockId: mw.Anytype.PredefinedBlocks().Home,
ArchiveBlockId: mw.Anytype.PredefinedBlocks().Archive,
ProfileBlockId: mw.Anytype.PredefinedBlocks().Profile,
HomeBlockId: at.PredefinedBlocks().Home,
ArchiveBlockId: at.PredefinedBlocks().Archive,
ProfileBlockId: at.PredefinedBlocks().Profile,
GatewayUrl: mw.gatewayAddr,
}
}

View file

@ -9,8 +9,8 @@ import (
"io/ioutil"
"strconv"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
)
@ -55,12 +55,12 @@ const (
</html>`
)
func NewHTMLConverter(a anytype.Service, s *state.State) *HTML {
func NewHTMLConverter(a core.Service, s *state.State) *HTML {
return &HTML{a: a, s: s}
}
type HTML struct {
a anytype.Service
a core.Service
s *state.State
buf *bytes.Buffer
}

View file

@ -9,19 +9,19 @@ import (
"strings"
"github.com/JohannesKaufmann/html-to-markdown/escape"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
func NewMDConverter(a anytype.Service, s *state.State) *MD {
func NewMDConverter(a core.Service, s *state.State) *MD {
return &MD{a: a, s: s}
}
type MD struct {
a anytype.Service
a core.Service
s *state.State
buf *bytes.Buffer

View file

@ -5,17 +5,12 @@ import (
"errors"
"sync"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/export"
"github.com/anytypeio/go-anytype-middleware/core/event"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/core/status"
"github.com/anytypeio/go-anytype-middleware/pb"
libCore "github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/gateway"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/anytypeio/go-anytype-middleware/util/linkpreview"
)
var log = logging.Logger("anytype-mw-api")
@ -35,13 +30,7 @@ type Middleware struct {
EventSender event.Sender
blocksService block.Service
linkPreview linkpreview.LinkPreview
status status.Service
indexer indexer.Indexer
exportService export.Export
Anytype libCore.Service
app *app.App
m sync.RWMutex
}
@ -64,8 +53,8 @@ func (mw *Middleware) Shutdown(request *pb.RpcShutdownRequest) *pb.RpcShutdownRe
func (mw *Middleware) getBlockService() (bs block.Service, err error) {
mw.m.RLock()
defer mw.m.RUnlock()
if mw.blocksService != nil {
return mw.blocksService, nil
if mw.app != nil {
return mw.app.MustComponent(block.CName).(block.Service), nil
}
return nil, ErrNotLoggedIn
}
@ -78,78 +67,15 @@ func (mw *Middleware) doBlockService(f func(bs block.Service) error) (err error)
return f(bs)
}
func (mw *Middleware) setIndexer(is indexer.Indexer) {
if mw.indexer != nil {
mw.indexer.Close()
}
mw.indexer = is
}
func (mw *Middleware) setBlockService(bs block.Service) {
if mw.blocksService != nil {
mw.blocksService.Close()
}
mw.blocksService = bs
mw.exportService = export.NewExport(mw.Anytype, bs)
}
func (mw *Middleware) setStatusService(ss status.Service) {
mw.status = ss
}
// Start starts the anytype node and HTTP gateway
func (mw *Middleware) start() error {
err := mw.Anytype.Start()
if err != nil {
return err
}
// start the local http gateway
gateway.Host = &gateway.Gateway{
Node: mw.Anytype,
}
gwAddr := gateway.GatewayAddr()
mw.gatewayAddr = "http://" + gwAddr
err = gateway.Host.Start(gwAddr)
if err != nil {
return err
}
log.Debug("Gateway started: " + mw.gatewayAddr)
mw.linkPreview = linkpreview.NewWithCache()
return nil
}
// Stop stops the anytype node and HTTP gateway
func (mw *Middleware) stop() error {
if gateway.Host != nil {
err := gateway.Host.Stop()
if err != nil {
log.Warnf("error while stop gateway: %v", err)
}
}
if mw.indexer != nil {
mw.indexer.Close()
}
if mw.blocksService != nil {
if err := mw.blocksService.Close(); err != nil {
log.Warnf("error while stop block service: %v", err)
}
}
if mw.status != nil {
mw.status.Stop()
}
if mw != nil && mw.Anytype != nil {
err := mw.Anytype.Stop()
if mw != nil && mw.app != nil {
err := mw.app.Close()
if err != nil {
log.Warnf("error while stop anytype: %v", err)
}
mw.Anytype = nil
mw.app = nil
mw.accountSearchCancel()
}
return nil

View file

@ -3,10 +3,11 @@ package core
import (
"context"
"fmt"
"github.com/textileio/go-threads/jsonpatcher"
"sort"
"time"
"github.com/textileio/go-threads/jsonpatcher"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/pb"
@ -31,8 +32,15 @@ func (mw *Middleware) DebugThread(req *pb.RpcDebugThreadRequest) *pb.RpcDebugThr
return m
}
mw.m.RLock()
defer mw.m.RUnlock()
if mw.app == nil {
return response(nil, 0, nil)
}
t := mw.Anytype.(*core.Anytype).ThreadService().Threads()
at := mw.app.MustComponent(core.CName).(core.Service)
t := at.(*core.Anytype).ThreadService().Threads()
cafePeer, _ := peer.Decode(cafePeerId)
tid, err := thread.Decode(req.ThreadId)
@ -40,13 +48,20 @@ func (mw *Middleware) DebugThread(req *pb.RpcDebugThreadRequest) *pb.RpcDebugThr
return response(nil, pb.RpcDebugThreadResponseError_BAD_INPUT, err)
}
tinfo := getThreadInfo(t, tid, mw.Anytype.Device(), cafePeer, req.SkipEmptyLogs, req.TryToDownloadRemoteRecords)
tinfo := getThreadInfo(t, tid, at.Device(), cafePeer, req.SkipEmptyLogs, req.TryToDownloadRemoteRecords)
return response(&tinfo, 0, nil)
}
func (mw *Middleware) DebugSync(req *pb.RpcDebugSyncRequest) *pb.RpcDebugSyncResponse {
mw.m.RLock()
if mw.app == nil {
return &pb.RpcDebugSyncResponse{}
}
at := mw.app.MustComponent(core.CName).(core.Service)
mw.m.Unlock()
response := func(threads []*pb.RpcDebugthreadInfo, threadsWithoutRepl int32, threadsWithoutHeadDownloaded int32, totalRecords int32, totalSize int32, code pb.RpcDebugSyncResponseErrorCode, err error) *pb.RpcDebugSyncResponse {
m := &pb.RpcDebugSyncResponse{DeviceId: mw.Anytype.Device(), Threads: threads, ThreadsWithoutReplInOwnLog: threadsWithoutRepl, ThreadsWithoutHeadDownloaded: threadsWithoutHeadDownloaded,TotalThreads: int32(len(threads)), TotalRecords: totalRecords, TotalSize: totalSize, Error: &pb.RpcDebugSyncResponseError{Code: code}}
m := &pb.RpcDebugSyncResponse{DeviceId: at.Device(), Threads: threads, ThreadsWithoutReplInOwnLog: threadsWithoutRepl, ThreadsWithoutHeadDownloaded: threadsWithoutHeadDownloaded, TotalThreads: int32(len(threads)), TotalRecords: totalRecords, TotalSize: totalSize, Error: &pb.RpcDebugSyncResponseError{Code: code}}
if err != nil {
m.Error.Description = err.Error()
}
@ -55,7 +70,7 @@ func (mw *Middleware) DebugSync(req *pb.RpcDebugSyncRequest) *pb.RpcDebugSyncRes
}
var threads []*pb.RpcDebugthreadInfo
t := mw.Anytype.(*core.Anytype).ThreadService().Threads()
t := at.(*core.Anytype).ThreadService().Threads()
ids, _ := t.Logstore().Threads()
cafePeer, _ := peer.Decode(cafePeerId)
@ -67,7 +82,7 @@ func (mw *Middleware) DebugSync(req *pb.RpcDebugSyncRequest) *pb.RpcDebugSyncRes
)
for _, id := range ids {
tinfo := getThreadInfo(t, id, mw.Anytype.Device(), cafePeer, req.SkipEmptyLogs, req.TryToDownloadRemoteRecords)
tinfo := getThreadInfo(t, id, at.Device(), cafePeer, req.SkipEmptyLogs, req.TryToDownloadRemoteRecords)
if tinfo.LogsWithDownloadedHead == 0 {
threadWithNoHeadDownloaded++
}
@ -119,7 +134,7 @@ func getThreadInfo(t net.NetBoostrapper, id thread.ID, ownDeviceId string, cafeP
}
}
if lgInfo.HeadDownloaded {
tinfo.LogsWithDownloadedHead ++
tinfo.LogsWithDownloadedHead++
}
}
@ -186,7 +201,6 @@ func getLogInfo(t net.NetBoostrapper, thrd thread.Info, lg thread.LogInfo, downl
lgInfo.Error = err.Error()
}
ss, err := t.Status(thrd.ID, lg.ID)
if err != nil {
lgInfo.DownStatus = err.Error()
@ -248,7 +262,7 @@ func getRecord(net net.NetBoostrapper, thrd thread.Info, rid cid.Cid, downloadRe
m := new(core.SignedPbPayload)
err = cbornode.DecodeInto(node.RawData(), m)
if err != nil {
jp:=jsonpatcher.New()
jp := jsonpatcher.New()
_, err2 := jp.EventsFromBytes(node.RawData())
if err2 == nil {
rinfo.Version = -1

View file

@ -1,15 +1,29 @@
package event
import "github.com/anytypeio/go-anytype-middleware/pb"
import (
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pb"
)
const CName = "eventSender"
type Sender interface {
Send(event *pb.Event)
app.Component
}
type CallbackSender struct {
callback func(event *pb.Event)
}
func (es *CallbackSender) Init(a *app.App) (err error) {
return
}
func (es *CallbackSender) Name() (name string) {
return CName
}
func NewCallbackSender(callback func(event *pb.Event)) *CallbackSender {
return &CallbackSender{callback: callback}
}

View file

@ -5,6 +5,7 @@ package event
import (
"sync"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pb/service"
"github.com/google/martian/log"
@ -20,6 +21,14 @@ type GrpcSender struct {
ServerCh chan struct{}
}
func (es *GrpcSender) Init(_ *app.App) (err error) {
return
}
func (es *GrpcSender) Name() (name string) {
return CName
}
func (es *GrpcSender) Send(pb *pb.Event) {
es.ServerMutex.Lock()
defer es.ServerMutex.Unlock()

View file

@ -2,6 +2,7 @@ package core
import (
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/export"
"github.com/anytypeio/go-anytype-middleware/pb"
)
@ -26,7 +27,8 @@ func (mw *Middleware) Export(req *pb.RpcExportRequest) *pb.RpcExportResponse {
err error
)
err = mw.doBlockService(func(_ block.Service) error {
path, err = mw.exportService.Export(*req)
es := mw.app.MustComponent(export.CName).(export.Export)
path, err = es.Export(*req)
return err
})
return response(path, err)

View file

@ -2,6 +2,7 @@ package core
import (
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/history"
"github.com/anytypeio/go-anytype-middleware/pb"
)
@ -28,7 +29,8 @@ func (mw *Middleware) HistoryShow(req *pb.RpcHistoryShowRequest) *pb.RpcHistoryS
err error
)
if err = mw.doBlockService(func(bs block.Service) (err error) {
show, ver, err = bs.History().Show(req.PageId, req.VersionId)
hs := mw.app.MustComponent(history.CName).(history.History)
show, ver, err = hs.Show(req.PageId, req.VersionId)
return
}); err != nil {
return response(nil, nil, err)
@ -58,7 +60,8 @@ func (mw *Middleware) HistoryVersions(req *pb.RpcHistoryVersionsRequest) *pb.Rpc
err error
)
if err = mw.doBlockService(func(bs block.Service) (err error) {
vers, err = bs.History().Versions(req.PageId, req.LastVersionId, int(req.Limit))
hs := mw.app.MustComponent(history.CName).(history.History)
vers, err = hs.Versions(req.PageId, req.LastVersionId, int(req.Limit))
return
}); err != nil {
return response(nil, err)
@ -81,6 +84,7 @@ func (mw *Middleware) HistorySetVersion(req *pb.RpcHistorySetVersionRequest) *pb
return
}
return response(mw.doBlockService(func(bs block.Service) (err error) {
return bs.History().SetVersion(req.PageId, req.VersionId)
hs := mw.app.MustComponent(history.CName).(history.History)
return hs.SetVersion(req.PageId, req.VersionId)
}))
}

View file

@ -4,8 +4,9 @@ import (
"fmt"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/template"
"github.com/anytypeio/go-anytype-middleware/core/block/meta"
@ -16,22 +17,21 @@ import (
"github.com/anytypeio/go-anytype-middleware/util/slice"
)
const CName = "history"
const versionGroupInterval = time.Minute * 5
var log = logging.Logger("anytype-mw-history")
func NewHistory(a anytype.Service, bs BlockService, m meta.Service) History {
return &history{
a: a,
bs: bs,
meta: m,
}
func New() History {
return new(history)
}
type History interface {
Show(pageId, versionId string) (bs *pb.EventBlockShow, ver *pb.RpcHistoryVersionsVersion, err error)
Versions(pageId, lastVersionId string, limit int) (resp []*pb.RpcHistoryVersionsVersion, err error)
SetVersion(pageId, versionId string) (err error)
app.Component
}
type BlockService interface {
@ -39,11 +39,22 @@ type BlockService interface {
}
type history struct {
a anytype.Service
a core.Service
bs BlockService
meta meta.Service
}
func (h *history) Init(a *app.App) (err error) {
h.a = a.MustComponent(core.CName).(core.Service)
h.bs = a.MustComponent(block.CName).(BlockService)
h.meta = a.MustComponent(meta.CName).(meta.Service)
return
}
func (h *history) Name() (name string) {
return CName
}
func (h *history) Show(pageId, versionId string) (bs *pb.EventBlockShow, ver *pb.RpcHistoryVersionsVersion, err error) {
s, ver, err := h.buildState(pageId, versionId)
if err != nil {
@ -82,7 +93,7 @@ func (h *history) Show(pageId, versionId string) (bs *pb.EventBlockShow, ver *pb
objectTypes := h.meta.FetchObjectTypes(uniqueObjTypes)
return &pb.EventBlockShow{
RootId: pageId,
Type: anytype.SmartBlockTypeToProto(sbType),
Type: smartblock.SmartBlockTypeToProto(sbType),
Blocks: s.Blocks(),
Details: details,
ObjectTypePerObject: objectTypePerObject,

View file

@ -3,13 +3,12 @@ package indexer
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/threads"
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/threads"
"github.com/anytypeio/go-anytype-middleware/change"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
@ -19,7 +18,7 @@ import (
"github.com/gogo/protobuf/types"
)
func newDoc(id string, a anytype.Service) (d *doc, err error) {
func newDoc(id string, a core.Service) (d *doc, err error) {
sb, err := a.GetBlock(id)
if err != nil {
err = fmt.Errorf("anytype.GetBlock error: %v", err)
@ -57,7 +56,7 @@ type doc struct {
store detailsGetter
lastUsage time.Time
mu sync.Mutex
sb anytype.SmartBlock
sb core.SmartBlock
}
type detailsGetter interface {

View file

@ -4,7 +4,7 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/core/anytype"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/threads"
@ -19,6 +19,8 @@ import (
"github.com/gogo/protobuf/types"
)
const CName = "indexer"
var log = logging.Logger("anytype-doc-indexer")
var (
@ -27,32 +29,13 @@ var (
docTTL = time.Minute * 2
)
func NewIndexer(a anytype.Service, searchInfo GetSearchInfo) (Indexer, error) {
ch, err := a.SubscribeForNewRecords()
if err != nil {
return nil, err
}
i := &indexer{
store: a.ObjectStore(),
anytype: a,
searchInfo: searchInfo,
cache: make(map[string]*doc),
quitWG: &sync.WaitGroup{},
quit: make(chan struct{}),
}
i.quitWG.Add(2)
if err := i.ftInit(); err != nil {
log.Errorf("can't init ft: %v", err)
}
go i.detailsLoop(ch)
go i.ftLoop()
return i, nil
func New() Indexer {
return &indexer{}
}
type Indexer interface {
SetDetail(id string, key string, val *types.Value) error
Close()
app.ComponentRunnable
}
type SearchInfo struct {
@ -69,7 +52,7 @@ type GetSearchInfo interface {
type indexer struct {
store localstore.ObjectStore
anytype anytype.Service
anytype core.Service
searchInfo GetSearchInfo
cache map[string]*doc
quitWG *sync.WaitGroup
@ -80,6 +63,34 @@ type indexer struct {
mu sync.Mutex
}
func (i *indexer) Init(a *app.App) (err error) {
i.anytype = a.MustComponent(core.CName).(core.Service)
i.searchInfo = a.MustComponent("blockService").(GetSearchInfo)
i.cache = make(map[string]*doc)
i.quitWG = new(sync.WaitGroup)
i.quit = make(chan struct{})
return
}
func (i *indexer) Name() (name string) {
return CName
}
func (i *indexer) Run() (err error) {
i.store = i.anytype.ObjectStore()
if ftErr := i.ftInit(); ftErr != nil {
log.Errorf("can't init ft: %v", ftErr)
}
ch, err := i.anytype.SubscribeForNewRecords()
if err != nil {
return
}
i.quitWG.Add(2)
go i.detailsLoop(ch)
go i.ftLoop()
return
}
func (i *indexer) detailsLoop(ch chan core.SmartblockRecordWithThreadID) {
batch := mb.New(0)
defer batch.Close()
@ -302,7 +313,7 @@ func (i *indexer) cleanup() {
log.Infof("indexer cleanup: removed %d from %d", removed, count)
}
func (i *indexer) Close() {
func (i *indexer) Close() error {
i.mu.Lock()
quit := i.quit
i.mu.Unlock()
@ -314,6 +325,7 @@ func (i *indexer) Close() {
i.quit = nil
i.mu.Unlock()
}
return nil
}
func (i *indexer) SetDetail(id string, key string, val *types.Value) error {

View file

@ -4,6 +4,7 @@ import (
"testing"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/indexer"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
@ -81,9 +82,12 @@ func TestNewIndexer(t *testing.T) {
func newFixture(t *testing.T) *fixture {
var err error
a := new(app.App)
fx := &fixture{
a: a,
ctrl: gomock.NewController(t),
}
fx.getSerach = mockIndexer.NewMockGetSearchInfo(fx.ctrl)
fx.anytype = testMock.NewMockService(fx.ctrl)
fx.objectStore = testMock.NewMockObjectStore(fx.ctrl)
@ -91,7 +95,13 @@ func newFixture(t *testing.T) *fixture {
fx.anytype.EXPECT().ObjectStore().Return(fx.objectStore).AnyTimes()
fx.ch = make(chan core.SmartblockRecordWithThreadID)
fx.anytype.EXPECT().SubscribeForNewRecords().Return(fx.ch, nil)
fx.Indexer, err = indexer.NewIndexer(fx.anytype, fx.getSerach)
fx.Indexer = indexer.New()
a.Register(fx.getSerach).
Register(fx.anytype).
Register(fx.objectStore).
Register(fx.Indexer)
err = a.Start()
require.NoError(t, err)
return fx
}
@ -103,8 +113,10 @@ type fixture struct {
objectStore *testMock.MockObjectStore
getSerach *mockIndexer.MockGetSearchInfo
ch chan core.SmartblockRecordWithThreadID
a *app.App
}
func (fx *fixture) tearDown() {
fx.a.Close()
fx.ctrl.Finish()
}

View file

@ -21,15 +21,17 @@ func (mw *Middleware) ImageGetBlob(req *pb.RpcIpfsImageGetBlobRequest) *pb.RpcIp
return m
}
if mw.Anytype == nil {
if mw.app == nil {
response(nil, pb.RpcIpfsImageGetBlobResponseError_NODE_NOT_STARTED, fmt.Errorf("anytype is nil"))
}
if !mw.Anytype.IsStarted() {
at := mw.app.MustComponent(core.CName).(core.Service)
if !at.IsStarted() {
response(nil, pb.RpcIpfsImageGetBlobResponseError_NODE_NOT_STARTED, fmt.Errorf("anytype node not started"))
}
image, err := mw.Anytype.ImageByHash(context.TODO(), req.GetHash())
image, err := at.ImageByHash(context.TODO(), req.GetHash())
if err != nil {
if err == core.ErrFileNotFound {
return response(nil, pb.RpcIpfsImageGetBlobResponseError_NOT_FOUND, err)

View file

@ -6,6 +6,7 @@ import (
"time"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/util/linkpreview"
"github.com/anytypeio/go-anytype-middleware/util/uri"
)
@ -22,7 +23,18 @@ func (mw *Middleware) LinkPreview(req *pb.RpcLinkPreviewRequest) *pb.RpcLinkPrev
}
}
data, err := mw.linkPreview.Fetch(ctx, url)
mw.m.RLock()
defer mw.m.RUnlock()
if mw.app == nil {
return &pb.RpcLinkPreviewResponse{
Error: &pb.RpcLinkPreviewResponseError{
Code: pb.RpcLinkPreviewResponseError_UNKNOWN_ERROR,
},
}
}
lp := mw.app.MustComponent(linkpreview.CName).(linkpreview.LinkPreview)
data, err := lp.Fetch(ctx, url)
if err != nil {
// trim the actual url from the error
errTrimmed := strings.Replace(err.Error(), url, "<url>", -1)

View file

@ -6,6 +6,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
coresb "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/database"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
@ -20,10 +21,15 @@ func (mw *Middleware) NavigationListObjects(req *pb.RpcNavigationListObjectsRequ
return m
}
mw.m.RLock()
defer mw.m.RUnlock()
if mw.Anytype == nil {
if mw.app == nil {
return response(pb.RpcNavigationListObjectsResponseError_BAD_INPUT, nil, fmt.Errorf("account must be started"))
}
at := mw.app.MustComponent(core.CName).(core.Service)
objectTypes := []coresb.SmartBlockType{
coresb.SmartBlockTypePage,
coresb.SmartBlockTypeProfilePage,
@ -38,7 +44,7 @@ func (mw *Middleware) NavigationListObjects(req *pb.RpcNavigationListObjectsRequ
coresb.SmartBlockTypeObjectType,
}
}
records, _, err := mw.Anytype.ObjectStore().QueryObjectInfo(database.Query{
records, _, err := at.ObjectStore().QueryObjectInfo(database.Query{
FullText: req.FullText,
Limit: int(req.Limit),
Offset: int(req.Offset),
@ -59,11 +65,15 @@ func (mw *Middleware) NavigationGetObjectInfoWithLinks(req *pb.RpcNavigationGetO
return m
}
mw.m.RLock()
defer mw.m.RUnlock()
if mw.Anytype == nil {
if mw.app == nil {
return response(pb.RpcNavigationGetObjectInfoWithLinksResponseError_BAD_INPUT, nil, fmt.Errorf("account must be started"))
}
at := mw.app.MustComponent(core.CName).(core.Service)
filter := func(Objects []*model.ObjectInfo) []*model.ObjectInfo {
var filtered []*model.ObjectInfo
for _, page := range Objects {
@ -76,7 +86,7 @@ func (mw *Middleware) NavigationGetObjectInfoWithLinks(req *pb.RpcNavigationGetO
return filtered
}
page, err := mw.Anytype.ObjectInfoWithLinks(req.ObjectId)
page, err := at.ObjectInfoWithLinks(req.ObjectId)
if err != nil {
return response(pb.RpcNavigationGetObjectInfoWithLinksResponseError_UNKNOWN_ERROR, nil, err)
}

View file

@ -6,6 +6,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/block"
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/database"
pbrelation "github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/relation"
"github.com/gogo/protobuf/types"
@ -42,11 +43,16 @@ func (mw *Middleware) ObjectSearch(req *pb.RpcObjectSearchRequest) *pb.RpcObject
return m
}
if mw.Anytype == nil {
mw.m.RLock()
defer mw.m.RUnlock()
if mw.app == nil {
return response(pb.RpcObjectSearchResponseError_BAD_INPUT, nil, fmt.Errorf("account must be started"))
}
records, _, err := mw.Anytype.ObjectStore().Query(nil, database.Query{
at := mw.app.MustComponent(core.CName).(core.Service)
records, _, err := at.ObjectStore().Query(nil, database.Query{
Filters: req.Filters,
Sorts: req.Sorts,
Offset: int(req.Offset),

View file

@ -9,6 +9,7 @@ import (
"github.com/anytypeio/go-anytype-middleware/core/block/editor/state"
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/bundle"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
pbrelation "github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/relation"
"github.com/anytypeio/go-anytype-middleware/util/pbtypes"
@ -226,7 +227,16 @@ func (mw *Middleware) ObjectTypeList(_ *pb.RpcObjectTypeListRequest) *pb.RpcObje
return response(pb.RpcObjectTypeListResponseError_UNKNOWN_ERROR, nil, err)
}
threadIds, err := mw.Anytype.ThreadService().ListThreadIdsByType(smartblock.SmartBlockTypeObjectType)
mw.m.RLock()
defer mw.m.RUnlock()
if mw.app == nil {
return response(pb.RpcObjectTypeListResponseError_BAD_INPUT, nil, fmt.Errorf("account must be started"))
}
at := mw.app.MustComponent(core.CName).(core.Service)
threadIds, err := at.ThreadService().ListThreadIdsByType(smartblock.SmartBlockTypeObjectType)
if err != nil {
return response(pb.RpcObjectTypeListResponseError_UNKNOWN_ERROR, nil, err)
}

View file

@ -5,6 +5,8 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/core/event"
"github.com/anytypeio/go-anytype-middleware/pb"
cafepb "github.com/anytypeio/go-anytype-middleware/pkg/lib/cafe/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
@ -13,6 +15,7 @@ import (
"github.com/dgtony/collections/hashset"
"github.com/dgtony/collections/queue"
ct "github.com/dgtony/collections/time"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/textileio/go-threads/core/net"
"github.com/textileio/go-threads/core/thread"
)
@ -20,11 +23,16 @@ import (
var log = logging.Logger("anytype-mw-status")
const (
CName = "status"
threadStatusUpdatePeriod = 5 * time.Second
threadStatusEventBatchPeriod = 2 * time.Second
profileInformationLifetime = 30 * time.Second
cafeLastPullTimeout = 10 * time.Minute
// TODO: move to global config component
cafePeerId = "12D3KooWKwPC165PptjnzYzGrEs7NSjsF5vvMmxmuqpA2VfaBbLw"
// truncate device names and account IDs to last symbols
maxNameLength = 8
)
@ -40,8 +48,7 @@ type Service interface {
Unwatch(thread.ID)
UpdateTimeline(thread.ID, []LogTime)
Start() error
Stop()
app.ComponentRunnable
}
var _ Service = (*service)(nil)
@ -68,28 +75,29 @@ type service struct {
mu sync.Mutex
}
func NewService(
ts net.SyncInfo,
fs pin.FilePinService,
profile core.ProfileInfo,
emitter func(event *pb.Event),
cafe string,
device string,
) *service {
return &service{
tInfo: ts,
fInfo: fs,
profile: profile,
emitter: emitter,
cafeID: cafe,
ownDeviceID: device,
watchers: make(map[thread.ID]func()),
threads: make(map[thread.ID]*threadStatus),
devThreads: make(map[string]hashset.HashSet),
devAccount: make(map[string]string),
connMap: make(map[string]bool),
tsTrigger: queue.NewBulkQueue(threadStatusEventBatchPeriod, 5, 2),
}
func New() Service {
return new(service)
}
func (s *service) Init(a *app.App) (err error) {
s.watchers = make(map[thread.ID]func())
s.threads = make(map[thread.ID]*threadStatus)
s.devThreads = make(map[string]hashset.HashSet)
s.devAccount = make(map[string]string)
s.connMap = make(map[string]bool)
s.tsTrigger = queue.NewBulkQueue(threadStatusEventBatchPeriod, 5, 2)
anytype := a.MustComponent(core.CName).(core.Service)
s.profile = anytype
s.emitter = a.MustComponent(event.CName).(event.Sender).Send
cafePid, _ := peer.Decode(cafePeerId)
s.cafeID = cafePid.String()
return
}
func (s *service) Name() string {
return CName
}
func (s *service) Watch(tid thread.ID, fList func() []string) bool {
@ -194,7 +202,12 @@ func (s *service) UpdateTimeline(tid thread.ID, timeline []LogTime) {
}
}
func (s *service) Start() error {
func (s *service) Run() error {
anytype := s.profile.(core.Service)
s.ownDeviceID = anytype.Device()
s.tInfo = anytype.SyncStatus()
s.fInfo = anytype.FileStatus()
if err := s.startConnectivityTracking(); err != nil {
return err
}
@ -202,7 +215,7 @@ func (s *service) Start() error {
return nil
}
func (s *service) Stop() {
func (s *service) Close() error {
s.tsTrigger.Stop()
s.mu.Lock()
@ -214,6 +227,7 @@ func (s *service) Stop() {
delete(s.watchers, tid)
stop()
}
return nil
}
func (s *service) startConnectivityTracking() error {

2
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/anytypeio/go-slip10 v0.0.0-20200330112030-a352ca8495e4
github.com/anytypeio/go-slip21 v0.0.0-20200218204727-e2e51e20ab51
github.com/blevesearch/bleve v1.0.14
github.com/cheggaaa/go-exit v1.0.5 // indirect
github.com/cheggaaa/mb v1.0.2
github.com/dave/jennifer v1.4.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
@ -58,6 +59,7 @@ require (
github.com/multiformats/go-multihash v0.0.14
github.com/otiai10/opengraph v1.1.3
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.7.0
github.com/textileio/go-threads v1.0.2-0.20201217154614-3a79caa4def7
github.com/tyler-smith/go-bip39 v1.0.1-0.20190808214741-c55f737395bc

2
go.sum
View file

@ -105,6 +105,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cheggaaa/go-exit v1.0.5 h1:WYbi84ckDAsrU1LwFWPufHEh/nHau5JwPp9KZ5CDhKQ=
github.com/cheggaaa/go-exit v1.0.5/go.mod h1:fINMUoc/qfXnKwsx5AjxoQMDdRC9C/Dus486LDEp1ro=
github.com/cheggaaa/mb v1.0.2 h1:YZO20cG1uCyIsBxxZyo9fvaqyVlCD94VQhnjmjcOaW4=
github.com/cheggaaa/mb v1.0.2/go.mod h1:GLKG3DLryeF3F4iC+5b5mSjDq5o7skhK2qGWEOzF6g8=
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=

View file

@ -9,6 +9,7 @@ import (
"sync"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/cafe"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core/threads"
@ -44,6 +45,8 @@ fee6e180af8fc354d321fde5c84cab22138f9c62fec0d1bc0e99f4439968b02c`
)
const (
CName = "anytype"
DefaultWebGatewaySnapshotURI = "/%s/snapshotId/%s#key=%s"
pullInterval = 3 * time.Minute
@ -105,6 +108,8 @@ type Service interface {
SubscribeForNewRecords() (ch chan SmartblockRecordWithThreadID, err error)
ProfileInfo
app.ComponentRunnable
}
var _ Service = (*Anytype)(nil)
@ -167,6 +172,18 @@ func New(options ...ServiceOption) (*Anytype, error) {
return a, nil
}
func (a *Anytype) Init(_ *app.App) (err error) {
return
}
func (a *Anytype) Name() string {
return CName
}
func (a *Anytype) Run() (err error) {
return a.Start()
}
func (a *Anytype) Account() string {
if a.opts.Account == nil {
return ""
@ -377,6 +394,10 @@ func (a *Anytype) InitPredefinedBlocks(ctx context.Context, accountSelect bool)
return nil
}
func (a *Anytype) Close() (err error) {
return a.Stop()
}
func (a *Anytype) Stop() error {
fmt.Printf("stopping the library...\n")
defer fmt.Println("library has been successfully stopped")

View file

@ -1,6 +1,7 @@
package smartblock
import (
"github.com/anytypeio/go-anytype-middleware/pb"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
@ -95,3 +96,39 @@ func uvarint(buf string) (uint64, int) {
}
return 0, 0
}
func SmartBlockTypeToProto(t SmartBlockType) pb.SmartBlockType {
switch t {
case SmartBlockTypePage:
return pb.SmartBlockType_Page
case SmartBlockTypeArchive:
return pb.SmartBlockType_Archive
case SmartBlockTypeHome:
return pb.SmartBlockType_Home
case SmartBlockTypeProfilePage:
return pb.SmartBlockType_ProfilePage
case SmartBlockTypeSet:
return pb.SmartBlockType_Set
case SmartBlockTypeObjectType:
return pb.SmartBlockType_ObjectType
}
return 0
}
func SmartBlockTypeToCore(t pb.SmartBlockType) SmartBlockType {
switch t {
case pb.SmartBlockType_Page:
return SmartBlockTypePage
case pb.SmartBlockType_Archive:
return SmartBlockTypeArchive
case pb.SmartBlockType_Home:
return SmartBlockTypeHome
case pb.SmartBlockType_ProfilePage:
return SmartBlockTypeProfilePage
case pb.SmartBlockType_Set:
return SmartBlockTypeSet
case pb.SmartBlockType_ObjectType:
return SmartBlockTypeObjectType
}
return 0
}

View file

@ -10,21 +10,31 @@ import (
"strings"
"time"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/core"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/logging"
)
const CName = "gateway"
const defaultPort = 47800
var log = logging.Logger("anytype-gateway")
// Host is the instance used by the daemon
var Host *Gateway
func New() Gateway {
return new(gateway)
}
// Gateway is a HTTP API for getting files and links from IPFS
type Gateway struct {
type Gateway interface {
Addr() string
app.ComponentRunnable
}
type gateway struct {
Node core.Service
server *http.Server
addr string
}
func getRandomPort() (int, error) {
@ -56,15 +66,24 @@ func GatewayAddr() string {
return fmt.Sprintf("127.0.0.1:%d", port)
}
// Start creates a gateway server
func (g *Gateway) Start(addr string) error {
func (g *gateway) Init(a *app.App) (err error) {
g.Node = a.MustComponent(core.CName).(core.Service)
g.addr = GatewayAddr()
return nil
}
func (g *gateway) Name() string {
return CName
}
func (g *gateway) Run() error {
if g.server != nil {
return fmt.Errorf("gateway already started")
}
handler := http.NewServeMux()
g.server = &http.Server{
Addr: addr,
Addr: g.addr,
Handler: handler,
}
@ -72,7 +91,7 @@ func (g *Gateway) Start(addr string) error {
handler.HandleFunc("/image/", g.imageHandler)
// check port first
listener, err := net.Listen("tcp", addr)
listener, err := net.Listen("tcp", g.addr)
if err != nil {
// todo: choose next available port
return err
@ -108,16 +127,16 @@ func (g *Gateway) Start(addr string) error {
return nil
}
// Stop stops the gateway
func (g *Gateway) Stop() error {
// Close stops the gateway
func (g *gateway) Close() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
return g.server.Shutdown(ctx)
}
// Addr returns the gateway's address
func (g *Gateway) Addr() string {
return g.server.Addr
func (g *gateway) Addr() string {
return g.addr
}
func enableCors(w http.ResponseWriter) {
@ -126,7 +145,7 @@ func enableCors(w http.ResponseWriter) {
}
// fileHandler gets file meta from the DB, gets the corresponding data from the IPFS and decrypts it
func (g *Gateway) fileHandler(w http.ResponseWriter, r *http.Request) {
func (g *gateway) fileHandler(w http.ResponseWriter, r *http.Request) {
fileHash := r.URL.Path[len("/file/"):]
enableCors(w)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
@ -157,7 +176,7 @@ func (g *Gateway) fileHandler(w http.ResponseWriter, r *http.Request) {
}
// fileHandler gets file meta from the DB, gets the corresponding data from the IPFS and decrypts it
func (g *Gateway) imageHandler(w http.ResponseWriter, r *http.Request) {
func (g *gateway) imageHandler(w http.ResponseWriter, r *http.Request) {
urlParts := strings.Split(r.URL.Path, "/")
imageHash := urlParts[2]
query := r.URL.Query()

View file

@ -3,6 +3,7 @@ package linkpreview
import (
"context"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
"github.com/hashicorp/golang-lru"
)
@ -12,11 +13,7 @@ const (
)
func NewWithCache() LinkPreview {
lruCache, _ := lru.New(maxCacheEntries)
return &cache{
lp: New(),
cache: lruCache,
}
return &cache{}
}
type cache struct {
@ -24,6 +21,16 @@ type cache struct {
cache *lru.Cache
}
func (c *cache) Init(_ *app.App) (err error) {
c.lp = New()
c.cache, _ = lru.New(maxCacheEntries)
return
}
func (c *cache) Name() string {
return CName
}
func (c *cache) Fetch(ctx context.Context, url string) (lp model.LinkPreview, err error) {
if res, ok := c.cache.Get(url); ok {
return res.(model.LinkPreview), nil

View file

@ -9,6 +9,7 @@ import (
"strings"
"unicode/utf8"
"github.com/anytypeio/go-anytype-middleware/app"
"github.com/anytypeio/go-anytype-middleware/util/uri"
"github.com/anytypeio/go-anytype-middleware/pkg/lib/pb/model"
@ -17,8 +18,10 @@ import (
"github.com/otiai10/opengraph"
)
const CName = "linkpreview"
func New() LinkPreview {
return &linkPreview{bmPolicy: bluemonday.NewPolicy().AddSpaceWhenStrippingTag(true)}
return &linkPreview{}
}
const (
@ -29,12 +32,22 @@ const (
type LinkPreview interface {
Fetch(ctx context.Context, url string) (model.LinkPreview, error)
app.Component
}
type linkPreview struct {
bmPolicy *bluemonday.Policy
}
func (l *linkPreview) Init(_ *app.App) (err error) {
l.bmPolicy = bluemonday.NewPolicy().AddSpaceWhenStrippingTag(true)
return
}
func (l *linkPreview) Name() (name string) {
return CName
}
func (l *linkPreview) Fetch(ctx context.Context, fetchUrl string) (model.LinkPreview, error) {
rt := &proxyRoundTripper{RoundTripper: http.DefaultTransport}
client := &http.Client{Transport: rt}