mirror of
https://github.com/hanzoai/tasks.git
synced 2026-11-03 03:56:04 +00:00
## What changed?
<!-- Describe what has changed in this PR -->
Remove license header from every file. Because it is really hard to
follow in this PR here is the summary:
1. License header is removed from all `.go` and `.proto` files
:fireworks::fireworks:🎆.
2. `LICENSE` file in the root directory has only Temporal and Uber
copyrights.
3. 5 other `LICENSE` files added to the packages which have copyrights
different from Temporal and Uber: Datadog, Xargin, "Mat Ryer, Tyler
Bunnell and contributors".
4. `license_file` flag is removed from all code generation tools.
5. `copyright_file` flag is removed from `go:generate mockgen`
directive.
6. All copyright related targets are removed from `Makefile`.
7. Updated Temporal copyright year to 2025 everywhere.
## Why?
<!-- Tell your future self why have you made these changes -->
I double checked with legal department that it is not needed to have
license header in every file. One file per repo is enough. I put all
copyrights to the root `LICENSE` file and removed header from all other
files. Also updated tools and `Makefile`.
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package shard
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
type (
|
|
OwnershipBasedQuotaScaler interface {
|
|
ScaleFactor() (float64, bool)
|
|
}
|
|
|
|
// OwnershipBasedQuotaScalerImpl scales rate-limiting quotas linearly with the fraction of the total shards in the
|
|
// cluster owned by this host. The purpose is to allocate more quota to hosts with a higher workload. This object
|
|
// can be obtained from the fx Module within this package.
|
|
OwnershipBasedQuotaScalerImpl struct {
|
|
shardCounter ShardCounter
|
|
totalNumShards int
|
|
updateAppliedCallback chan struct{}
|
|
|
|
shardCount atomic.Int64
|
|
subscription ShardCountSubscription
|
|
shutdownWG sync.WaitGroup
|
|
}
|
|
|
|
LazyLoadedOwnershipBasedQuotaScaler struct {
|
|
*atomic.Value // value type is OwnershipBasedQuotaScaler
|
|
}
|
|
|
|
// ShardCountSubscription is a subscription to a ShardCounter. It provides a channel that receives the
|
|
// shard count updates and an Unsubscribe method that unsubscribes from the counter.
|
|
ShardCountSubscription interface {
|
|
// ShardCount returns a channel that receives shard count updates.
|
|
ShardCount() <-chan int
|
|
// Unsubscribe unsubscribes from the shard counter. This closes the ShardCount channel.
|
|
Unsubscribe()
|
|
}
|
|
|
|
// ShardCounter is an observable object that emits the current shard count.
|
|
ShardCounter interface {
|
|
// SubscribeShardCount returns a ShardCountSubscription for receiving shard count updates.
|
|
SubscribeShardCount() ShardCountSubscription
|
|
}
|
|
)
|
|
|
|
var (
|
|
// shardCountNotSet is a sentinel value for the shardCount which indicates that it hasn't been set yet. It's an
|
|
// int64 because that's the type of the atomic.
|
|
shardCountNotSet int64 = -1
|
|
|
|
ErrNonPositiveTotalNumShards = errors.New("totalNumShards must be greater than 0")
|
|
)
|
|
|
|
// NewOwnershipBasedQuotaScaler returns an OwnershipBasedQuotaScaler. The updateAppliedCallback field is a channel which
|
|
// is sent to in a blocking fashion when the shard count updates are applied. This is useful for testing. In production,
|
|
// you should pass in nil, which will cause the callback to be ignored. If totalNumShards is non-positive, then an error
|
|
// is returned.
|
|
func NewOwnershipBasedQuotaScaler(
|
|
shardCounter ShardCounter,
|
|
totalNumShards int,
|
|
updateAppliedCallback chan struct{},
|
|
) (*OwnershipBasedQuotaScalerImpl, error) {
|
|
if totalNumShards <= 0 {
|
|
return nil, fmt.Errorf("%w: %d", ErrNonPositiveTotalNumShards, totalNumShards)
|
|
}
|
|
|
|
scaler := &OwnershipBasedQuotaScalerImpl{
|
|
shardCounter: shardCounter,
|
|
totalNumShards: totalNumShards,
|
|
updateAppliedCallback: updateAppliedCallback,
|
|
subscription: shardCounter.SubscribeShardCount(),
|
|
}
|
|
|
|
scaler.shardCount.Store(shardCountNotSet)
|
|
scaler.shutdownWG.Add(1)
|
|
go func() {
|
|
defer scaler.shutdownWG.Done()
|
|
|
|
for count := range scaler.subscription.ShardCount() {
|
|
scaler.shardCount.Store(int64(count))
|
|
if scaler.updateAppliedCallback != nil {
|
|
scaler.updateAppliedCallback <- struct{}{}
|
|
}
|
|
}
|
|
}()
|
|
|
|
return scaler, nil
|
|
}
|
|
|
|
func (s *OwnershipBasedQuotaScalerImpl) ScaleFactor() (float64, bool) {
|
|
shardCount := s.shardCount.Load()
|
|
if shardCount == shardCountNotSet {
|
|
return 0, false
|
|
}
|
|
|
|
return float64(shardCount) / float64(s.totalNumShards), true
|
|
}
|
|
|
|
func (s *OwnershipBasedQuotaScalerImpl) Close() {
|
|
s.subscription.Unsubscribe()
|
|
s.shutdownWG.Wait()
|
|
}
|
|
|
|
func (s LazyLoadedOwnershipBasedQuotaScaler) ScaleFactor() (float64, bool) {
|
|
if value := s.Load(); value != nil {
|
|
return value.(OwnershipBasedQuotaScaler).ScaleFactor()
|
|
}
|
|
return 0, false
|
|
}
|