Documentation
¶
Overview ¶
SCRU64: Sortable, Clock-based, Realm-specifically Unique identifier
SCRU64 ID offers compact, time-ordered unique identifiers generated by distributed nodes. SCRU64 has the following features:
- 63-bit non-negative integer storable as signed/unsigned 64-bit integer
- Sortable by generation time (as integer and as text)
- 12-digit case-insensitive textual representation (Base36)
- ~38-bit Unix epoch-based timestamp that ensures useful life until year 4261
- Variable-length node/machine ID and counter fields that share 24 bits
See SCRU64 Specification for details: https://github.com/scru64/spec
Index ¶
- Variables
- func NewString() string
- type CounterMode
- type CounterModeRenewContext
- type Generator
- func (g *Generator) Generate() (Id, error)
- func (g *Generator) GenerateOrAbortCore(unixTsMs uint64, rollbackAllowance uint64) (Id, error)
- func (g *Generator) GenerateOrReset() Id
- func (g *Generator) GenerateOrResetCore(unixTsMs uint64, rollbackAllowance uint64) Id
- func (g *Generator) GenerateOrSleep() Id
- func (g *Generator) NodeId() uint32
- func (g *Generator) NodeIdSize() uint8
- func (g *Generator) NodeSpec() NodeSpec
- type Id
- type NodeSpec
Constants ¶
This section is empty.
Variables ¶
var ErrClockRollback = fmt.Errorf(
"scru64.Generator: detected unbearable clock rollback")
The error value returned by Generator.Generate and Generator.GenerateOrAbortCore when the relevant timestamp is significantly smaller than the one embedded in the immediately preceding ID generated by the generator.
var GlobalGenerator interface { // Initializes the global generator, if not initialized, with the node spec // passed. // // This method configures the global generator with the argument only when the // global generator is not yet initialized. Otherwise, it preserves the // existing configuration. // // This method return `true` if this method configures the global generator or // `false` if it preserves the existing configuration. Initialize(nodeSpec NodeSpec) bool // Calls `Generator.Generate` of the global generator. Generate() (Id, error) // Calls `Generator.GenerateOrSleep` of the global generator. GenerateOrSleep() Id // Calls `Generator.NodeId` of the global generator. NodeId() uint32 // Calls `Generator.NodeIdSize` of the global generator. NodeIdSize() uint8 // Calls `Generator.NodeSpec` of the global generator. NodeSpec() NodeSpec } = &globalGeneratorInner{}
The gateway object that forwards supported method calls to the process-wide global generator.
By default, the global generator reads the node configuration from the `SCRU64_NODE_SPEC` environment variable when a generator method is first called, and it panics if it fails to do so. The node configuration is encoded in a node spec string consisting of `nodeId` and `nodeIdSize` integers separated by a slash (e.g., "42/8", "0xb00/12"; see NodeSpec for details). You can configure the global generator differently by calling `GlobalGenerator.initialize` before the default initializer is triggered.
Functions ¶
func NewString ¶
func NewString() string
Generates a new SCRU64 ID encoded in the 12-digit canonical string representation using the global generator.
By default, the global generator reads the node configuration from the `SCRU64_NODE_SPEC` environment variable when a generator method is first called, and it panics if it fails to do so. The node configuration is encoded in a node spec string consisting of `nodeId` and `nodeIdSize` integers separated by a slash (e.g., "42/8", "0xb00/12"; see NodeSpec for details). You can configure the global generator differently by calling `GlobalGenerator.Initialize()` before the default initializer is triggered.
This function usually returns a value immediately, but if not possible, it sleeps and waits for the next timestamp tick.
This function is thread-safe; multiple threads can call it concurrently.
This function panics if the global generator is not properly configured.
Types ¶
type CounterMode ¶
type CounterMode interface {
// Returns the next initial counter value of `counterSize` bits.
//
// `Generator` passes the `counterSize` (from 1 to 23) and other context
// information that may be useful for counter renewal. The returned value must
// be within the range of `counterSize`-bit unsigned integer.
Renew(counterSize uint8, context CounterModeRenewContext) uint32
}
An interface to customize the initial counter value for each new `timestamp`.
Generator calls `Renew()` to obtain the initial counter value when the `timestamp` field has changed since the immediately preceding ID. Types implementing this interface may apply their respective logic to calculate the initial counter value.
func NewDefaultCounterMode ¶
func NewDefaultCounterMode(overflowGuardSize uint8) CounterMode
Creates a new instance of the default "initialize a portion counter" mode with the size (in bits) of overflow guard bits.
With this mode, the counter is reset to a random number for each new `timestamp` tick, but some specified leading bits are set to zero to reserve space as the counter overflow guard.
Note that the random number generator employed is not cryptographically strong. This mode does not pay for security because a small random number is insecure anyway.
type CounterModeRenewContext ¶
type CounterModeRenewContext struct {
// The `timestamp` value for the new counter.
Timestamp uint64
// The `nodeId` of the generator.
NodeId uint32
}
Represents the context information provided by Generator to `CounterMode.Renew`.
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Represents a SCRU64 ID generator.
This structure must be instantiated by one of the dedicated constructors: NewGenerator, NewGeneratorParsing, or NewGeneratorWithCounterMode.
The generator comes with several different methods that generate a SCRU64 ID:
| Flavor | Timestamp | Thread- | On big clock rewind | | ------------------- | --------- | ------- | ------------------- | | Generate | Now | Safe | Returns error | | GenerateOrReset | Now | Safe | Resets generator | | GenerateOrSleep | Now | Safe | Sleeps | | GenerateOrAbortCore | Argument | Unsafe | Returns error | | GenerateOrResetCore | Argument | Unsafe | Resets generator |
All of these methods return a monotonically increasing ID by reusing the previous `timestamp` even if the one provided is smaller than the immediately preceding ID's, unless such a clock rollback is considered significant (by default, approx. 10 seconds). A clock rollback may also be detected when a generator has generated too many IDs within a certain unit of time, because this implementation increments the previous `timestamp` when `counter` reaches the limit to continue instant monotonic generation. When a significant clock rollback is detected:
- `Generate` (OrAbort) methods abort and return the ErrClockRollback error value immediately.
- `OrReset` variants reset the generator and return a new ID based on the given `timestamp`, breaking the increasing order of IDs.
- `OrSleep` method sleeps and waits for the next timestamp tick.
The `Core` functions offer low-level thread-unsafe primitives to customize the behavior.
func NewGenerator ¶
Creates a new generator with the given node configuration.
func NewGeneratorParsing ¶
Creates a new generator by parsing the given node spec string.
This is a shortcut constructor that chains ParseNodeSpec and NewGenerator for convenience, panicking if the argument is not a valid node spec string.
func NewGeneratorWithCounterMode ¶
func NewGeneratorWithCounterMode( nodeSpec NodeSpec, counterMode CounterMode) *Generator
Creates a new generator with the given node configuration and counter initialization mode.
This constructor panics if `counterMode` is nil.
func (*Generator) Generate ¶
Generates a new SCRU64 ID object from the current `timestamp`, or returns an error upon significant timestamp rollback.
See the Generator type documentation for the description.
This method returns the ErrClockRollback error upon significant clock rollback.
func (*Generator) GenerateOrAbortCore ¶
Generates a new SCRU64 ID object from a Unix timestamp in milliseconds, or returns an error upon significant timestamp rollback.
See the Generator type documentation for the description.
The `rollbackAllowance` parameter specifies the amount of `unixTsMs` rollback that is considered significant. A suggested value is `10_000` (milliseconds).
Unlike Generator.Generate, this method is NOT thread-safe. The generator object should be protected from concurrent accesses using a mutex or other synchronization mechanism to avoid race conditions.
This method returns the ErrClockRollback error upon significant clock rollback.
This method panics if `unixTsMs` is not a positive integer within the valid range.
func (*Generator) GenerateOrReset ¶
Generates a new SCRU64 ID object from the current `timestamp`, or resets the generator upon significant timestamp rollback.
See the Generator type documentation for the description.
Note that this mode of generation is not recommended because rewinding `timestamp` without changing `nodeId` considerably increases the risk of duplicate results.
func (*Generator) GenerateOrResetCore ¶
Generates a new SCRU64 ID object from a Unix timestamp in milliseconds, or resets the generator upon significant timestamp rollback.
See the Generator type documentation for the description.
Note that this mode of generation is not recommended because rewinding `timestamp` without changing `nodeId` considerably increases the risk of duplicate results.
The `rollbackAllowance` parameter specifies the amount of `unixTsMs` rollback that is considered significant. A suggested value is `10_000` (milliseconds).
Unlike Generator.GenerateOrReset, this method is NOT thread-safe. The generator object should be protected from concurrent accesses using a mutex or other synchronization mechanism to avoid race conditions.
This method panics if `unixTsMs` is not a positive integer within the valid range.
func (*Generator) GenerateOrSleep ¶
Returns a new SCRU64 ID object, or sleeps and waits for one if not immediately available.
See the Generator type documentation for the description.
func (*Generator) NodeIdSize ¶
Returns the size in bits of the `nodeId` adopted by the generator.
type Id ¶
type Id uint64
Represents a SCRU64 ID.
const MaxId Id = 4738381338321616895
The maximum valid SCRU64 ID value (i.e., `zzzzzzzzzzzz`).
const MinId Id = 0
The minimum valid SCRU64 ID value (i.e., `000000000000`).
func FromParts ¶
Creates a value from the `timestamp` and the combined `nodeCtr` field value.
This function returns a non-nil error if any argument is larger than their respective maximum value (`36^12 / 2^24 - 1` and `2^24 - 1`, respectively).
func FromUint ¶
Creates a value from a 64-bit unsigned integer.
This function returns a non-nil error if the argument is larger than `36^12 - 1`.
func New ¶
func New() Id
Generates a new SCRU64 ID object using the global generator.
By default, the global generator reads the node configuration from the `SCRU64_NODE_SPEC` environment variable when a generator method is first called, and it panics if it fails to do so. The node configuration is encoded in a node spec string consisting of `nodeId` and `nodeIdSize` integers separated by a slash (e.g., "42/8", "0xb00/12"; see NodeSpec for details). You can configure the global generator differently by calling `GlobalGenerator.Initialize()` before the default initializer is triggered.
This function usually returns a value immediately, but if not possible, it sleeps and waits for the next timestamp tick.
This function is thread-safe; multiple threads can call it concurrently.
This function panics if the global generator is not properly configured.
func Parse ¶
Creates a value from a 12-digit string representation.
This function returns a non-nil error if the argument is not a valid string representation.
func (Id) MarshalText ¶
See encoding.TextMarshaler
func (Id) NodeCtr ¶
Returns the `nodeId` and `counter` field values combined as a single 24-bit integer.
func (*Id) UnmarshalText ¶
See encoding.TextUnmarshaler
type NodeSpec ¶
type NodeSpec struct {
// contains filtered or unexported fields
}
Represents a node configuration specifier used to build a Generator.
A `NodeSpec` is usually expressed as a node spec string, which starts with a decimal `nodeId`, a hexadecimal `nodeId` prefixed by "0x", or a 12-digit `nodePrev` SCRU64 ID value, followed by a slash and a decimal `nodeIdSize` value ranging from 1 to 23 (e.g., "42/8", "0xb00/12", "0u2r85hm2pt3/16"). The first and second forms create a fresh new generator with the given `nodeId`, while the third form constructs one that generates subsequent SCRU64 IDs to the `nodePrev`. See also the usage notes in the SCRU64 spec for tips and techniques to design node configurations.
func NewNodeSpecWithNodeId ¶
Creates an instance of NodeSpec with `nodeId` and `nodeIdSize` values.
This function returns a non-nil error if the `nodeIdSize` is zero or greater than 23 or if the `nodeId` does not fit in `nodeIdSize` bits.
func NewNodeSpecWithNodePrev ¶
Creates an instance of NodeSpec with `nodePrev` and `nodeIdSize` values.
This function returns a non-nil error if the `nodeIdSize` is zero or greater than 23.
func ParseNodeSpec ¶
Creates an instance of NodeSpec from a node spec string.
This function returns a non-nil error if if an invalid node spec string is passed.
func (NodeSpec) MarshalText ¶
See encoding.TextMarshaler
func (NodeSpec) NodeId ¶
Returns the `nodeId` value given at instance creation or encoded in the `nodePrev` value.
func (NodeSpec) NodePrev ¶
Returns the `nodePrev` value if the `NodeSpec` is constructed with one or the zero value (`scru64.Id(0)`) otherwise.
func (*NodeSpec) UnmarshalText ¶
See encoding.TextUnmarshaler