154 lines
3.4 KiB
Go
154 lines
3.4 KiB
Go
//go:generate mockgen -destination mock_deletionstate/mock_deletionstate.go github.com/anytypeio/any-sync/commonspace/settings/deletionstate DeletionState
|
|
package deletionstate
|
|
|
|
import (
|
|
"github.com/anytypeio/any-sync/commonspace/spacestorage"
|
|
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
|
|
"sync"
|
|
)
|
|
|
|
type StateUpdateObserver func(ids []string)
|
|
|
|
type DeletionState interface {
|
|
AddObserver(observer StateUpdateObserver)
|
|
Add(ids []string) (err error)
|
|
GetQueued() (ids []string)
|
|
Delete(id string) (err error)
|
|
Exists(id string) bool
|
|
FilterJoin(ids ...[]string) (filtered []string)
|
|
CreateDeleteChange(id string, isSnapshot bool) (res []byte, err error)
|
|
}
|
|
|
|
type deletionState struct {
|
|
sync.RWMutex
|
|
queued map[string]struct{}
|
|
deleted map[string]struct{}
|
|
stateUpdateObservers []StateUpdateObserver
|
|
storage spacestorage.SpaceStorage
|
|
}
|
|
|
|
func NewDeletionState(storage spacestorage.SpaceStorage) DeletionState {
|
|
return &deletionState{
|
|
queued: map[string]struct{}{},
|
|
deleted: map[string]struct{}{},
|
|
storage: storage,
|
|
}
|
|
}
|
|
|
|
func (st *deletionState) AddObserver(observer StateUpdateObserver) {
|
|
st.Lock()
|
|
defer st.Unlock()
|
|
st.stateUpdateObservers = append(st.stateUpdateObservers, observer)
|
|
}
|
|
|
|
func (st *deletionState) Add(ids []string) (err error) {
|
|
st.Lock()
|
|
defer func() {
|
|
st.Unlock()
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, ob := range st.stateUpdateObservers {
|
|
ob(ids)
|
|
}
|
|
}()
|
|
|
|
for _, id := range ids {
|
|
if _, exists := st.deleted[id]; exists {
|
|
continue
|
|
}
|
|
if _, exists := st.queued[id]; exists {
|
|
continue
|
|
}
|
|
|
|
var status string
|
|
status, err = st.storage.TreeDeletedStatus(id)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
switch status {
|
|
case spacestorage.TreeDeletedStatusQueued:
|
|
st.queued[id] = struct{}{}
|
|
case spacestorage.TreeDeletedStatusDeleted:
|
|
st.deleted[id] = struct{}{}
|
|
default:
|
|
st.queued[id] = struct{}{}
|
|
err = st.storage.SetTreeDeletedStatus(id, spacestorage.TreeDeletedStatusQueued)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (st *deletionState) GetQueued() (ids []string) {
|
|
st.RLock()
|
|
defer st.RUnlock()
|
|
ids = make([]string, 0, len(st.queued))
|
|
for id := range st.queued {
|
|
ids = append(ids, id)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (st *deletionState) Delete(id string) (err error) {
|
|
st.Lock()
|
|
defer st.Unlock()
|
|
delete(st.queued, id)
|
|
st.deleted[id] = struct{}{}
|
|
err = st.storage.SetTreeDeletedStatus(id, spacestorage.TreeDeletedStatusDeleted)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (st *deletionState) Exists(id string) bool {
|
|
st.RLock()
|
|
defer st.RUnlock()
|
|
return st.exists(id)
|
|
}
|
|
|
|
func (st *deletionState) FilterJoin(ids ...[]string) (filtered []string) {
|
|
st.RLock()
|
|
defer st.RUnlock()
|
|
filter := func(ids []string) {
|
|
for _, id := range ids {
|
|
if !st.exists(id) {
|
|
filtered = append(filtered, id)
|
|
}
|
|
}
|
|
}
|
|
for _, arr := range ids {
|
|
filter(arr)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (st *deletionState) CreateDeleteChange(id string, isSnapshot bool) (res []byte, err error) {
|
|
content := &spacesyncproto.SpaceSettingsContent_ObjectDelete{
|
|
ObjectDelete: &spacesyncproto.ObjectDelete{Id: id},
|
|
}
|
|
change := &spacesyncproto.SettingsData{
|
|
Content: []*spacesyncproto.SpaceSettingsContent{
|
|
{Value: content},
|
|
},
|
|
Snapshot: nil,
|
|
}
|
|
// TODO: add snapshot logic
|
|
res, err = change.Marshal()
|
|
return
|
|
}
|
|
|
|
func (st *deletionState) exists(id string) bool {
|
|
if _, exists := st.deleted[id]; exists {
|
|
return true
|
|
}
|
|
if _, exists := st.queued[id]; exists {
|
|
return true
|
|
}
|
|
return false
|
|
}
|