semaphore

package
v1.4.3-prerelease05 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NumBuckets

func NumBuckets(size, bucketSize int) (int, error)

NumBuckets returns how many buckets a semaphore is split into: ceil(size / bucketSize).

func OwnerIDToBucket

func OwnerIDToBucket(ownerID string, numBuckets int) (int, error)

OwnerIDToBucket returns the bucket that serves the given owner_id.

The acquire and the later release for one owner_id each compute this separately, so they must get the same answer. Never change the hash or add a seed: a release sent to a different bucket cannot free the slot its acquire took. For the same reason, numBuckets must come from NumBuckets on the semaphore's stored size and bucket_size, which never change after creation.

func RingKey

func RingKey(domainID, semaphoreName string, bucket int) string

RingKey returns the key used to look up a bucket's Matching host on the membership ring.

The caller uses it to choose a host, and that host uses it to check it still owns the bucket. Both must build the same key, or the host refuses every request.

Types

type Owner

type Owner struct {
	// WorkflowID is the user-supplied workflow name, so it can hold any byte, separator
	// included.
	WorkflowID string
	// RunID is the server-generated UUID for one execution of that workflow; a retry, a cron
	// fire, or a continue-as-new is a new run with a new id. A hold belongs to the run, not
	// to the workflow name.
	RunID string
	// HoldID is the id of the event that started the acquire. Taking it from the run's
	// history rather than minting one is what lets an owner_id survive replay, retries,
	// and failover. Event ids start at 1, though the encoding does not enforce it.
	HoldID int64
}

Owner identifies one hold on a semaphore: a specific run, and which of that run's holds.

func ParseOwner

func ParseOwner(ownerID string) (Owner, error)

ParseOwner takes an owner_id back apart into the three ids that built it.

It reads the digits before the first separator as the byte length of WorkflowID, takes exactly that many bytes verbatim, then splits what is left on its last separator into RunID and HoldID. Both string fields may therefore contain separators.

It accepts only the spellings String produces: "7", never "007" or "+7", though a negative HoldID keeps its minus.

func (Owner) String

func (o Owner) String() string

String returns the canonical owner_id string:

<byteLen(WorkflowID)> ":" <WorkflowID> ":" <RunID> ":" <HoldID>

The length prefix is what makes the string splittable again. WorkflowID is user-supplied and may contain the separator, so a plain join could not be taken apart; giving its byte length up front lets a reader skip over it without interpreting its contents.

semaphore_tokens stores this string twice: as the token row's holder column and as the owner row's owner_id key. ReleaseSemaphoreToken guards its write on `IF holder = ?` with it, and Cassandra compares text bytewise. So one hold must have exactly one byte form — a release that supplies a string differing by a single byte matches nothing and silently leaves the slot held with no live run behind it.

RunID needs no prefix of its own. HoldID is a decimal number, so the last separator in the string is always the one in front of it, and everything between the workflow id and that separator is the run id, whatever bytes it holds. Every Owner therefore has an encoding and String cannot fail.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL