Skip to content

Conversation

@jb-needhelp
Copy link
Contributor

Automatically synchronize Clock::$globalClock with the injected clock instance, eliminating the need for manual Clock::set() calls in test environments.

Why is this change proposed?

Problem

When using a custom clock (e.g., a static clock for testing) with \Ecotone\Messaging\Scheduling\Clock, the global clock remains unsynchronized. This causes incorrect timestamps in message headers created via MessageHeaders::createMessageHeadersWith().
Currently, the workaround requires calling Clock::set() explicitly in each test case, which leaks internal implementation details into application tests.

Solution

Set $globalClock automatically when a Clock instance is constructed:

If an internal clock is provided → use it as the global clock
Otherwise → default to NativeClock

This allows applications to define their own PsrClockInterface implementation without manual global clock management.

Cleaner Solution

A cleaner long-term solution would be removing the deprecated Clock::get() method entirely and replace it with Clockinstance. However, this creates a cascade of changes, particularly around DelayableQueueChannel which calls MessageBuilder::fromMessage($message) without access to a Clock instance.

Description of Changes

  • Ecotone\Messaging\Scheduling\Clock: Auto-set $globalClock on construction; added resetGlobalClock() for test teardown
  • Test\Ecotone\Messaging\Unit\Scheduling\StaticGlobalClockTest: Verify expected behavior

Pull Request Contribution Terms

  • I have read and agree to the contribution terms outlined in CONTRIBUTING.

$this->assertInstanceOf(Clock::class, $globalClock);
$this->assertEquals('2025-08-11 16:00:00', $globalClock->now()->format('Y-m-d H:i:s'));
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide test case with delay message using new clock strategy?

So similar test to this, but by changing time using clock

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this separate test: DelayedMessageAgainstGlobalClockTest

return self::$globalClock ??= self::defaultClock();
}

public static function resetGlobalClock(): void
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static function resetGlobalClock(): void
public static function resetToNativeClock(): void

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion applied

- Add `PlaceOrder`, `OrderWasPlaced`, `OrderService`, and `NotificationService` test fixtures.
- Improve `Clock` initialization to ensure `globalClock` is only set when unset.
- Rename `resetGlobalClock` to `resetToNativeClock` for better clarity.
- Add `StaticPsrClock` implementation for static clock testing.
- Create `DelayedMessageAgainstGlobalClockTest` to validate delay handling against clock changes.
- Update and refactor existing clock-related tests for consistency.
{
$ecotoneTestSupport = EcotoneLite::bootstrapFlowTesting(
[EcotoneClockInterface::class, OrderService::class, NotificationService::class, CustomNotifier::class],
[$clock = new Clock(new StaticPsrClock('2025-08-11 16:00:00')), new OrderService(), new NotificationService(), $notifier = new CustomNotifier()],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dgafka just out of curiosity, can you explain why instance of EcotoneClockInterface on this test is reinstantiated? It's the reason why I added this if condition in Clock::__constructor();

        if (!self::$globalClock) {
            self::$globalClock = $this->clock ? $this : self::defaultClock();
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants