-
Notifications
You must be signed in to change notification settings - Fork 5
Set progress counts when resuming a sync. #328
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,144 @@ | ||||||||||||||||||||||||||||||||||||||
| package progress | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| "github.com/conductorone/baton-sdk/pkg/sync/expand" | ||||||||||||||||||||||||||||||||||||||
| "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" | ||||||||||||||||||||||||||||||||||||||
| "go.uber.org/zap" | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| type ProgressCounts struct { | ||||||||||||||||||||||||||||||||||||||
| ResourceTypes int // count of resource types | ||||||||||||||||||||||||||||||||||||||
| Resources map[string]int // map of resource type id to resource count | ||||||||||||||||||||||||||||||||||||||
| EntitlementsProgress map[string]int // map of resource type id to entitlement count | ||||||||||||||||||||||||||||||||||||||
| LastEntitlementLog map[string]time.Time | ||||||||||||||||||||||||||||||||||||||
| GrantsProgress map[string]int // map of resource type id to grant count | ||||||||||||||||||||||||||||||||||||||
| LastGrantLog map[string]time.Time | ||||||||||||||||||||||||||||||||||||||
| LastActionLog time.Time | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using int64 for counts. Storing counts in the - type ProgressCounts struct {
- ResourceTypes int
- Resources map[string]int
- EntitlementsProgress map[string]int
- ...
- }
+ type ProgressCounts struct {
+ ResourceTypes int64
+ Resources map[string]int64
+ EntitlementsProgress map[string]int64
+ ...
+ }📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const maxLogFrequency = 10 * time.Second | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // TODO: use a mutex or a syncmap for when syncer code becomes parallel | ||||||||||||||||||||||||||||||||||||||
| func NewProgressCounts() *ProgressCounts { | ||||||||||||||||||||||||||||||||||||||
| return &ProgressCounts{ | ||||||||||||||||||||||||||||||||||||||
| Resources: make(map[string]int), | ||||||||||||||||||||||||||||||||||||||
| EntitlementsProgress: make(map[string]int), | ||||||||||||||||||||||||||||||||||||||
| LastEntitlementLog: make(map[string]time.Time), | ||||||||||||||||||||||||||||||||||||||
| GrantsProgress: make(map[string]int), | ||||||||||||||||||||||||||||||||||||||
| LastGrantLog: make(map[string]time.Time), | ||||||||||||||||||||||||||||||||||||||
| LastActionLog: time.Time{}, | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func (p *ProgressCounts) LogResourceTypesProgress(ctx context.Context) { | ||||||||||||||||||||||||||||||||||||||
| l := ctxzap.Extract(ctx) | ||||||||||||||||||||||||||||||||||||||
| l.Info("Synced resource types", zap.Int("count", p.ResourceTypes)) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func (p *ProgressCounts) LogResourcesProgress(ctx context.Context, resourceType string) { | ||||||||||||||||||||||||||||||||||||||
| l := ctxzap.Extract(ctx) | ||||||||||||||||||||||||||||||||||||||
| resources := p.Resources[resourceType] | ||||||||||||||||||||||||||||||||||||||
| l.Info("Synced resources", zap.String("resource_type_id", resourceType), zap.Int("count", resources)) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func (p *ProgressCounts) LogEntitlementsProgress(ctx context.Context, resourceType string) { | ||||||||||||||||||||||||||||||||||||||
| entitlementsProgress := p.EntitlementsProgress[resourceType] | ||||||||||||||||||||||||||||||||||||||
| resources := p.Resources[resourceType] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| l := ctxzap.Extract(ctx) | ||||||||||||||||||||||||||||||||||||||
| if resources == 0 { | ||||||||||||||||||||||||||||||||||||||
| // if resuming sync, resource counts will be zero, so don't calculate percentage. just log every 10 seconds. | ||||||||||||||||||||||||||||||||||||||
| if time.Since(p.LastEntitlementLog[resourceType]) > maxLogFrequency { | ||||||||||||||||||||||||||||||||||||||
| l.Info("Syncing entitlements", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", entitlementsProgress), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastEntitlementLog[resourceType] = time.Now() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| percentComplete := (entitlementsProgress * 100) / resources | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| switch { | ||||||||||||||||||||||||||||||||||||||
| case entitlementsProgress > resources: | ||||||||||||||||||||||||||||||||||||||
| l.Error("more entitlement resources than resources", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", entitlementsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| case percentComplete == 100: | ||||||||||||||||||||||||||||||||||||||
| l.Info("Synced entitlements", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("count", entitlementsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastEntitlementLog[resourceType] = time.Time{} | ||||||||||||||||||||||||||||||||||||||
| case time.Since(p.LastEntitlementLog[resourceType]) > maxLogFrequency: | ||||||||||||||||||||||||||||||||||||||
| l.Info("Syncing entitlements", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", entitlementsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("percent_complete", percentComplete), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastEntitlementLog[resourceType] = time.Now() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func (p *ProgressCounts) LogGrantsProgress(ctx context.Context, resourceType string) { | ||||||||||||||||||||||||||||||||||||||
| grantsProgress := p.GrantsProgress[resourceType] | ||||||||||||||||||||||||||||||||||||||
| resources := p.Resources[resourceType] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| l := ctxzap.Extract(ctx) | ||||||||||||||||||||||||||||||||||||||
| if resources == 0 { | ||||||||||||||||||||||||||||||||||||||
| // if resuming sync, resource counts will be zero, so don't calculate percentage. just log every 10 seconds. | ||||||||||||||||||||||||||||||||||||||
| if time.Since(p.LastGrantLog[resourceType]) > maxLogFrequency { | ||||||||||||||||||||||||||||||||||||||
| l.Info("Syncing grants", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", grantsProgress), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastGrantLog[resourceType] = time.Now() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| percentComplete := (grantsProgress * 100) / resources | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| switch { | ||||||||||||||||||||||||||||||||||||||
| case grantsProgress > resources: | ||||||||||||||||||||||||||||||||||||||
| l.Error("more grant resources than resources", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", grantsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| case percentComplete == 100: | ||||||||||||||||||||||||||||||||||||||
| l.Info("Synced grants", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("count", grantsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastGrantLog[resourceType] = time.Time{} | ||||||||||||||||||||||||||||||||||||||
| case time.Since(p.LastGrantLog[resourceType]) > maxLogFrequency: | ||||||||||||||||||||||||||||||||||||||
| l.Info("Syncing grants", | ||||||||||||||||||||||||||||||||||||||
| zap.String("resource_type_id", resourceType), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("synced", grantsProgress), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("total", resources), | ||||||||||||||||||||||||||||||||||||||
| zap.Int("percent_complete", percentComplete), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| p.LastGrantLog[resourceType] = time.Now() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| func (p *ProgressCounts) LogExpandProgress(ctx context.Context, actions []*expand.EntitlementGraphAction) { | ||||||||||||||||||||||||||||||||||||||
| actionsLen := len(actions) | ||||||||||||||||||||||||||||||||||||||
| if time.Since(p.LastActionLog) < maxLogFrequency { | ||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| p.LastActionLog = time.Now() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| l := ctxzap.Extract(ctx) | ||||||||||||||||||||||||||||||||||||||
| l.Info("Expanding grants", zap.Int("actions_remaining", actionsLen)) | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Potential overflow and repeated queries.
int64) in anintfield can lead to overflow on 32-bit systems if counts exceed 2,147,483,647. Consider refactoring theProgressCountsstruct to useint64instead ofintwhere feasible.I'll begin by gathering additional context regarding the definition of the
ProgressCountsstruct and its initialization via theNewProgressCountsfunction to verify the potential overflow issue mentioned. This will help us confirm whether the struct fields are defined asintorint64, and if the repeated query logic can be optimized.Below is a shell script to search for these definitions in the codebase:
🏁 Script executed:
Length of output: 384
I'll now gather more details about the field types within the
ProgressCountsstruct to verify if the overflow concern is valid. Specifically, we need to check whether fields likeResources,GrantsProgress, andEntitlementsProgressare declared as typeint(which may cause overflows on 32-bit systems) or asint64.Below is a shell script to inspect the definition of
ProgressCountsin thepkg/progress/progress.gofile:🏁 Script executed:
Length of output: 887
Action Required: Refactor Integer Types and Consolidate Query Logic
ProgressCountsstruct (inpkg/progress/progress.go) defines count fields asint. Given that the database queries returnint64, casting withint(...)risks overflow on 32-bit systems—even though there’s a check againstmath.MaxInt. Consider refactoring these fields (and the corresponding initialization inNewProgressCounts) to useint64to safely handle larger numbers.Please address these concerns to ensure robustness and cleaner code.