glhd/bits
Generate unique 64‑bit IDs for distributed systems in PHP. Create Twitter Snowflake, Sonyflake, or custom bit-sequence identifiers with configurable worker/datacenter IDs and epoch for compact, time-ordered, collision-resistant IDs across multiple servers.
WHERE id > firstForTimestamp(now()->subDay())).BITS_DATACENTER_ID/BITS_WORKER_ID configuration aligns with Kubernetes, Laravel Vapor, or multi-AZ deployments, avoiding collisions.created_at columns.HasSnowflakes trait (replaces HasUuids).$casts = ['id' => Snowflake::class]).JsonSerializable and Query\Expression, ensuring compatibility with Laravel’s query builder and API responses.| Risk Area | Mitigation Strategy |
|---|---|
| Worker ID Conflicts | Enforce unique BITS_WORKER_ID per process (e.g., via env vars or config). |
| Epoch Mismatch | Validate BITS_EPOCH during deployment (e.g., CI/CD checks). |
| Lambda/Vapor Limits | Use Redis-backed sequence resolution for serverless (see CacheSequenceResolver). |
| Time Skew | Configure BITS_EPOCH to 2023-01-01 (default) or adjust for testing. |
| Frontend JS Limits | Cast IDs to strings for JavaScript (handled automatically via JsonSerializable). |
BITS_WORKER_ID/BITS_DATACENTER_ID be managed in dynamic environments (e.g., Kubernetes, serverless)?toCarbon() for analytics? Test performance with large datasets (e.g., 10M+ records).Bits::setTestNow() instead of Carbon::setTestNow.| Laravel Component | Integration Method |
|---|---|
| Eloquent Models | use HasSnowflakes trait or $casts = ['id' => Snowflake::class]. |
| API Responses | Automatic JSON serialization via JsonSerializable. |
| Query Builder | Query\Expression support enables direct ID comparisons (e.g., where('id', '>', ...)). |
| Livewire | Register SnowflakeSynth in AppServiceProvider for client-side ID generation. |
| Events/Jobs | Use snowflake_id() helper for concise ID generation in queues. |
| Testing | Mock Bits::setTestNow() for deterministic test IDs. |
BIGINT UNSIGNED (64-bit).HasUuids with HasSnowflakes across models.User::where('id', '>', firstForTimestamp(...))).# Set in .env
BITS_DATACENTER_ID=1
BITS_WORKER_ID=1
BITS_EPOCH=2023-01-01
composer require glhd/bits
use Glhd\Bits\Database\HasSnowflakes;
class Order extends Model
{
use HasSnowflakes;
protected $casts = ['id' => Snowflake::class];
}
$order = Order::create(['user_id' => 1]);
assert($order->id instanceof Snowflake);
assert($order->id->toCarbon()->year === 2023);
// app/Providers/AppServiceProvider.php
Livewire::propertySynthesizer(SnowflakeSynth::class);
BITS_WORKER_ID/BITS_DATACENTER_ID in dynamic environments (e.g., Kubernetes pods).BITS_EPOCH to a future date (throws exception).CacheSequenceResolver to avoid collisions.$id = Snowflake::fromString('1234567890');
$id->toCarbon(); // Extract timestamp
$id->datacenter_id; // Verify worker/datacenter
BITS_WORKER_ID is unique per process.| Scenario | Solution |
|---|---|
| Multi-Region | Assign unique BITS_DATACENTER_ID per region (0–31). |
| High Throughput | Use Redis-backed sequence resolution (CacheSequenceResolver). |
| Serverless (Vapor) | Implement locking for worker IDs or use a centralized ID service. |
| Legacy UUIDs | Use a migration script to backfill Snowflakes for existing records. |
| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Worker ID collision | Duplicate IDs | Enforce unique IDs via config. |
| Epoch misconfiguration | Invalid timestamps | Validate BITS_EPOCH in CI/CD. |
| Clock skew > 1ms | ID generation gaps | Sync NTP across servers. |
| Redis failure (sequence) | Sequence exhaustion | Fallback to in-memory resolver. |
| Database overflow (64-bit) | ID wrap-around (2269 AD) | Monitor and adjust epoch if needed. |
HasSnowflakes, toCarbon(), and Livewire integration.How can I help you explore Laravel packages today?