このプロジェクトは、ペーパーで定義されているベクトルクロックとランパートタイムスタンプの概念のPHP実装です。部分的な順序を保持するメッセージパスシステムのタイムスタンプ(Paper/Vector-Crock-Paper.pdf)。
このライブラリは次のとおりです。
これらの実装は、研究論文を慎重に追跡し、すべてのクラスが完全にテストされています(100%カバレッジ)。
論文に存在するすべての例は、phpunitテストとして転写されます。
composer require dynamophp/vector-clock <?php
$ lt1 = new LamportTimestamp ( 76 );
$ lt2 = new LamportTimestamp ( 59 );
assertEquals ( 76 , lt1-> getValue ());
assertEquals ( 59 , lt2-> getValue ());
assertTrue ( $ lt1 -> happenAfter ( $ lt2 )); // lt2 -> lt1
assertTrue ( $ lt2 -> happenBefore ( $ lt1 ));
$ lt1 -> applyLocalEvent ();
$ lt2 -> applyLocalEvent ();
assertEquals ( 77 , lt1-> getValue ());
assertEquals ( 60 , lt2-> getValue ());
assertTrue ( $ lt1 -> happenAfter ( $ lt2 )); // lt2 -> lt1
assertTrue ( $ lt2 -> happenBefore ( $ lt1 ));
$ lt1ToSend = clone $ lt1 -> applySendEvent ();
$ lt2 -> applyLocalEvent ();
assertEquals ( 78 , lt1-> getValue ());
assertEquals ( 78 , $ lt1ToSend -> getValue ());
assertEquals ( 61 , lt2-> getValue ());
assertTrue ( $ lt1 -> isIdenticalTo ( $ lt1ToSend )); // lt1 == lt1ToSend
assertFalse ( $ lt2 -> isIdenticalTo ( $ lt1ToSend )); // lt2 != lt1ToSend
$ lt2 -> applyReceiveEvent ( $ lt1ToSend );
assertEquals ( 78 , lt1-> getValue ());
assertEquals ( 79 , lt2-> getValue ());
assertTrue ( $ lt1 -> happenBefore ( $ lt2 )); // lt1 -> lt2
assertTrue ( $ lt2 -> happenAfter ( $ lt1 ));テストケースでは、 LamportTimestampscenariotest :: testpaperfigure1aおよびlamporttimestampscenariotest :: testpaperfigure1bペーパーの完全なシナリオを見ることができます。

<?php
// We create three clocks, one for each node in our system
$ clockNode1 = new AsyncVectorClock ( ' NODE-1 ' );
$ clockNode2 = new AsyncVectorClock ( ' NODE-2 ' );
$ clockNode3 = new AsyncVectorClock ( ' NODE-3 ' );
// Then, for each clock, we add the others nodes in the current vector
$ clockNode1 -> addNode ( ' NODE-2 ' );
$ clockNode1 -> addNode ( ' NODE-3 ' );
$ clockNode2 -> addNode ( ' NODE-1 ' );
$ clockNode2 -> addNode ( ' NODE-3 ' );
$ clockNode3 -> addNode ( ' NODE-1 ' );
$ clockNode3 -> addNode ( ' NODE-2 ' );
// All clocks must look like [0, 0, 0]
// After the initialization part, we can play with our clocks
$ a = ( clone $ clockProcess1 )-> applySendEvent (); // [1, 0, 0]
$ l = ( clone $ clockProcess2 )-> applyLocalEvent (); // [0, 1, 0]
$ v = ( clone $ clockProcess3 )-> applyLocalEvent (); // [0, 0, 1]
$ b = ( clone $ a )-> applyLocalEvent (); // [2, 0, 0]
$ m = ( clone $ l )-> applyReceiveEvent ( $ a ); // [2, 2, 0]
$ w = ( clone $ v )-> applyLocalEvent (); // [0, 0, 3]
// And one more important thing, we can compare clocks
assertTrue ( $ l -> canBeComparedWith ( $ v ));
assertTrue ( $ a -> isIdenticalTo ( $ a )); // a == a
assertTrue ( $ l -> isConcurrentWith ( $ v )); // l <-> v
assertTrue ( $ m -> happenAfter ( $ a )); // a -> m
assertTrue ( $ a -> happenBefore ( $ m )); // a -> m
assertTrue ( $ l -> happenBefore ( $ m )); // l -> mテストの場合: asyncvectorscenariotest :: testpaperfigure3ペーパーの完全なシナリオを見ることができます。

<?php
// We create three clocks, one for each node in our system
$ clockNode1 = new SyncVectorClock ( ' NODE-1 ' );
$ clockNode2 = new SyncVectorClock ( ' NODE-2 ' );
$ clockNode3 = new SyncVectorClock ( ' NODE-3 ' );
// Then, for each clock, we add the others nodes in the current vector
$ clockNode1 -> addNode ( ' NODE-2 ' );
$ clockNode1 -> addNode ( ' NODE-3 ' );
$ clockNode2 -> addNode ( ' NODE-1 ' );
$ clockNode2 -> addNode ( ' NODE-3 ' );
$ clockNode3 -> addNode ( ' NODE-1 ' );
$ clockNode3 -> addNode ( ' NODE-2 ' );
// All clocks must look like [0, 0, 0] and are idle (i.e. not in communication with another node)
// After the initialization part, we can play with our clocks
assertTrue ( $ clockNode1 -> isIdle ());
assertTrue ( $ clockNode2 -> isIdle ());
assertTrue ( $ clockNode3 -> isIdle ());
$ a = ( clone $ clockNode1 )-> applyLocalEvent (); // [1, 0, 0]
$ t = ( clone $ clockNode3 )-> applyLocalEvent (); // [0, 0, 1]
// Then we want to make a synchrone communication between node1 and node2
$ b = clone $ a ; // [1, 0, 0]
$ l = clone $ clockNode2 ; // [0, 0, 0]
$ b -> applySendEvent ( $ l -> getNode ());
assertTrue ( $ b -> isCommunicating ());
assertEquals ( ' NODE-2 ' , $ b -> getCommunicatingNode ());
// $b sends its clock and is in a communicating state
// This means that, if you try to modify the clock you will get a ClockIsNotIdleException
// The only way for $b to become idle again is to receive a clock from NODE-2 (the current node is communicating with)
// As soon as $b receive a clock from NODE-2, it will merge it and go back to idle state and can be modified again
$ l -> applyReceiveEvent ( $ b ); // [2, 1, 0]
$ b -> applyReceiveEvent ( $ l ); // [2, 1, 0]
assertTrue ( $ b -> isIdle ());
// And one more important thing, we can compare clocks
assertTrue ( $ a -> canBeComparedWith ( $ t ));
assertTrue ( $ a -> isIdenticalTo ( $ a )); // a == a
assertTrue ( $ l -> isIdenticalTo ( $ b )); // l == b
assertTrue ( $ a -> isConcurrentWith ( $ t )); // a <-> t
assertTrue ( $ l -> happenAfter ( $ a )); // a -> l
assertTrue ( $ a -> happenBefore ( $ b )); // a -> b
assertTrue ( $ a -> happenBefore ( $ l )); // a -> lテストケースでは: Syncvectorscenariotest :: testpaperfigure7ペーパーの完全なシナリオを見ることができます。

昔ながらのPHPインストールまたはDockerを使用して、プロジェクトをローカルで起動できます。
Dockerを使用する場合、 dockerディレクトリにDocker-Composeファイルがあります。
cd docker && docker-compose up -dyou dev envで作曲家を使用する:
composer installコードはphpcsfixerを渡す必要があります。
src/修正
php vendor/bin/php-cs-fixer fix src --rules=@Symfony tests/
php vendor/bin/php-cs-fixer fix tests --rules=@Symfonyphpstanによって分析されます
php vendor/bin/phpstan analyse src -c /app/phpstan.neonプロジェクトはphpunitを使用します
これがテストスイートを起動するコマンドです
php vendor/phpunit/phpunit/phpunit --configuration phpunit.xml.dist tests注:カバレッジにはXdebugが必要です。このプロジェクトで提供されているDocker Envを使用している場合、すでにインストールされて構成されています。
あなたのコミットメッセージはこの条約に従う必要があります