Skip to content

codemouse/raindrop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Raindrop

NPM version Downloads

Build Status

Coverage Status

Dependency status devDependency Status

Raindrop is a distributed id generation utility that mimics the MongoDB BSON ObjectID implementation, with a few key tweaks.

The Raindrop is a 24 character hex string that is automatically encoded into a compact 16 character string represented with the following alphabet:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_

The core hex identifier is represented with the following attributes:

  • 4-byte value representing the seconds since the Unix epoch (32-bit timestamp down to the second)
  • 3-byte process identifier (defaults to random value or user input)
  • 1-byte service id (defaults to 0 or user input)
  • 1-byte entity type id (defaults to 0 or user input)
  • 3-byte incremental counter, reset every second to a random start value

This means the physical structure of the identifier's 5 components is:

FFFFFFFF FFFFFF FF FF FFFFFF

Note: Once the 3-byte incremental counter hits the medium int maximum (12,777,215), it will roll over to 0 and start again

Raindrop is entirely deconstructable into its core values, to allow for the id to travel with key information regarding service origination id and domain-specific entity type identifiers.

Chance of collisions

Raindrops that are generated are highly likely to be unique across collections. The 3-byte incrementing counter is set to a random value every second an operation is performed. Therefore, a total of 16,777,215 unique ids could be inserted every second with the same unique process id and the same service id, without chance of collision.

As long as process id remains unique amongst all of your running processes, and your service id is always registered as being unique, and you do not try to store more than 16,777,215 ids per second, per process id, per service id, you will avoid collisions.

It's recommended to have your service instance pass in a process id likely a combination of machine identifier along with a process id such as a PM2 cluster process identifier.

Motivation

You may be asking yourself, why not just use a GUID? Or perhaps a UUID generator? Isn't that good enough? Maybe. But what if you care about storing some embedded internal domain specific data within your identifier? Why not have your identifier provide some information to help you out? Raindrop gives you:

  • Embeddable user-defined information to store 2 bytes of custom information, highly applicable across a tightly controlled service environment. Embed a marker with these attributes on issuing the id to help assist with type and service lookups later on.
  • Avoid unnecessary lookups to your data store to determine service issuer and entity type. Create efficiency and optimization by decoding and parsing the information inline as you receive it.
  • Reduces the overall id storage footprint by 32 bits over UUID.Raindrop is 96-bit, UUID is 128-bit. This can improve overall data storage efficiency.
  • Uses a custom URL-safe alphabet beyond hex to shrink the represented string even further to just 16 characters. UUID/GUID will contain 32-38 characters. This is ideal where sending lengthy strings in URLs or message strings can impact performance.
  • Based on an established distributed ID generation system in used by MongoDB. This is not reinventing the wheel; it's just painting the wheel a different color.

Install

$ npm install raindrop

Usage

'use strict'

const raindrop = require('../lib/raindrop')

// set options for entityTypeId (0 - 255)
// set options for processId (0 - 16777215)
// set options for serviceId (0 - 255)
const options = {
  'entityTypeId': 4,
  'processId': 7844,
  'serviceId': 1
}

// create new raindrop with options
const drop = raindrop(options)

// get Raindrop object
console.log(drop)

// get Raindrop version info (returns Raindrop object version)
console.log(`version: ${drop.version}`)

// get Raindrop object id as 16 character string
console.log(drop.id)

// get Raindrop object as 24 character hex string
console.log(drop.hexId)

// get Raindrop object materials property
console.log(drop.materials)

// get Raindrop object decoded properties
console.log(drop.decoded())

// get timestamp portion up to the second as ISO 8601 date from UTC
console.log(`timestamp: ${drop.decoded().timestamp}`)

// get entity type id decoded
console.log(`entity type id: ${drop.decoded().entityTypeId}`)

// get process id decoded
console.log(`process id: ${drop.decoded().processId}`)

// get service id decoded
console.log(`service id: ${drop.decoded().serviceId}`)

// get counter for that 1 second timestamp range decoded
console.log(`counter: ${drop.decoded().counter}`)

// see if one Raindrop object equals another

// true
console.log(drop.equals(drop))

const drop2 = raindrop(options)

// false
console.log(drop.equals(drop2))

License

MIT ©2016 codemouse

About

A distributed id generation utility

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published