Initial cloud-services repo - gateway service + pkg modules
This commit is contained in:
52
pkg/scheduler/bucket.go
Normal file
52
pkg/scheduler/bucket.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Assign elements to a bucket and perform an action 12 cycles later. This can be
|
||||
// used in conjunction with a cron job to perform cleanup tasks at a constant point
|
||||
// in the future.
|
||||
type Bucket[T any] struct {
|
||||
elements [12][]T
|
||||
bucket int
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
type BucketInterface[T any] interface {
|
||||
Process(handler func(element Bucket[T]))
|
||||
Schedule(element T) error
|
||||
clear()
|
||||
lapse()
|
||||
}
|
||||
|
||||
// Run a callback on each element in next bucket, then clear
|
||||
func (e *Bucket[T]) Process(handler func(element T)) {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
e.lapse()
|
||||
if len(e.elements[e.bucket]) > 0 {
|
||||
for _, element := range e.elements[e.bucket] {
|
||||
handler(element)
|
||||
}
|
||||
e.clear()
|
||||
}
|
||||
}
|
||||
|
||||
// Add element to a bucket to be deleted later
|
||||
func (e *Bucket[T]) Schedule(element T) {
|
||||
e.mutex.Lock()
|
||||
defer e.mutex.Unlock()
|
||||
e.elements[e.bucket] = append(e.elements[e.bucket], element)
|
||||
}
|
||||
|
||||
// Remove all elements from current bucket
|
||||
func (e *Bucket[T]) clear() {
|
||||
e.elements[e.bucket] = []T{}
|
||||
}
|
||||
|
||||
// Increment the active bucket
|
||||
func (e *Bucket[T]) lapse() {
|
||||
e.bucket += 1
|
||||
e.bucket %= len(e.elements)
|
||||
}
|
||||
63
pkg/scheduler/bucket_test.go
Normal file
63
pkg/scheduler/bucket_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"fiskerinc.com/modules/testhelper"
|
||||
)
|
||||
|
||||
func TestBucketProcess(t *testing.T) {
|
||||
bucket := Bucket[int]{}
|
||||
actual := []int{}
|
||||
|
||||
bucket.elements[1] = []int{1, 2, 3}
|
||||
|
||||
double := func(element int) {
|
||||
actual = append(actual, element*2)
|
||||
}
|
||||
|
||||
bucket.Process(double)
|
||||
|
||||
if len(bucket.elements[1]) != 0 {
|
||||
t.Errorf("Expected bucket to be clearsd after processing, but it wasn't")
|
||||
}
|
||||
|
||||
if bucket.bucket != 1 {
|
||||
t.Errorf("Expected active bucket to be incremented, but it wasn't")
|
||||
}
|
||||
|
||||
expected := []int{2, 4, 6}
|
||||
for i := 0; i < len(expected); i++ {
|
||||
if actual[i] != expected[i] {
|
||||
t.Errorf(testhelper.TestErrorTemplate, "Bucket.Process()", expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBucketLoop(t *testing.T) {
|
||||
bucket := Bucket[int]{}
|
||||
|
||||
stub := func(element int) {}
|
||||
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
bucket.Process(stub)
|
||||
|
||||
if bucket.bucket != 11 {
|
||||
t.Errorf("Expected active bucket to be 11, got %d", bucket.bucket)
|
||||
}
|
||||
|
||||
bucket.Process(stub)
|
||||
|
||||
if bucket.bucket != 0 {
|
||||
t.Errorf("Expected active bucket to be 0, got %d", bucket.bucket)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user