Skip to content

Commit 12aeaa3

Browse files
authored
Merge pull request #156 from anyproto/GO-5827-deletion-debug-handler
GO-5827 debug: http deleteion checker
2 parents 7e0d35c + da32dfa commit 12aeaa3

File tree

7 files changed

+136
-3
lines changed

7 files changed

+136
-3
lines changed

deletelog/deletelog.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ func (d *deleteLog) Name() (name string) {
5454

5555
func (d *deleteLog) Run(ctx context.Context) (err error) {
5656
if !d.disableTicker {
57-
d.ticker = periodicsync.NewPeriodicSync(60, time.Hour, d.checkLog, log)
57+
d.ticker = periodicsync.NewPeriodicSync(30, time.Hour*2, d.checkLog, log)
5858
d.ticker.Run()
5959
}
6060
return
6161
}
6262

6363
func (d *deleteLog) checkLog(ctx context.Context) (err error) {
64-
mu := d.redsync.NewMutex("_lock:deletion", redsync.WithExpiry(time.Hour))
64+
mu := d.redsync.NewMutex("_lock:deletion", redsync.WithExpiry(time.Hour*2))
6565
if err = mu.LockContext(ctx); err != nil {
6666
return
6767
}

index/check.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,44 @@ func (gc *groupContent) Check(cidRefs map[string]uint64, sumSize uint64) (checkR
362362
}
363363
return
364364
}
365+
366+
func (ri *redisIndex) CheckDeletedSpaces(
367+
ctx context.Context,
368+
key Key,
369+
resolve func(spaceIds []string) (deletedIds []string, err error),
370+
doFix bool,
371+
) (toBeDeleted []string, err error) {
372+
gExists, gRelease, err := ri.AcquireKey(ctx, GroupKey(key))
373+
if err != nil {
374+
return
375+
}
376+
if !gExists {
377+
gRelease()
378+
return
379+
}
380+
gEntry, err := ri.getGroupEntry(ctx, key)
381+
if err != nil {
382+
gRelease()
383+
return
384+
}
385+
386+
deletedIds, err := resolve(gEntry.GetSpaceIds())
387+
if err != nil {
388+
gRelease()
389+
return
390+
}
391+
392+
gRelease()
393+
394+
if doFix {
395+
ctx = context.WithValue(ctx, ctxForceSpaceGet, true)
396+
for _, toDeleteSpaceId := range deletedIds {
397+
key := Key{GroupId: key.GroupId, SpaceId: toDeleteSpaceId}
398+
if _, err = ri.SpaceDelete(ctx, key); err != nil {
399+
return nil, err
400+
}
401+
_, _ = ri.MarkSpaceAsDeleted(ctx, key)
402+
}
403+
}
404+
return deletedIds, nil
405+
}

index/check_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,28 @@ func TestRedisIndex_Check(t *testing.T) {
8989
})
9090

9191
}
92+
93+
func TestRedisIndex_CheckDeletedSpaces(t *testing.T) {
94+
fx := newFixture(t)
95+
defer fx.Finish(t)
96+
bs := testutil.NewRandBlocks(3)
97+
fileId1 := testutil.NewRandCid().String()
98+
99+
require.NoError(t, fx.BlocksAdd(ctx, bs))
100+
key := newRandKey()
101+
cids, err := fx.CidEntriesByBlocks(ctx, bs[:2])
102+
require.NoError(t, err)
103+
require.NoError(t, fx.FileBind(ctx, key, fileId1, cids))
104+
cids.Release()
105+
106+
result, err := fx.CheckDeletedSpaces(ctx, key, func(spaceIds []string) (deletedIds []string, err error) {
107+
return spaceIds, nil
108+
}, true)
109+
require.NoError(t, err)
110+
require.Len(t, result, 1)
111+
assert.Equal(t, key.SpaceId, result[0])
112+
113+
info, err := fx.GroupInfo(ctx, key.GroupId)
114+
require.NoError(t, err)
115+
assert.Len(t, info.SpaceIds, 0)
116+
}

index/index.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ var (
3333
ErrSpaceIsDeleted = errors.New("space is deleted")
3434
)
3535

36+
type ctxKey int
37+
38+
const (
39+
ctxForceSpaceGet ctxKey = iota
40+
)
41+
3642
type Index interface {
3743
FileBind(ctx context.Context, key Key, fileId string, cidEntries *CidEntries) (err error)
3844
FileUnbind(ctx context.Context, kye Key, fileIds ...string) (err error)
@@ -62,6 +68,7 @@ type Index interface {
6268
Migrate(ctx context.Context, key Key) error
6369

6470
Check(ctx context.Context, key Key, doFix bool) (checkResults []CheckResult, err error)
71+
CheckDeletedSpaces(ctx context.Context, key Key, resolve func(spaceIds []string) (deletedIds []string, err error), doFix bool) (toBeDeleted []string, err error)
6572

6673
SpaceDelete(ctx context.Context, key Key) (ok bool, err error)
6774
MarkSpaceAsDeleted(ctx context.Context, key Key) (ok bool, err error)

index/loader.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ func (ri *redisIndex) AcquireSpace(ctx context.Context, key Key) (entry groupSpa
8787
return
8888
}
8989

90-
if !sExists {
90+
isForceLoad, _ := ctx.Value(ctxForceSpaceGet).(bool)
91+
if !isForceLoad {
9192
// check if space marked as deleted
9293
var (
9394
delKey = DelKey(key)

index/mock_index/mock_index.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

stat/stat.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88

99
"github.com/anyproto/any-sync/app"
1010
"github.com/anyproto/any-sync/commonfile/fileproto"
11+
"github.com/anyproto/any-sync/coordinator/coordinatorclient"
12+
"github.com/anyproto/any-sync/coordinator/coordinatorproto"
1113

1214
"github.com/anyproto/any-sync-filenode/index"
1315
)
@@ -30,11 +32,13 @@ func New() Stat {
3032
type statService struct {
3133
accountInfoProvider accountInfoProvider
3234
index index.Index
35+
coordinator coordinatorclient.CoordinatorClient
3336
}
3437

3538
func (i *statService) Init(a *app.App) (err error) {
3639
i.accountInfoProvider = app.MustComponent[accountInfoProvider](a)
3740
i.index = app.MustComponent[index.Index](a)
41+
i.coordinator = app.MustComponent[coordinatorclient.CoordinatorClient](a)
3842
return
3943
}
4044

@@ -118,6 +122,46 @@ func (i *statService) Run(ctx context.Context) (err error) {
118122
return
119123
}
120124
})
125+
http.HandleFunc("/stat/check_deletion/{identity}", func(writer http.ResponseWriter, request *http.Request) {
126+
identity := request.PathValue("identity")
127+
if identity == "" {
128+
http.Error(writer, "identity is empty", http.StatusBadRequest)
129+
return
130+
}
131+
isDoFix := request.URL.Query().Get("fix") != ""
132+
133+
st := time.Now()
134+
res, err := i.index.CheckDeletedSpaces(ctx, index.Key{GroupId: identity}, func(spaceIds []string) (deletedIds []string, err error) {
135+
statuses, _, err := i.coordinator.StatusCheckMany(ctx, spaceIds)
136+
if err != nil {
137+
return nil, err
138+
}
139+
for idx, status := range statuses {
140+
if status.Status == coordinatorproto.SpaceStatus_SpaceStatusDeleted {
141+
deletedIds = append(deletedIds, spaceIds[idx])
142+
}
143+
}
144+
return
145+
}, isDoFix)
146+
if err != nil {
147+
http.Error(writer, err.Error(), http.StatusInternalServerError)
148+
}
149+
resp := struct {
150+
Results []string `json:"results"`
151+
Duration string `json:"duration"`
152+
}{
153+
Results: res,
154+
Duration: time.Since(st).String(),
155+
}
156+
157+
writer.Header().Set("Content-Type", "application/json")
158+
writer.WriteHeader(http.StatusOK)
159+
err = json.NewEncoder(writer).Encode(resp)
160+
if err != nil {
161+
http.Error(writer, err.Error(), http.StatusInternalServerError)
162+
return
163+
}
164+
})
121165
return nil
122166
}
123167

0 commit comments

Comments
 (0)