Skip to content

Conversation

@kans
Copy link
Contributor

@kans kans commented Dec 18, 2024

We were accidentally updating actions by value instead of by reference. This meant we never updated the page token on the action. I'm guessing the default page size is 10K, which my test mysteriously hit at 2500 users in 5 nested groups (4 * 2500). This bug is 1 year old.

@kans kans requested a review from jirwin as a code owner December 18, 2024 21:30
@coderabbitai
Copy link

coderabbitai bot commented Dec 18, 2024

Walkthrough

The pull request introduces modifications to the SyncGrantExpansion method in the pkg/sync/syncer.go file, focusing on how actions are managed within the entitlement graph. The changes include appending pointers to EntitlementGraphAction, enhancing cycle detection and logging, and refining error handling. Additionally, a new test function, TestExpandGrants, is added in pkg/sync/syncer_test.go to validate grant expansion functionality, while the pkg/sync/expand/graph.go file updates the Actions field to store pointers instead of values, impacting memory management.

Changes

File Change Summary
pkg/sync/syncer.go - Modified SyncGrantExpansion to append pointers to EntitlementGraphAction
- Enhanced logging for cycle detection and management
pkg/sync/syncer_test.go - Added TestExpandGrants function to validate grant expansion functionality
pkg/sync/expand/graph.go - Changed Actions field from []EntitlementGraphAction to []*EntitlementGraphAction

Possibly related PRs

  • Expand grants faster. #255: The changes in this PR involve optimizations to cycle handling and checkpointing logic, which are directly related to the modifications made in the SyncGrantExpansion method regarding cycle detection and management.

Suggested reviewers

  • jirwin

Poem

🐰 In the garden where grants do grow,
Cycles detected, with a gentle flow.
Pointers now dance in the graph's embrace,
Debug logs twinkle, keeping pace.
A rabbit's cheer for code refined,
In the syncer's realm, harmony aligned! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7854360 and 50a3065.

📒 Files selected for processing (2)
  • pkg/sync/syncer.go (4 hunks)
  • pkg/sync/syncer_test.go (6 hunks)
🧰 Additional context used
🪛 golangci-lint (1.62.2)
pkg/sync/syncer.go

855-855: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


857-857: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


868-868: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


870-870: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


875-875: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


1429-1429: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)


1440-1440: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint
pkg/sync/syncer.go

[failure] 855-855:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 857-857:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 868-868:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 870-870:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 875-875:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 1429-1429:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


[failure] 1440-1440:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

🔇 Additional comments (14)
pkg/sync/syncer_test.go (14)

44-44: **Field initialization **

Appending resource types to mc.RtDb looks fine.
No issues found here.


94-99: **Commented-out lines **

These lines are just commented out. No functional change.
No further action is needed.


100-146: **BenchmarkExpandGrants block **

The approach of creating groups, users, and measuring expansion performance is straightforward, though large data sets (2500 users per layer) might lead to high memory usage.
Overall, this benchmark is valid and helps stress test the expansion logic.


182-186: **Renaming or initializing DB fields **

Logical changes to field names are consistent with the rest of the mockConnector code.
No immediate issues found here.


193-197: **Updated struct field names **

Renamed fields appear consistent with the new naming scheme.
No further changes needed.


218-218: **Appending to ResourceDB in AddGroup **

Storing the group resource in ResourceDB is correct.
No issues found.


226-226: **Storing the Entitlement in EntDB **

Looks correct. No issues found.


243-243: **Appending to UserDB in AddUser **

Storing the user resource in UserDB is valid.
No issues found.


265-265: **Storing grants in GrantDB **

No issues found here.


271-271: **Returning resource types in ListResourceTypes **

Implementation looks straightforward and correct.


276-279: Listing group vs user resources [approve]

The resource listing logic is consistent. No issues detected.
If new resource types are introduced later, consider a more dynamic approach.


285-285: **ListEntitlements logic **

Returning entitlements from the in-memory database is correct.


289-289: **ListGrants logic **

Implementation is correct. No issues found.


72-73: **Potential out-of-range error when accessing mc.EntDB[groupId] **

You are indexing the first element ([0]) of mc.EntDB[groupId] and mc.EntDB[nextGroupId]. If either slice is empty, this will panic.
You might want to check the slice length or handle missing entries gracefully.

To verify if any code path leads to an empty slice for these group IDs, run:


fmt.Printf("%v\n", entitlementGraph)
if entitlementGraph.Loaded {
fmt.Printf("getting cycles1\n")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("getting cycles1\n")
+ l.Debug("getting cycles1")

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

857-857: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 857-857:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

return nil
}

fmt.Printf("not done: %v\n", graph.Depth)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("not done: %v\n", graph.Depth)
+ l.Debug("graph not done yet", zap.Int("depth", graph.Depth))

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

1440-1440: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 1440-1440:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)


fmt.Printf("fixing cycles1\n")
err := entitlementGraph.FixCycles()
fmt.Printf("fixed cycles1\n")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("fixed cycles1\n")
+ l.Debug("fixed cycles1")

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

870-870: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 870-870:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

actions := len(graph.Actions)
if actions%250 == 0 || actions < 10 {
l.Info("Expanding grants", zap.Int("actions", actions))
fmt.Printf("actions: %v: %v\n", actions, graph.Actions)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("actions: %v: %v\n", actions, graph.Actions)
+ l.Info("expanding grants: actions", zap.Int("actions_count", actions), zap.Any("actions", graph.Actions))

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

1429-1429: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 1429-1429:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

return err
}
}
fmt.Printf("expandGrantsForEntitlements\n")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("expandGrantsForEntitlements\n")
+ l.Debug("expandGrantsForEntitlements")

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

875-875: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 875-875:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

return fmt.Errorf("cycles detected in entitlement graph")
}

fmt.Printf("fixing cycles1\n")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

Please switch to structured logging instead of fmt.Printf.

Suggested fix:

- fmt.Printf("fixing cycles1\n")
+ l.Debug("fixing cycles1")

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

868-868: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 868-868:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

return nil
}

fmt.Printf("%v\n", entitlementGraph)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

**Avoid using fmt.Printf in production code **

According to the lint rules (forbidigo), usage of fmt.Printf is disallowed:
Please switch to structured logging (e.g. l.Debug) to ensure consistency, traceability, and adherence to logging policy.

Suggested fix:

- fmt.Printf("%v\n", entitlementGraph)
+ l.Debug("entitlementGraph state", zap.Any("graph", entitlementGraph))

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 golangci-lint (1.62.2)

855-855: use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$

(forbidigo)

🪛 GitHub Check: go-lint

[failure] 855-855:
use of fmt.Printf forbidden by pattern ^(fmt\.Print(|f|ln)|print|println)$ (forbidigo)

@kans kans force-pushed the kans/grant-expansion-halting branch from 9da9d5a to 05051db Compare December 18, 2024 22:04
@kans kans changed the title [WIP] Debugging Infinite Loop Fix Infinite Loop Dec 18, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/sync/syncer_test.go (1)

36-38: Consider documenting the test parameters

The magic numbers 2500 and 5 would benefit from documentation explaining their significance, especially since they are related to a pagination bug that caused infinite loops.

-	// 2500 * 4 = 10K - used to cause an infinite loop on pagition
-	usersPerLayer := 2500
-	groupCount := 5
+	// These parameters are chosen to reproduce a pagination-related infinite loop bug:
+	// - usersPerLayer=2500 creates 10K users (2500 * 4) which exceeds typical page sizes
+	// - groupCount=5 creates enough group layers to test deep grant expansion
+	usersPerLayer := 2500
+	groupCount := 5
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50a3065 and 05051db.

📒 Files selected for processing (3)
  • pkg/sync/expand/graph.go (1 hunks)
  • pkg/sync/syncer.go (1 hunks)
  • pkg/sync/syncer_test.go (1 hunks)
🔇 Additional comments (2)
pkg/sync/expand/graph.go (1)

42-52: Excellent change to use pointer slice for Actions

The modification of Actions field to use pointers ([]*EntitlementGraphAction) instead of values is a good improvement because:

  1. It ensures modifications to actions are visible across the codebase
  2. It reduces memory usage by avoiding copies of potentially large action objects
  3. It aligns with how actions are manipulated in the syncer code
pkg/sync/syncer.go (1)

Line range hint 1472-1479: Correctly using pointer when appending action

The code properly creates and appends a pointer to EntitlementGraphAction, which aligns with the updated Actions field type in the EntitlementGraph struct.

Comment on lines +65 to +67
// This isn't needed because grant expansion will create this grant
// _ = mc.AddGroupMember(ctx, group, principal)
_ = mc.AddGroupMember(ctx, group, principal)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove redundant comment and duplicate code

The code contains both a commented-out line and its uncommented duplicate, which is confusing.

-			// This isn't needed because grant expansion will create this grant
-			// _ = mc.AddGroupMember(ctx, group, principal)
-			_ = mc.AddGroupMember(ctx, group, principal)
+			_ = mc.AddGroupMember(ctx, group, principal)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// This isn't needed because grant expansion will create this grant
// _ = mc.AddGroupMember(ctx, group, principal)
_ = mc.AddGroupMember(ctx, group, principal)
_ = mc.AddGroupMember(ctx, group, principal)

Comment on lines +71 to +82
tempDir, err := os.MkdirTemp("", "baton-benchmark-expand-grants")
require.NoError(t, err)
defer os.RemoveAll(tempDir)
c1zpath := filepath.Join(tempDir, "expand-grants.c1z")
syncer, err := NewSyncer(ctx, mc, WithC1ZPath(c1zpath), WithTmpDir(tempDir))
require.NoError(t, err)
err = syncer.Sync(ctx)
require.NoError(t, err)
err = syncer.Close(ctx)
require.NoError(t, err)
_ = os.Remove(c1zpath)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding test assertions

The test creates the data structure but doesn't verify the results of the grant expansion.

Add assertions to verify:

  1. The correct number of grants were created
  2. The grants have the expected relationships
  3. No infinite loops occurred during expansion

Example:

 	err = syncer.Close(ctx)
 	require.NoError(t, err)
 	_ = os.Remove(c1zpath)
+
+	// Verify grant expansion results
+	grants, err := syncer.store.ListGrants(ctx, &v2.GrantsServiceListGrantsRequest{})
+	require.NoError(t, err)
+	
+	// Assert expected number of grants
+	expectedGrantCount := groupCount * usersPerLayer
+	assert.Equal(t, expectedGrantCount, len(grants.List), "Unexpected number of grants")
+	
+	// Verify grant relationships
+	for _, grant := range grants.List {
+		assert.NotNil(t, grant.Principal, "Grant should have a principal")
+		assert.NotNil(t, grant.Entitlement, "Grant should have an entitlement")
+	}

Committable suggestion skipped: line range outside the PR's diff.

@ggreer ggreer merged commit f23f6a9 into main Dec 18, 2024
4 checks passed
@ggreer ggreer deleted the kans/grant-expansion-halting branch December 18, 2024 22:12
@coderabbitai coderabbitai bot mentioned this pull request Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants