sourcegraph/internal/workerutil/idset.go
Sander Ginn a1a2684610
Worker: use string ID instead of int for job tracking (#52454)
- Prerequisite for
https://github.com/sourcegraph/sourcegraph/issues/51658, see [thread for
context](https://sourcegraph.slack.com/archives/C04K1NSCK6K/p1684841039315679)

This PR lets the worker keep track of it's running job IDs using a
string ID rather than int IDs. To achieve this, the `Record` interface
is extended with a second method `RecordUID()` which returns a string.

All the types that implement `Record` add a method `RecordUID()` which
simply converts its int value to a string representation. The only
exception to this rule is `executortypes.Job`, which includes the queue
name if it is set. The end goal here is that an executor can process
jobs from multiple queues by retrieving the required context from the
heartbeat IDs without leaking implementation details to the worker
level.

## Test plan
Unit tests.
Looking for input on other ways to validate nothing is broken.
<!-- All pull requests REQUIRE a test plan:
https://docs.sourcegraph.com/dev/background-information/testing_principles
-->
2023-05-26 16:26:42 +02:00

86 lines
1.6 KiB
Go

package workerutil
import (
"context"
"sort"
"sync"
)
type IDSet struct {
sync.RWMutex
ids map[string]context.CancelFunc
}
func newIDSet() *IDSet {
return &IDSet{ids: map[string]context.CancelFunc{}}
}
// Add associates the given identifier with the given cancel function
// in the set. If the identifier was already present then the set is
// unchanged.
func (i *IDSet) Add(id string, cancel context.CancelFunc) bool {
i.Lock()
defer i.Unlock()
if _, ok := i.ids[id]; ok {
return false
}
i.ids[id] = cancel
return true
}
// Remove invokes the cancel function associated with the given identifier
// in the set and removes the identifier from the set. If the identifier is
// not a member of the set, then no action is performed.
func (i *IDSet) Remove(id string) bool {
i.Lock()
cancel, ok := i.ids[id]
delete(i.ids, id)
i.Unlock()
if ok {
cancel()
}
return ok
}
// Remove invokes the cancel function associated with the given identifier
// in the set. If the identifier is not a member of the set, then no action
// is performed.
func (i *IDSet) Cancel(id string) {
i.RLock()
cancel, ok := i.ids[id]
i.RUnlock()
if ok {
cancel()
}
}
// Slice returns an ordered copy of the identifiers composing the set.
func (i *IDSet) Slice() []string {
i.RLock()
defer i.RUnlock()
ids := make([]string, 0, len(i.ids))
for id := range i.ids {
ids = append(ids, id)
}
sort.Strings(ids)
return ids
}
// Has returns whether the IDSet contains the given id.
func (i *IDSet) Has(id string) bool {
for _, have := range i.Slice() {
if id == have {
return true
}
}
return false
}