| package lockr | |
| import ( | |
| "errors" | |
| "fmt" | |
| "strings" | |
| xxhash "github.com/zeebo/xxh3" | |
| ) | |
| var stringSeparator = ":" | |
| // Key is a unique identifier for a resource and a scope that can be locked | |
| type Key interface { | |
| String() string | |
| Hash64() uint64 | |
| } | |
| // NewKey constructs a key for the given scopes. | |
| // Scope is always required and must be non-empty. | |
| func NewKey(scopes ...string) (Key, error) { | |
| if len(scopes) == 0 { | |
| return nil, errors.New("at least one scope is required") | |
| } | |
| for idx, s := range scopes { | |
| if s == "" { | |
| return nil, fmt.Errorf("scope cannot be empty [index=%d]", idx) | |
| } | |
| if strings.Contains(s, stringSeparator) { | |
| return nil, fmt.Errorf("scope cannot contain %q [index=%d]", stringSeparator, idx) | |
| } | |
| } | |
| return &key{scopes: scopes}, nil | |
| } | |
| type key struct { | |
| scopes []string | |
| } | |
| var _ Key = (*key)(nil) | |
| func (k *key) String() string { | |
| return strings.Join(k.scopes, stringSeparator) | |
| } | |
| // Hash64 translates the key string to a 64bit keyspace via hashing it | |
| func (k *key) Hash64() uint64 { | |
| h := xxhash.New() | |
| _, _ = h.WriteString(k.String()) | |
| return h.Sum64() | |
| } | |