Skip to content

Instantly share code, notes, and snippets.

@MisterFixx
Last active August 12, 2019 13:41
Show Gist options
  • Save MisterFixx/54570994f44373e89365ba8ca938a7a0 to your computer and use it in GitHub Desktop.
Save MisterFixx/54570994f44373e89365ba8ca938a7a0 to your computer and use it in GitHub Desktop.
Php class to fetch snowflakes from JSnowflake (https://github.com/MisterFixx/JSnowflake)
<?php
/**
* Snowflake.php
*
* Licensed under The MIT License
* @author Mister_Fix <me@misterfix.io>
* @package Snowflake
* @version v 2.0
* @license MIT License
*
* NOTE: This will only work properly on 64 bit versions of PHP, because Snowflakes are 64 bit integers.
*/
class Snowflake{
/**
* Last fetched snowflake
*/
private $lastSnowflake = 0;
/**
* If a socket has already been opened, it will be stored here so we don't have to open another one wasting time.
*/
private $socket = null;
/**
* The data to write to the socket each time a Snowflake is needed
*/
private $socketData = null;
/**
* The lenth of the data aforementioned data
*/
private $dataLength = 0;
/**
* Initiate a connection to the Snowflake server
*/
public function __construct($host = 'localhost:9098'){
$this->socket = stream_socket_client("tcp://{$host}");
$this->socketData = pack('N*', 1);
$this->dataLength = strlen($this->socketData);
return $this;
}
/**
* Fetches a single snowflake
* @param string (Optional Snowflake server address)
* @return int (The Snowflake)
*/
public function nextId():int{
if ($this->socket != false) {
fwrite($this->socket, $this->socketData, $this->dataLength);
$this->lastSnowflake = unpack("J", fread($this->socket, 8))[1];
return $this->lastSnowflake;
}
else {
throw new RuntimeException('Unable to connect to Snowflake service');
}
}
/**
* Returns the last generated snowflake
* @return int The last returned Snowflake
*/
public function getLastId():int{
return $this->lastSnowflake;
}
/**
* Returns the creation timestamp of a given snowflake
* @param int Snowflake
* @param int (Optional) epoch of the snowflake
* @return int java timestamp of Snowflake's creation time
* To convert to php timestamp divide by 1000
*/
public function getIdCreationTime($snowflake, $epoch = 1436077819000):int{
return ($snowflake >> 22)+$epoch;
}
/**
* Returns the datacenter ID at which the given snowflake was generated.
* @param int Snowflake
* @return int Snowflake's Datacenter ID
*/
public function getDatacenterId($snowflake):int{
return $snowflake >> 17 & 31;
}
/**
* Returns the instance ID at which the given snowflake was generated.
* @param int Snowflake
* @return int Snowflake's Instance ID
*/
public function getInstanceId($snowflake):int{
return $snowflake >> 12 & 31;
}
/**
* Returns the sequential number of the given snowflake.
* @param int Snowflake
* @return int Snowflake's Sequential number
*/
public function getSequentialNumber($snowflake):int{
return $snowflake >> 0 & 4095;
}
}
//Example & Benchmark
$snowflake = new Snowflake();
$time_start = microtime(true);
for($i = 0; $i < 10000; $i++){
$snowflake->nextId();
}
$time_stop = microtime(true);
$id = $snowflake->nextId();
echo "Snowflake: ".$id."<br /><br />";
echo "Created at: ".gmdate("Y-m-d H:i:s", $snowflake->getIdCreationTime($id)/1000)."<br />";
echo "Datacenter ID: ".$snowflake->getDatacenterId($id)."<br />";
echo "Instance ID: ".$snowflake->getInstanceId($id)."<br />";
echo "Sequential Number: ".$snowflake->getSequentialNumber($id)."<br /><br />";
echo "Time to get 10k Snowflakes: ".($time_stop-$time_start)." seconds<br />";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment