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

GO-2275 Merge branch 'main' of github.com:anyproto/anytype-heart into go-2275-change-client-api-for-storage-limits

This commit is contained in:
Sergey 2023-11-01 15:56:02 +05:00
commit 4e2906efa6
No known key found for this signature in database
GPG key ID: 3B6BEF79160221C6
32 changed files with 1135 additions and 937 deletions

View file

@ -3,6 +3,8 @@ package core
import (
"context"
"github.com/anyproto/any-sync/net"
"github.com/anyproto/anytype-heart/core/application"
"github.com/anyproto/anytype-heart/pb"
)
@ -99,6 +101,7 @@ func (mw *Middleware) AccountDelete(cctx context.Context, req *pb.RpcAccountDele
status, err := mw.applicationService.AccountDelete(cctx, req)
code := mapErrorCode(err,
errToCode(application.ErrAccountIsAlreadyDeleted, pb.RpcAccountDeleteResponseError_ACCOUNT_IS_ALREADY_DELETED),
errToCode(net.ErrUnableToConnect, pb.RpcAccountDeleteResponseError_UNABLE_TO_CONNECT),
)
return &pb.RpcAccountDeleteResponse{
Status: status,
@ -113,6 +116,7 @@ func (mw *Middleware) AccountRevertDeletion(cctx context.Context, req *pb.RpcAcc
status, err := mw.applicationService.AccountRevertDeletion(cctx)
code := mapErrorCode(err,
errToCode(application.ErrAccountIsActive, pb.RpcAccountRevertDeletionResponseError_ACCOUNT_IS_ACTIVE),
errToCode(net.ErrUnableToConnect, pb.RpcAccountRevertDeletionResponseError_UNABLE_TO_CONNECT),
)
return &pb.RpcAccountRevertDeletionResponse{
Status: status,

View file

@ -35,7 +35,6 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
"github.com/anyproto/anytype-heart/pkg/lib/database"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/addr"
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
@ -580,17 +579,6 @@ func (sb *smartBlock) navigationalLinks(s *state.State) []string {
}
// handle corner cases first for specific formats
if rel.Format == model.RelationFormat_date &&
!lo.Contains(bundle.LocalRelationsKeys, rel.Key) &&
!lo.Contains(bundle.DerivedRelationsKeys, rel.Key) {
relInt := pbtypes.GetInt64(det, rel.Key)
if relInt > 0 {
t := time.Unix(relInt, 0)
t = t.In(time.Local)
ids = append(ids, addr.TimeToID(t))
}
continue
}
if rel.Format != model.RelationFormat_object {
continue

View file

@ -66,7 +66,7 @@ func (t *Template) GetNewPageState(name string) (st *state.State, err error) {
}
st.RemoveDetail(bundle.RelationKeyTargetObjectType.String(), bundle.RelationKeyTemplateIsBundled.String())
st.SetDetail(bundle.RelationKeySourceObject.String(), pbtypes.String(t.Id()))
st.SetDetailAndBundledRelation(bundle.RelationKeySourceObject, pbtypes.String(t.Id()))
// clean-up local details from the template state
st.SetLocalDetails(nil)

View file

@ -101,7 +101,7 @@ func (e *export) Export(ctx context.Context, req pb.RpcObjectListExportRequest)
}
defer queue.Stop(err)
docs, err := e.docsForExport(req.SpaceId, req.ObjectIds, req.IncludeNested, req.IncludeArchived, isProtobufExport(req.Format))
docs, err := e.docsForExport(req.SpaceId, req.ObjectIds, req.IncludeNested, req.IncludeArchived, isAnyblockExport(req.Format))
if err != nil {
return
}
@ -183,8 +183,8 @@ func (e *export) renameZipArchive(req pb.RpcObjectListExportRequest, wr writer,
return zipName, succeed, nil
}
func isProtobufExport(format pb.RpcObjectListExportFormat) bool {
return format == pb.RpcObjectListExport_Protobuf
func isAnyblockExport(format pb.RpcObjectListExportFormat) bool {
return format == pb.RpcObjectListExport_Protobuf || format == pb.RpcObjectListExport_JSON
}
func (e *export) docsForExport(spaceID string, reqIds []string, includeNested bool, includeArchived bool, isProtobuf bool) (docs map[string]*types.Struct, err error) {
@ -233,7 +233,17 @@ func (e *export) getObjectsByIDs(spaceID string, reqIds []string, includeNested
e.getNested(spaceID, id, docs)
}
}
return docs, err
derivedObjects, err := e.getRelatedDerivedObjects(res)
if err != nil {
return nil, err
}
for _, do := range derivedObjects {
id := pbtypes.GetString(do.Details, bundle.RelationKeyId.String())
docs[id] = do.Details
}
return docs, nil
}
func (e *export) getNested(spaceID string, id string, docs map[string]*types.Struct) {
@ -535,3 +545,153 @@ func (e *export) cleanupFile(wr writer) {
wr.Close()
os.Remove(wr.Path())
}
func (e *export) getRelatedDerivedObjects(objects []database.Record) ([]database.Record, error) {
var (
derivedObjects []database.Record
err error
)
for _, object := range objects {
derivedObjects, err = e.processObject(object, derivedObjects)
if err != nil {
return nil, err
}
}
return derivedObjects, nil
}
func (e *export) processObject(object database.Record, derivedObjects []database.Record) ([]database.Record, error) {
details := object.Details
for key, value := range details.Fields {
relation, err := e.getRelation(key)
if err != nil {
return nil, err
}
if relation != nil {
derivedObjects, err = e.addRelationAndOptions(relation, value, derivedObjects)
if err != nil {
return nil, err
}
}
}
objectTypeDetails, err := e.objectStore.GetDetails(pbtypes.GetString(details, bundle.RelationKeyType.String()))
if err != nil {
return nil, err
}
derivedObjects = append(derivedObjects, database.Record{Details: objectTypeDetails.Details})
return derivedObjects, nil
}
func (e *export) getRelation(key string) (*database.Record, error) {
uniqueKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeRelation, key)
if err != nil {
return nil, err
}
relation, _, err := e.objectStore.Query(database.Query{
Filters: []*model.BlockContentDataviewFilter{
{
RelationKey: bundle.RelationKeyUniqueKey.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(uniqueKey.Marshal()),
},
{
RelationKey: bundle.RelationKeyIsArchived.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(false),
},
{
RelationKey: bundle.RelationKeyIsDeleted.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(false),
},
},
})
if err != nil {
return nil, err
}
if len(relation) == 0 {
return nil, nil
}
return &relation[0], nil
}
func (e *export) addRelationAndOptions(relation *database.Record, value *types.Value, derivedObjects []database.Record) ([]database.Record, error) {
derivedObjects = e.addRelation(relation, derivedObjects)
format := pbtypes.GetInt64(relation.Details, bundle.RelationKeyRelationFormat.String())
if format == int64(model.RelationFormat_tag) || format == int64(model.RelationFormat_status) {
relationOptions, err := e.getRelationOptions(value)
if err != nil {
return nil, err
}
derivedObjects = append(derivedObjects, relationOptions...)
}
return derivedObjects, nil
}
func (e *export) addRelation(relation *database.Record, derivedObjects []database.Record) []database.Record {
if relationKey := relation.Get(bundle.RelationKeyRelationKey.String()); relationKey != nil {
if !bundle.HasRelation(relationKey.GetStringValue()) {
derivedObjects = append(derivedObjects, *relation)
}
}
return derivedObjects
}
func (e *export) getRelationOptions(relationOptions *types.Value) ([]database.Record, error) {
var filter *model.BlockContentDataviewFilter
if relationOptions.GetStringValue() != "" {
filter = e.getFilterForStringOption(relationOptions, filter)
}
if relationOptions.GetListValue() != nil && len(relationOptions.GetListValue().Values) != 0 {
filter = e.getFilterForOptionsList(relationOptions, filter)
}
if filter == nil {
return nil, nil
}
relationOptionsDetails, _, err := e.objectStore.Query(database.Query{
Filters: []*model.BlockContentDataviewFilter{
filter,
{
RelationKey: bundle.RelationKeyIsArchived.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(false),
},
{
RelationKey: bundle.RelationKeyIsDeleted.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(false),
},
},
})
if err != nil {
return nil, err
}
return relationOptionsDetails, nil
}
func (e *export) getFilterForOptionsList(relationOptions *types.Value, filter *model.BlockContentDataviewFilter) *model.BlockContentDataviewFilter {
ids := make([]string, 0, len(relationOptions.GetListValue().Values))
for _, id := range relationOptions.GetListValue().Values {
ids = append(ids, id.GetStringValue())
}
filter = &model.BlockContentDataviewFilter{
RelationKey: bundle.RelationKeyId.String(),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.StringList(ids),
}
return filter
}
func (e *export) getFilterForStringOption(value *types.Value, filter *model.BlockContentDataviewFilter) *model.BlockContentDataviewFilter {
id := value.GetStringValue()
filter = &model.BlockContentDataviewFilter{
RelationKey: bundle.RelationKeyId.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(id),
}
return filter
}

View file

@ -408,7 +408,7 @@ func (r *Renderer) renderText(_ util.BufWriter,
r.AddTextToBuffer(string(segment.Value(source)))
if n.HardLineBreak() {
r.ForceCloseTextBlock()
r.CloseTextBlock(model.BlockContentText_Paragraph)
} else if n.SoftLineBreak() {
r.AddTextToBuffer("\n")

View file

@ -243,8 +243,8 @@ func (p *Pb) makeSnapshot(name, profileID, path string, file io.ReadCloser, isMi
if errGS != nil {
return nil, errGS
}
if snapshot == nil {
return nil, nil
if valid := p.isSnapshotValid(snapshot); !valid {
return nil, fmt.Errorf("snapshot is not valid: %s", name)
}
id := uuid.New().String()
id, err := p.normalizeSnapshot(snapshot, id, profileID, isMigration)
@ -541,3 +541,7 @@ func (p *Pb) filterObjects(objectTypesToImport widgets.ImportWidgetFlags, object
}
return rootObjects
}
func (p *Pb) isSnapshotValid(snapshot *pb.SnapshotWithType) bool {
return !(snapshot == nil || snapshot.Snapshot == nil || snapshot.Snapshot.Data == nil)
}

View file

@ -184,10 +184,11 @@ func Test_GetSnapshotsSkipFileWithoutExtension(t *testing.T) {
}},
UpdateExistingObjects: false,
Type: 0,
Mode: 0,
Mode: 1,
}, process.NewProgress(pb.ModelProcess_Import))
assert.Nil(t, ce)
assert.NotNil(t, ce, 1)
assert.Contains(t, ce.Error().Error(), "snapshot is not valid: test")
assert.NotNil(t, res.Snapshots)
assert.Len(t, res.Snapshots, 2)

View file

@ -2,10 +2,12 @@ package objectcreator
import (
"context"
"errors"
"fmt"
"time"
"github.com/anyproto/any-sync/app"
"github.com/anyproto/any-sync/commonspace/spacestorage"
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"golang.org/x/exp/slices"
@ -88,7 +90,10 @@ func (s *service) createSmartBlockFromTemplate(ctx context.Context, space space.
var createState *state.State
if templateID != "" {
if createState, err = s.blockService.StateFromTemplate(templateID, pbtypes.GetString(details, bundle.RelationKeyName.String())); err != nil {
return
if !errors.Is(err, spacestorage.ErrTreeStorageAlreadyDeleted) {
return
}
createState = state.NewDoc("", nil).NewState()
}
} else {
createState = state.NewDoc("", nil).NewState()

View file

@ -37,17 +37,26 @@ func newSubObjectsAndProfileLinksMigration(space Space, identityObjectID string,
func (m *subObjectsAndProfileLinksMigration) replaceLinksInDetails(s *state.State) {
for _, rel := range s.GetRelationLinks() {
if m.canRelationContainObjectValues(rel.Format) {
ids := pbtypes.GetStringList(s.Details(), rel.Key)
changed := false
for i, oldId := range ids {
rawValue := s.Details().GetFields()[rel.Key]
if oldId := rawValue.GetStringValue(); oldId != "" {
newId := m.migrateId(oldId)
if oldId != newId {
ids[i] = newId
changed = true
s.SetDetail(rel.Key, pbtypes.String(newId))
}
} else if rawIds := rawValue.GetListValue(); rawIds != nil {
ids := pbtypes.ListValueToStrings(rawIds)
changed := false
for i, oldId := range ids {
newId := m.migrateId(oldId)
if oldId != newId {
ids[i] = newId
changed = true
}
}
if changed {
s.SetDetail(rel.Key, pbtypes.StringList(ids))
}
}
if changed {
s.SetDetail(rel.Key, pbtypes.StringList(ids))
}
}
}

View file

@ -118,7 +118,7 @@ func (f *fileSync) Run(ctx context.Context) (err error) {
return
}
go f.precacheSpaceStats()
go f.precacheNodeUsage()
f.loopCtx, f.loopCancel = context.WithCancel(context.Background())
go f.addLoop()
@ -126,21 +126,6 @@ func (f *fileSync) Run(ctx context.Context) (err error) {
return
}
func (f *fileSync) precacheSpaceStats() {
_, err := f.NodeUsage(context.Background())
if err != nil {
log.Error("can't init node usage cache", zap.Error(err))
// Don't confuse users with 0B limit in case of error, so set default 1GB limit
err = f.queue.setNodeUsage(NodeUsage{
AccountBytesLimit: 1024 * 1024 * 1024, // 1 GB
})
if err != nil {
log.Error("can't set default limits", zap.Error(err))
}
}
}
func (f *fileSync) Close(ctx context.Context) (err error) {
if f.loopCancel != nil {
f.loopCancel()

View file

@ -60,6 +60,33 @@ func (s FileStat) IsPinned() bool {
return s.UploadedChunksCount == s.TotalChunksCount
}
func (f *fileSync) precacheNodeUsage() {
_, ok, err := f.getCachedNodeUsage()
// Init cache with default limits
if !ok || err != nil {
err = f.queue.setNodeUsage(NodeUsage{
AccountBytesLimit: 1024 * 1024 * 1024, // 1 GB
})
if err != nil {
log.Error("can't set default limits", zap.Error(err))
}
}
// Load actual node usage
_, err = f.getAndUpdateNodeUsage(context.Background())
if err != nil {
log.Error("can't init node usage cache", zap.Error(err))
// Don't confuse users with 0B limit in case of error, so set default 1GB limit
err = f.queue.setNodeUsage(NodeUsage{
AccountBytesLimit: 1024 * 1024 * 1024, // 1 GB
})
if err != nil {
log.Error("can't set default limits", zap.Error(err))
}
}
}
func (s *fileSync) NodeUsage(ctx context.Context) (NodeUsage, error) {
usage, ok, err := s.getCachedNodeUsage()
if err != nil {

View file

@ -36,7 +36,7 @@ const (
// ForceIdxRebuildCounter erases localstore indexes and reindex all type of objects
// (no need to increase ForceObjectsReindexCounter & ForceFilesReindexCounter)
ForceIdxRebuildCounter int32 = 60
ForceIdxRebuildCounter int32 = 61
// ForceFulltextIndexCounter performs fulltext indexing for all type of objects (useful when we change fulltext config)
ForceFulltextIndexCounter int32 = 5

View file

@ -15504,6 +15504,7 @@ Middleware-to-front-end response, that can contain a NULL error or a non-NULL er
| UNKNOWN_ERROR | 1 | Any other errors |
| BAD_INPUT | 2 | |
| ACCOUNT_IS_ALREADY_DELETED | 101 | |
| UNABLE_TO_CONNECT | 102 | |
@ -15579,6 +15580,7 @@ Middleware-to-front-end response, that can contain a NULL error or a non-NULL er
| UNKNOWN_ERROR | 1 | Any other errors |
| BAD_INPUT | 2 | |
| ACCOUNT_IS_ACTIVE | 101 | |
| UNABLE_TO_CONNECT | 102 | |

4
go.mod
View file

@ -7,7 +7,7 @@ require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/VividCortex/ewma v1.2.0
github.com/adrium/goheif v0.0.0-20230113233934-ca402e77a786
github.com/anyproto/any-sync v0.3.5
github.com/anyproto/any-sync v0.3.6
github.com/anyproto/go-naturaldate/v2 v2.0.2-0.20230524105841-9829cfd13438
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
github.com/blevesearch/bleve/v2 v2.3.10
@ -77,7 +77,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/vektra/mockery/v2 v2.35.2
github.com/yuin/goldmark v1.5.6
github.com/yuin/goldmark v1.6.0
go.uber.org/mock v0.3.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.26.0

8
go.sum
View file

@ -82,8 +82,8 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-sync v0.3.5 h1:G7hqF2ww8oNs1C3Tve/k3B9PucaFU0UOkS4iopLYA1I=
github.com/anyproto/any-sync v0.3.5/go.mod h1:b5VBU4kw1df4ezTYZd9iPEVzPZcDfTGfjis6gUortQc=
github.com/anyproto/any-sync v0.3.6 h1:a8M9JMi9TEwskZI3ePYNrgmE/4se/ymrs+Q0SomXA7Q=
github.com/anyproto/any-sync v0.3.6/go.mod h1:b5VBU4kw1df4ezTYZd9iPEVzPZcDfTGfjis6gUortQc=
github.com/anyproto/go-chash v0.1.0 h1:I9meTPjXFRfXZHRJzjOHC/XF7Q5vzysKkiT/grsogXY=
github.com/anyproto/go-chash v0.1.0/go.mod h1:0UjNQi3PDazP0fINpFYu6VKhuna+W/V+1vpXHAfNgLY=
github.com/anyproto/go-gelf v0.0.0-20210418191311-774bd5b016e7 h1:SyEu5uxZ5nKHEJ6TPKQqjM+T00SYi0MW1VaLzqZtZ9E=
@ -1330,8 +1330,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.5/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA=
github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=

File diff suppressed because it is too large Load diff

View file

@ -351,6 +351,7 @@ message Rpc {
BAD_INPUT = 2;
ACCOUNT_IS_ALREADY_DELETED = 101;
UNABLE_TO_CONNECT = 102;
}
}
}
@ -374,6 +375,7 @@ message Rpc {
BAD_INPUT = 2;
ACCOUNT_IS_ACTIVE = 101;
UNABLE_TO_CONNECT = 102;
}
}
}

View file

@ -9,7 +9,7 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
)
const RelationChecksum = "fea7f1638ce0cf6eba87b597a8b819e136ff951c566a723120f6976840faff6b"
const RelationChecksum = "d9bac6d7e7ac3918a327e29c65c2587817ac04a02098b4440e337d93a7ee5038"
const (
RelationKeyTag domain.RelationKey = "tag"
RelationKeyCamera domain.RelationKey = "camera"
@ -1185,7 +1185,7 @@ var (
Id: "_brlinkedProjects",
Key: "linkedProjects",
Name: "Linked Projects",
ObjectTypes: []string{TypePrefix + "task", TypePrefix + "project"},
ObjectTypes: []string{TypePrefix + "project"},
ReadOnly: false,
ReadOnlyRelation: true,
Scope: model.Relation_type,

View file

@ -331,7 +331,6 @@
"readonly": false,
"source": "details",
"objectTypes": [
"task",
"project"
]
},

View file

@ -11,7 +11,7 @@ func (s *service) create(ctx context.Context, coreSpace *spacecore.AnySpace) (Sp
s.createdSpaces[coreSpace.Id()] = struct{}{}
s.mu.Unlock()
if err := s.techSpace.SpaceViewCreate(ctx, coreSpace.Id()); err != nil {
if err := s.techSpace.SpaceViewCreate(ctx, coreSpace.Id(), true); err != nil {
return nil, err
}

View file

@ -52,17 +52,21 @@ func (ls *loadingSpace) loadRetry(ctx context.Context) {
if ls.load(ctx) {
return
}
ticker := time.NewTicker(ls.retryTimeout)
timeout := 1 * time.Second
for {
select {
case <-ctx.Done():
ls.loadErr = ctx.Err()
return
case <-ticker.C:
case <-time.After(timeout):
if ls.load(ctx) {
return
}
}
timeout *= 2
if timeout > ls.retryTimeout {
timeout = ls.retryTimeout
}
}
}

View file

@ -51,7 +51,7 @@ func (s *service) loadPersonalSpace(ctx context.Context) (err error) {
err = s.startLoad(ctx, s.personalSpaceID)
// This could happen for old accounts
if errors.Is(err, ErrSpaceNotExists) {
err = s.techSpace.SpaceViewCreate(ctx, s.personalSpaceID)
err = s.techSpace.SpaceViewCreate(ctx, s.personalSpaceID, false)
if err != nil {
return err
}

View file

@ -34,7 +34,7 @@ type TechSpace interface {
Close(ctx context.Context) (err error)
TechSpaceId() string
SpaceViewCreate(ctx context.Context, spaceId string) (err error)
SpaceViewCreate(ctx context.Context, spaceId string, force bool) (err error)
SpaceViewExists(ctx context.Context, spaceId string) (exists bool, err error)
SetInfo(ctx context.Context, info spaceinfo.SpaceInfo) (err error)
SpaceViewSetData(ctx context.Context, spaceId string, details *types.Struct) (err error)
@ -86,11 +86,9 @@ func (s *techSpace) wakeUpViews() {
default:
}
s.mu.Lock()
if _, err := s.objectCache.GetObject(s.ctx, id); err != nil {
log.Warn("wakeUp views: get object error", zap.String("objectId", id), zap.Error(err))
}
s.mu.Unlock()
}
s.techCore.TreeSyncer().StartSync()
return
@ -108,9 +106,12 @@ func (s *techSpace) SetInfo(ctx context.Context, info spaceinfo.SpaceInfo) (err
})
}
func (s *techSpace) SpaceViewCreate(ctx context.Context, spaceId string) (err error) {
func (s *techSpace) SpaceViewCreate(ctx context.Context, spaceId string, force bool) (err error) {
s.mu.Lock()
defer s.mu.Unlock()
if force {
return s.spaceViewCreate(ctx, spaceId)
}
viewId, err := s.getViewId(ctx, spaceId)
if err != nil {

View file

@ -66,7 +66,7 @@ func TestTechSpace_SpaceViewCreate(t *testing.T) {
fx.objectCache.EXPECT().GetObject(ctx, viewId).Return(nil, fmt.Errorf("not found"))
fx.objectCache.EXPECT().DeriveTreeObject(ctx, mock.Anything).Return(view, nil)
require.NoError(t, fx.SpaceViewCreate(ctx, spaceId))
require.NoError(t, fx.SpaceViewCreate(ctx, spaceId, false))
})
t.Run("err spaceView exists", func(t *testing.T) {
@ -76,7 +76,7 @@ func TestTechSpace_SpaceViewCreate(t *testing.T) {
fx.expectDeriveTreePayload(viewId)
fx.objectCache.EXPECT().GetObject(ctx, viewId).Return(view, nil)
assert.EqualError(t, fx.SpaceViewCreate(ctx, spaceId), ErrSpaceViewExists.Error())
assert.EqualError(t, fx.SpaceViewCreate(ctx, spaceId, false), ErrSpaceViewExists.Error())
})
}

View file

@ -159,10 +159,6 @@ func (b *builtinObjects) CreateObjectsForUseCase(
spaceID string,
useCase pb.RpcObjectImportUseCaseRequestUseCase,
) (code pb.RpcObjectImportUseCaseResponseErrorCode, err error) {
if useCase == pb.RpcObjectImportUseCaseRequest_EMPTY {
return pb.RpcObjectImportUseCaseResponseError_NULL, err
}
start := time.Now()
archive, found := archives[useCase]

Binary file not shown.

Binary file not shown.

View file

@ -212,20 +212,24 @@ func GetStringListValue(v *types.Value) []string {
if v == nil {
return nil
}
var stringsSlice []string
if list, ok := v.Kind.(*types.Value_ListValue); ok {
if list.ListValue == nil {
return nil
}
for _, v := range list.ListValue.Values {
if _, ok := v.GetKind().(*types.Value_StringValue); ok {
stringsSlice = append(stringsSlice, v.GetStringValue())
}
}
return ListValueToStrings(list.ListValue)
} else if val, ok := v.Kind.(*types.Value_StringValue); ok && val.StringValue != "" {
return []string{val.StringValue}
}
return nil
}
func ListValueToStrings(list *types.ListValue) []string {
if list == nil {
return nil
}
stringsSlice := make([]string, 0, len(list.Values))
for _, v := range list.Values {
if _, ok := v.GetKind().(*types.Value_StringValue); ok {
stringsSlice = append(stringsSlice, v.GetStringValue())
}
}
return stringsSlice
}