Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Snowflake Laravel Package

godruoyi/php-snowflake

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require godruoyi/php-snowflake
    

    For Redis/Predis/Swoole support, install additional dependencies as needed (see README).

  2. First Use Case: Generate a basic Snowflake ID in a Laravel controller or service:

    use Godruoyi\Snowflake\Snowflake;
    
    $snowflake = new Snowflake();
    $id = $snowflake->id(); // e.g., 1537200202186752
    
  3. Where to Look First:

    • Default Behavior: The package auto-generates datacenterId and workerId (0–31) if not set (since v3.2.0).
    • Key Methods:
      • setStartTimeStamp(): Optimize timestamp range (e.g., strtotime('2023-01-01') * 1000).
      • setSequenceResolver(): Choose concurrency strategy (e.g., RedisSequenceResolver for distributed systems).
    • Laravel Integration: Register as a singleton in AppServiceProvider (see Advanced).

Implementation Patterns

Core Workflows

  1. Basic ID Generation:

    $snowflake = new Snowflake($datacenterId, $workerId);
    $id = $snowflake->id(); // 64-bit integer
    
    • Use Case: Replace Str::uuid() or DB::raw('AUTO_INCREMENT') in models/services.
  2. Laravel Service Container:

    // config/snowflake.php
    return [
        'start_timestamp' => strtotime('2023-01-01') * 1000,
        'datacenter_id'  => env('SNOWFLAKE_DATACENTER_ID', 1),
        'worker_id'      => env('SNOWFLAKE_WORKER_ID', 1),
    ];
    
    // AppServiceProvider.php
    $this->app->singleton(Snowflake::class, function ($app) {
        $config = config('snowflake');
        $snowflake = new Snowflake($config['datacenter_id'], $config['worker_id']);
        return $snowflake->setStartTimeStamp($config['start_timestamp']);
    });
    
    • Use Case: Centralized ID generation across microservices.
  3. Distributed Systems:

    // Using Redis for concurrency safety
    $snowflake = new Snowflake();
    $snowflake->setSequenceResolver(new RedisSequenceResolver($redisClient, 'snowflake:lock'));
    $id = $snowflake->id();
    
    • Use Case: Kubernetes pods or auto-scaled workers where file locks (FileLockResolver) are impractical.
  4. Sonyflake for Non-Time-Based IDs:

    $sonyflake = new Sonyflake();
    $id = $sonyflake->id(); // Non-time-based, 64-bit
    
    • Use Case: IDs where timestamp embedding isn’t required (e.g., internal tracking).

Integration Tips

  • Database Schemas: Use BIGINT UNSIGNED for storage (e.g., id bigint unsigned primary key).

    CREATE TABLE users (
        id BIGINT UNSIGNED NOT NULL PRIMARY KEY,
        name VARCHAR(255),
        created_at TIMESTAMP
    );
    
  • Event Sourcing: Embed Snowflake IDs in event payloads for traceability:

    $event = new UserRegisteredEvent(
        id: $snowflake->id(),
        userId: $user->id,
        metadata: [...]
    );
    
  • Caching: Cache Snowflake instances in Laravel’s cache store for high-throughput scenarios:

    $snowflake = Cache::remember('snowflake_instance', 3600, function () {
        return new Snowflake($datacenterId, $workerId);
    });
    
  • Testing: Mock the SequenceResolver interface for unit tests:

    $mockResolver = $this->createMock(SequenceResolver::class);
    $mockResolver->method('sequence')->willReturn(42);
    $snowflake->setSequenceResolver($mockResolver);
    

Gotchas and Tips

Pitfalls

  1. Timestamp Skew:

    • If setStartTimeStamp() isn’t configured, the package uses the current time, risking collisions if the system clock is adjusted.
    • Fix: Set a fixed start timestamp (e.g., deployment date) to maximize the 69-year range.
    $snowflake->setStartTimeStamp(strtotime('2023-01-01') * 1000);
    
  2. Sequence Collisions:

    • The default RandomSequenceResolver is not thread-safe and may cause duplicates in concurrent environments.
    • Fix: Use FileLockResolver, RedisSequenceResolver, or LaravelSequenceResolver for production.
    $snowflake->setSequenceResolver(new FileLockResolver('/tmp/snowflake.lock'));
    
  3. Datacenter/Worker ID Limits:

    • IDs are 5 bits each (max 31). Exceeding this throws an exception.
    • Fix: Validate IDs during deployment or use environment variables:
    $datacenterId = max(0, min(31, env('SNOWFLAKE_DATACENTER_ID', 1)));
    
  4. Sonyflake vs. Snowflake:

    • Sonyflake does not embed timestamps, making it unsuitable for time-based sorting or analytics.
    • Use Case: Only for non-temporal IDs (e.g., internal references).
  5. PHP 8.1+ Requirement:

    • Older PHP versions may fail due to type hints or bytecode changes.
    • Fix: Upgrade or use a legacy branch (if available).

Debugging

  • ID Parsing: Use the parse() method to extract components from an ID:

    $parsed = $snowflake->parse($id);
    // Returns: [
    //     'timestamp' => 1537200202186,
    //     'datacenterId' => 1,
    //     'workerId' => 1,
    //     'sequence' => 752
    // ]
    
    • Use Case: Debugging or validating IDs in logs.
  • Clock Drift: If IDs appear out of order, check system time synchronization:

    timedatectl status  # Linux
    
    • Fix: Use NTP or adjust setStartTimeStamp() to account for drift.

Extension Points

  1. Custom Sequence Resolver: Implement Godruoyi\Snowflake\SequenceResolver for bespoke concurrency control:

    class DatabaseSequenceResolver implements SequenceResolver
    {
        public function sequence(int $currentMillisecond): int
        {
            return DB::table('snowflake_sequences')
                ->where('millisecond', $currentMillisecond)
                ->increment('sequence', 1);
        }
    }
    
  2. Time Resolver: Override timestamp logic (e.g., for testing or custom clocks):

    $snowflake->setTimeResolver(function () {
        return time() * 1000; // Milliseconds
    });
    
  3. Laravel Cache Prefix: Customize the cache key prefix for LaravelSequenceResolver:

    $resolver = new LaravelSequenceResolver($cache, 'custom_');
    $snowflake->setSequenceResolver($resolver);
    

Performance Tips

  • Batch Generation: Pre-generate IDs in bulk for offline processing (e.g., data migration):

    $ids = [];
    for ($i = 0; $i < 1000; $i++) {
        $ids[] = $snowflake->id();
    }
    
  • Avoid Lock Contention: For high-throughput systems, use RedisSequenceResolver with a dedicated Redis instance:

    $redis = Redis::connection('snowflake');
    $snowflake->setSequenceResolver(new RedisSequenceResolver($redis, 'snowflake:seq'));
    
  • Swoole Optimization: In Swoole coroutines, use SwooleSequenceResolver for lock-free concurrency:

    $snowflake->setSequenceResolver(new SwooleSequenceResolver());
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony