Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIx Finding Housekeeping Candidates and Modify Housekeeping Structure #749

Merged
merged 25 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a9fdfbe
Change `listProjectInfos` to `rotateListProjectInfosGreaterThan`
devleejb Jan 5, 2024
4af4a1d
Update testcase for changing `rotateListProjectInfosGreaterThan` to c…
devleejb Jan 5, 2024
544b6a8
Change `listProjectInfos` to `rotateListProjectInfosGreaterThan` for …
devleejb Jan 5, 2024
55dc6f2
Update testcase for changing `rotateListProjectInfosGreaterThan` to c…
devleejb Jan 5, 2024
371c0bd
Remove unused print
devleejb Jan 5, 2024
ce1ad89
Add missing housekeeping testcase in memDB
krapie Jan 7, 2024
339272f
Remove useless error checking
Jan 8, 2024
7b2f720
Change `listProjectInfos` to `rotateListProjectInfosGreaterThan`
Jan 8, 2024
51dab2f
Improve cycling logic for `rotateListProjectInfosGreaterThan`
Jan 8, 2024
63970f2
Change function name from `rotateListProjectInfosGreaterThan` to `nex…
Jan 8, 2024
021918b
Move `FindDeactivateCandidates` to service layer
Jan 8, 2024
9c0bee4
Change function name from `NextCyclingProjectInfos` to `FindNextNCycl…
Jan 8, 2024
0ea19bb
Change parameter name from `housekeepingLastProjectID` to `lastProjec…
Jan 8, 2024
554fbd5
Change parameter from `lastProjectId` to `lastProjectID`
Jan 8, 2024
f73b6de
Remove useless codes
Jan 8, 2024
5ee06cd
Add integration test case for housekeeping
devleejb Jan 9, 2024
0c1547f
Fix lint errors
devleejb Jan 9, 2024
f40b0ee
Add testcase for crud about housekeeping logic
devleejb Jan 9, 2024
01ea858
Fix `FindDeactivateCandidatesPerProject` to return only candidates fo…
devleejb Jan 9, 2024
a92289e
Fix lint
devleejb Jan 9, 2024
2cc193f
Fix lint
devleejb Jan 9, 2024
11d5ba2
Remove not working test
devleejb Jan 9, 2024
84daeaa
Remove useless codes
devleejb Jan 9, 2024
b5d883b
Apply comment
Jan 10, 2024
6ad2ca3
Update function related comments
krapie Jan 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions server/backend/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,19 @@ type Database interface {
// after handling PushPull.
UpdateClientInfoAfterPushPull(ctx context.Context, clientInfo *ClientInfo, docInfo *DocInfo) error

// FindDeactivateCandidates finds the housekeeping candidates.
FindDeactivateCandidates(
// FindNextNCyclingProjectInfos finds the next N cycling projects from the given projectID.
FindNextNCyclingProjectInfos(
ctx context.Context,
candidatesLimitPerProject int,
projectFetchSize int,
pageSize int,
lastProjectID types.ID,
) (types.ID, []*ClientInfo, error)
) ([]*ProjectInfo, error)

// FindDeactivateCandidatesPerProject finds the clients that need housekeeping per project.
FindDeactivateCandidatesPerProject(
ctx context.Context,
project *ProjectInfo,
candidatesLimit int,
) ([]*ClientInfo, error)

// FindDocInfoByKey finds the document of the given key.
FindDocInfoByKey(
Expand Down
71 changes: 31 additions & 40 deletions server/backend/database/memory/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,38 +224,58 @@ func (d *DB) CreateProjectInfo(
return info, nil
}

// listProjectInfos returns all project infos rotationally.
func (d *DB) listProjectInfos(
// FindNextNCyclingProjectInfos finds the next N cycling projects from the given projectID.
func (d *DB) FindNextNCyclingProjectInfos(
_ context.Context,
pageSize int,
housekeepingLastProjectID types.ID,
lastProjectID types.ID,
) ([]*database.ProjectInfo, error) {
txn := d.db.Txn(false)
defer txn.Abort()

iter, err := txn.LowerBound(
tblProjects,
"id",
housekeepingLastProjectID.String(),
lastProjectID.String(),
)
if err != nil {
return nil, fmt.Errorf("fetch projects: %w", err)
}

var infos []*database.ProjectInfo
isCircular := false

for i := 0; i < pageSize; i++ {
raw := iter.Next()
if raw == nil {
break
if isCircular {
break
}

iter, err = txn.LowerBound(
tblProjects,
"id",
database.DefaultProjectID.String(),
)
if err != nil {
return nil, fmt.Errorf("fetch projects: %w", err)
}

i--
isCircular = true
continue
}
info := raw.(*database.ProjectInfo).DeepCopy()

if i == 0 && info.ID == housekeepingLastProjectID {
if i == 0 && info.ID == lastProjectID {
pageSize++
continue
}

if len(infos) > 0 && infos[0].ID == info.ID {
break
}

infos = append(infos, info)
}

Expand Down Expand Up @@ -563,8 +583,8 @@ func (d *DB) UpdateClientInfoAfterPushPull(
return nil
}

// findDeactivateCandidatesPerProject finds the clients that need housekeeping per project.
func (d *DB) findDeactivateCandidatesPerProject(
// FindDeactivateCandidatesPerProject finds the clients that need housekeeping per project.
func (d *DB) FindDeactivateCandidatesPerProject(
_ context.Context,
project *database.ProjectInfo,
candidatesLimit int,
Expand Down Expand Up @@ -599,41 +619,12 @@ func (d *DB) findDeactivateCandidatesPerProject(
info.UpdatedAt.After(offset) {
break
}
infos = append(infos, info)
}
return infos, nil
}

// FindDeactivateCandidates finds the clients that need housekeeping.
func (d *DB) FindDeactivateCandidates(
ctx context.Context,
candidatesLimitPerProject int,
projectFetchSize int,
lastProjectID types.ID,
) (types.ID, []*database.ClientInfo, error) {
projects, err := d.listProjectInfos(ctx, projectFetchSize, lastProjectID)
if err != nil {
return database.DefaultProjectID, nil, err
}

var candidates []*database.ClientInfo
for _, project := range projects {
infos, err := d.findDeactivateCandidatesPerProject(ctx, project, candidatesLimitPerProject)
if err != nil {
return database.DefaultProjectID, nil, err
if info.ProjectID == project.ID {
infos = append(infos, info)
}

candidates = append(candidates, infos...)
}

var topProjectID types.ID
if len(projects) < projectFetchSize {
topProjectID = database.DefaultProjectID
} else {
topProjectID = projects[len(projects)-1].ID
}

return topProjectID, candidates, nil
return infos, nil
}

// FindDocInfoByKeyAndOwner finds the document of the given key. If the
Expand Down
8 changes: 8 additions & 0 deletions server/backend/database/memory/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ func TestDB(t *testing.T) {
db, err := memory.New()
assert.NoError(t, err)

t.Run("FindNextNCyclingProjectInfos test", func(t *testing.T) {
testcases.RunFindNextNCyclingProjectInfosTest(t, db)
})

t.Run("FindDeactivateCandidatesPerProject test", func(t *testing.T) {
testcases.RunFindDeactivateCandidatesPerProjectTest(t, db)
})

t.Run("RunFindDocInfo test", func(t *testing.T) {
testcases.RunFindDocInfoTest(t, db, projectID)
})
Expand Down
133 changes: 0 additions & 133 deletions server/backend/database/memory/housekeeping_test.go

This file was deleted.

62 changes: 25 additions & 37 deletions server/backend/database/mongo/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,13 @@ func (c *Client) CreateProjectInfo(
return info, nil
}

// listProjectInfos returns all project infos rotationally.
func (c *Client) listProjectInfos(
// FindNextNCyclingProjectInfos finds the next N cycling projects from the given projectID.
func (c *Client) FindNextNCyclingProjectInfos(
ctx context.Context,
pageSize int,
housekeepingLastProjectID types.ID,
lastProjectID types.ID,
) ([]*database.ProjectInfo, error) {
encodedID, err := encodeID(housekeepingLastProjectID)
encodedID, err := encodeID(lastProjectID)
if err != nil {
return nil, err
}
Expand All @@ -268,6 +268,25 @@ func (c *Client) listProjectInfos(
return nil, fmt.Errorf("fetch project infos: %w", err)
}

if len(infos) < pageSize {
opts.SetLimit(int64(pageSize - len(infos)))

cursor, err := c.collection(colProjects).Find(ctx, bson.M{
"_id": bson.M{
"$lte": encodedID,
},
}, opts)
if err != nil {
return nil, fmt.Errorf("find project infos: %w", err)
}

var newInfos []*database.ProjectInfo
if err := cursor.All(ctx, &newInfos); err != nil {
return nil, fmt.Errorf("fetch project infos: %w", err)
}
infos = append(infos, newInfos...)
}

return infos, nil
}

Expand Down Expand Up @@ -633,8 +652,8 @@ func (c *Client) UpdateClientInfoAfterPushPull(
return nil
}

// findDeactivateCandidatesPerProject finds the clients that need housekeeping per project.
func (c *Client) findDeactivateCandidatesPerProject(
// FindDeactivateCandidatesPerProject finds the clients that need housekeeping per project.
func (c *Client) FindDeactivateCandidatesPerProject(
ctx context.Context,
project *database.ProjectInfo,
candidatesLimit int,
Expand Down Expand Up @@ -669,37 +688,6 @@ func (c *Client) findDeactivateCandidatesPerProject(
return clientInfos, nil
}

// FindDeactivateCandidates finds the clients that need housekeeping.
func (c *Client) FindDeactivateCandidates(
ctx context.Context,
candidatesLimitPerProject int,
projectFetchSize int,
lastProjectID types.ID,
) (types.ID, []*database.ClientInfo, error) {
projects, err := c.listProjectInfos(ctx, projectFetchSize, lastProjectID)
if err != nil {
return database.DefaultProjectID, nil, err
}

var candidates []*database.ClientInfo
for _, project := range projects {
clientInfos, err := c.findDeactivateCandidatesPerProject(ctx, project, candidatesLimitPerProject)
if err != nil {
return database.DefaultProjectID, nil, err
}

candidates = append(candidates, clientInfos...)
}

var topProjectID types.ID
if len(projects) < projectFetchSize {
topProjectID = database.DefaultProjectID
} else {
topProjectID = projects[len(projects)-1].ID
}
return topProjectID, candidates, nil
}

// FindDocInfoByKeyAndOwner finds the document of the given key. If the
// createDocIfNotExist condition is true, create the document if it does not
// exist.
Expand Down
Loading
Loading