You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
internal/difc/capabilities.go and internal/difc/labels.go both define a concurrent tag-set backed by map[Tag]struct{} + sync.RWMutex. Five core methods — Add, AddAll, Remove, Contains, and GetAll/GetTags — are nearly identical between the two types, differing only in receiver name and optional debug-log calls.
Maintainability: Any fix, optimization, or logging change to the mutex-locking pattern must be applied twice. The recent commit ([log] Add debug logging to difc/capabilities.go #8744) added logging only to Capabilities — if the same logging is wanted in Label.GetTags() or Label.Contains(), it requires another PR.
Bug Risk: A concurrency bug (e.g. defer vs manual unlock ordering) fixed in one place may be missed in the other.
Code Bloat: ~25 lines of duplicated logic across two files in the same package.
Refactoring Recommendations
Extract a tagSet helper type (preferred)
Create internal/difc/tagset.go with an unexported tagSet struct that holds tags map[Tag]struct{} and mu sync.RWMutex
Implement add, addAll, remove, contains, getAll, clear, count on tagSet
Embed or delegate from both Label and Capabilities
Estimated effort: 1–2 hours
Benefits: single source of truth for mutex discipline; debug logging added once
Embed Label inside Capabilities
Capabilities wraps a *Label and delegates Add, AddAll, Remove, Contains, GetAll to it
Simpler change, but Label has set-algebra methods (Union, Intersect) that Capabilities does not need — embedding exposes more API surface than desired
Estimated effort: 30 minutes
Implementation Checklist
Review duplication findings
Decide on refactoring approach (extract tagSet vs embed Label)
Implement changes in internal/difc/
Update existing unit tests in capabilities_test.go and labels_test.go
Verify go test ./internal/difc/ passes
Verify no functionality broken
Parent Issue
See parent analysis report: #8771
Related to #8771
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
awmgmcpg
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
Part of duplicate code analysis: #8771
Summary
internal/difc/capabilities.goandinternal/difc/labels.goboth define a concurrent tag-set backed bymap[Tag]struct{}+sync.RWMutex. Five core methods —Add,AddAll,Remove,Contains, andGetAll/GetTags— are nearly identical between the two types, differing only in receiver name and optional debug-log calls.Duplication Details
Pattern: Concurrent map[Tag]struct{} mutation methods
internal/difc/capabilities.go(lines 27–86) —Capabilities.Add,Capabilities.AddAll,Capabilities.Remove,Capabilities.Contains,Capabilities.GetAllinternal/difc/labels.go(lines 42–154) —Label.Add,Label.AddAll,Label.Remove,Label.Contains,Label.GetTagsCode Sample —
Add(Capabilities vs Label):Code Sample —
GetAll/GetTags(Capabilities vs Label):Impact Analysis
Capabilities— if the same logging is wanted inLabel.GetTags()orLabel.Contains(), it requires another PR.Refactoring Recommendations
Extract a
tagSethelper type (preferred)internal/difc/tagset.gowith an unexportedtagSetstruct that holdstags map[Tag]struct{}andmu sync.RWMutexadd,addAll,remove,contains,getAll,clear,countontagSetLabelandCapabilitiesEmbed
LabelinsideCapabilitiesCapabilitieswraps a*Labeland delegatesAdd,AddAll,Remove,Contains,GetAllto itLabelhas set-algebra methods (Union,Intersect) thatCapabilitiesdoes not need — embedding exposes more API surface than desiredImplementation Checklist
tagSetvs embedLabel)internal/difc/capabilities_test.goandlabels_test.gogo test ./internal/difc/passesParent Issue
See parent analysis report: #8771
Related to #8771
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
awmgmcpgSee Network Configuration for more information.