History

fix(auth): preserve and restore ready view cursors during index rebuilds

Luis Pater committed 7 months ago

Commit 730809d1 parent 5e81b651 file · +83 −1Browse files

Unified · Split

sdk/cliproxy/auth/scheduler.go+83−1
@@ -97,6 +97,72 @@ type childBucket struct { · 96 unmodified lines
97// cooldownQueue is the blocked auth collection ordered by next retry time during rebuilds.97// cooldownQueue is the blocked auth collection ordered by next retry time during rebuilds.
98type cooldownQueue []*scheduledAuth98type cooldownQueue []*scheduledAuth
99 99
100type readyViewCursorState struct {
101 cursor int
102 parentCursor int
103 childCursors map[string]int
104}
105
106type readyBucketCursorState struct {
107 all readyViewCursorState
108 ws readyViewCursorState
109}
110
111func snapshotReadyViewCursors(view readyView) readyViewCursorState {
112 state := readyViewCursorState{
113 cursor: view.cursor,
114 parentCursor: view.parentCursor,
115 }
116 if len(view.children) == 0 {
117 return state
118 }
119 state.childCursors = make(map[string]int, len(view.children))
120 for parent, child := range view.children {
121 if child == nil {
122 continue
123 }
124 state.childCursors[parent] = child.cursor
125 }
126 return state
127}
128
129func restoreReadyViewCursors(view *readyView, state readyViewCursorState) {
130 if view == nil {
131 return
132 }
133 if len(view.flat) > 0 {
134 view.cursor = normalizeCursor(state.cursor, len(view.flat))
135 }
136 if len(view.parentOrder) == 0 || len(view.children) == 0 {
137 return
138 }
139 view.parentCursor = normalizeCursor(state.parentCursor, len(view.parentOrder))
140 if len(state.childCursors) == 0 {
141 return
142 }
143 for parent, child := range view.children {
144 if child == nil || len(child.items) == 0 {
145 continue
146 }
147 cursor, ok := state.childCursors[parent]
148 if !ok {
149 continue
150 }
151 child.cursor = normalizeCursor(cursor, len(child.items))
152 }
153}
154
155func normalizeCursor(cursor, size int) int {
156 if size <= 0 || cursor <= 0 {
157 return 0
158 }
159 cursor = cursor % size
160 if cursor < 0 {
161 cursor += size
162 }
163 return cursor
164}
165
100// newAuthScheduler constructs an empty scheduler configured for the supplied selector strategy.166// newAuthScheduler constructs an empty scheduler configured for the supplied selector strategy.
101func newAuthScheduler(selector Selector) *authScheduler {167func newAuthScheduler(selector Selector) *authScheduler {
102 return &authScheduler{168 return &authScheduler{
@@ -824,6 +890,17 @@ func (m *modelScheduler) availabilitySummaryLocked(predicate func(*scheduledAuth · 721 unmodified lines
824 890
825// rebuildIndexesLocked reconstructs ready and blocked views from the current entry map.891// rebuildIndexesLocked reconstructs ready and blocked views from the current entry map.
826func (m *modelScheduler) rebuildIndexesLocked() {892func (m *modelScheduler) rebuildIndexesLocked() {
893 cursorStates := make(map[int]readyBucketCursorState, len(m.readyByPriority))
894 for priority, bucket := range m.readyByPriority {
895 if bucket == nil {
896 continue
897 }
898 cursorStates[priority] = readyBucketCursorState{
899 all: snapshotReadyViewCursors(bucket.all),
900 ws: snapshotReadyViewCursors(bucket.ws),
901 }
902 }
903
827 m.readyByPriority = make(map[int]*readyBucket)904 m.readyByPriority = make(map[int]*readyBucket)
828 m.priorityOrder = m.priorityOrder[:0]905 m.priorityOrder = m.priorityOrder[:0]
829 m.blocked = m.blocked[:0]906 m.blocked = m.blocked[:0]
@@ -844,7 +921,12 @@ func (m *modelScheduler) rebuildIndexesLocked() { · 14 unmodified lines
844 sort.Slice(entries, func(i, j int) bool {921 sort.Slice(entries, func(i, j int) bool {
845 return entries[i].auth.ID < entries[j].auth.ID922 return entries[i].auth.ID < entries[j].auth.ID
846 })923 })
847 m.readyByPriority[priority] = buildReadyBucket(entries)924 bucket := buildReadyBucket(entries)
925 if cursorState, ok := cursorStates[priority]; ok && bucket != nil {
926 restoreReadyViewCursors(&bucket.all, cursorState.all)
927 restoreReadyViewCursors(&bucket.ws, cursorState.ws)
928 }
929 m.readyByPriority[priority] = bucket
848 m.priorityOrder = append(m.priorityOrder, priority)930 m.priorityOrder = append(m.priorityOrder, priority)
849 }931 }
850 sort.Slice(m.priorityOrder, func(i, j int) bool {932 sort.Slice(m.priorityOrder, func(i, j int) bool {