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

Duoclock Laravel Package

sanmai/duoclock

PSR-20 clock abstraction with dual time access (DateTimeImmutable, time(), microtime()) plus mockable sleep/usleep/nanosleep for testing. Includes deterministic TimeSpy and tick helpers to measure elapsed time. Minimal dependency (psr/clock) and easy to mock.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install via Composer:
    composer require sanmai/duoclock
    
  2. Core Concepts:
    • DualClock holds two coordinated clocks: local (e.g., app server) and remote (e.g., external service/API).
    • Clocks are represented as ClockSource instances (e.g., LocalClock, RemoteClock).
  3. First Use Case: Synchronize a client timestamp with server time in a webhook handler:
    use Sanmai\Duoclock\DualClock;
    use Sanmai\Duoclock\Source\LocalClock;
    use Sanmai\Duoclock\Source\RemoteClock;
    
    $clock = new DualClock(
        LocalClock::fromDateTime(new \DateTimeImmutable()),
        RemoteClock::fromString($webhookHeader['X-Client-Timestamp'])
    );
    

Implementation Patterns

  • Laravel Service Binding (in a service provider):
    $this->app->singleton(DualClock::class, function () {
        $local = LocalClock::fromCurrent();
        $remote = RemoteClock::fromConfig(config('services.external.time_offset'));
        return new DualClock($local, $remote);
    });
    
  • In a Job/Service: Normalize incoming external timestamps:
    public function handle(DualClock $clock)
    {
        $clientTime = $clock->normalizeTo('remote', $incomingTimestamp); // $incomingTimestamp is local-time
        $event = new Event(['scheduled_at' => $clientTime]);
    }
    
  • Drift Monitoring: Log clock drift over time in health checks:
    $drift = $clock->drift()->getTotalSeconds();
    if (abs($drift) > 5) {
        throw new \RuntimeException("Clock drift exceeded 5s: {$drift}s");
    }
    
  • Testing: Stub remote time deterministically in tests:
    $clock = new DualClock(
        LocalClock::fromString('2025-01-01 12:00:00'),
        RemoteClock::fromString('2025-01-01 12:00:10') // remote is 10s ahead
    );
    

Gotchas and Tips

  • ⚠️ Initialization matters: RemoteClock must be constructed before or with known offset; don’t assume remote time is ever “now” unless you’ve verified sync.
  • Drift ≠ offset: Use offset() for static calibration (e.g., config-based), and drift() for observed deviation over time.
  • Mutable vs Immutable: All returned times are DateTimeImmutable; avoid reusing instances across threads or async flows.
  • Serialization: DualClock isn’t serializable. Store only the offset() or drift() data if needed (e.g., in job payload).
  • Extension point: Implement custom ClockSource for HTTP time sources (e.g., NTP, API Date header) — RemoteClock is generic but not opinionated about source.
  • Debugging tip: Enable DualClock::debug() (if available in future) or log $clock->drift() at the start of long-running tasks to catch gradual drift.
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport