-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally trigger pcntl_signal_dispatch #96
Conversation
@@ -164,6 +170,7 @@ public function __construct( | |||
$this->persistBlockSize = $persistBlockSize; | |||
$this->sleep = $sleep; | |||
$this->status = ProjectionStatus::IDLE(); | |||
$this->triggerPcntlSignalDispatch = extension_loaded('pcntl') && $triggerPcntlSignalDispatch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switch the order of the checks so that if $triggerPcntlSignalDispatch = false
PHP does not check if extension is loaded
@@ -151,6 +161,7 @@ public function __construct( | |||
$this->persistBlockSize = $persistBlockSize; | |||
$this->sleep = $sleep; | |||
$this->status = ProjectionStatus::IDLE(); | |||
$this->triggerPcntlSignalDispatch = extension_loaded('pcntl') && $triggerPcntlSignalDispatch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@prolic can you take a look? You are the expert in that area. Also a test and docs update would be nice, especially regarding $pcntlCallback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
besides some small remarks, it definitely needs docs and a small sample in the docs on how usage might look like
@@ -35,6 +35,10 @@ | |||
|
|||
final class PdoEventStoreReadModelProjector implements ReadModelProjector | |||
{ | |||
const OPTION_PCNTL_DISPATCH = 'trigger_pcntl_dispatch'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public const
@@ -35,6 +35,10 @@ | |||
|
|||
final class PdoEventStoreReadModelProjector implements ReadModelProjector | |||
{ | |||
const OPTION_PCNTL_DISPATCH = 'trigger_pcntl_dispatch'; | |||
|
|||
const DEFAULT_PCNTL_DISPATCH = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public const
*/ | ||
private $triggerPcntlSignalDispatch; | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new consts missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow, could you ellaborate? :)
@@ -87,7 +87,8 @@ public function createProjection( | |||
$options[PdoEventStoreProjector::OPTION_LOCK_TIMEOUT_MS] ?? PdoEventStoreProjector::DEFAULT_LOCK_TIMEOUT_MS, | |||
$options[PdoEventStoreProjector::OPTION_CACHE_SIZE] ?? PdoEventStoreProjector::DEFAULT_CACHE_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_PERSIST_BLOCK_SIZE] ?? PdoEventStoreProjector::DEFAULT_PERSIST_BLOCK_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP, | |||
$options[PdoEventStoreReadModelProjector::OPTION_PCNTL_DISPATCH] ?? PdoEventStoreReadModelProjector::DEFAULT_PCNTL_DISPATCH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong cost usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow, could you ellaborate? :)
@@ -87,7 +87,8 @@ public function createProjection( | |||
$options[PdoEventStoreProjector::OPTION_LOCK_TIMEOUT_MS] ?? PdoEventStoreProjector::DEFAULT_LOCK_TIMEOUT_MS, | |||
$options[PdoEventStoreProjector::OPTION_CACHE_SIZE] ?? PdoEventStoreProjector::DEFAULT_CACHE_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_PERSIST_BLOCK_SIZE] ?? PdoEventStoreProjector::DEFAULT_PERSIST_BLOCK_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP, | |||
$options[PdoEventStoreReadModelProjector::OPTION_PCNTL_DISPATCH] ?? PdoEventStoreReadModelProjector::DEFAULT_PCNTL_DISPATCH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong const usage
@@ -87,7 +87,8 @@ public function createProjection( | |||
$options[PdoEventStoreProjector::DEFAULT_LOCK_TIMEOUT_MS] ?? PdoEventStoreProjector::DEFAULT_LOCK_TIMEOUT_MS, | |||
$options[PdoEventStoreProjector::OPTION_CACHE_SIZE] ?? PdoEventStoreProjector::DEFAULT_CACHE_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_PERSIST_BLOCK_SIZE] ?? PdoEventStoreProjector::DEFAULT_PERSIST_BLOCK_SIZE, | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP | |||
$options[PdoEventStoreProjector::OPTION_SLEEP] ?? PdoEventStoreProjector::DEFAULT_SLEEP, | |||
$options[PdoEventStoreReadModelProjector::OPTION_PCNTL_DISPATCH] ?? PdoEventStoreReadModelProjector::DEFAULT_PCNTL_DISPATCH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong const usage
@@ -498,6 +505,8 @@ public function run(bool $keepRunning = true): void | |||
|
|||
$this->eventCounter = 0; | |||
|
|||
$this->triggerPcntlSignalDispatch(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be the best place for that function call
@fritz-gerneth do you have any idea how to add a test for this ? |
Should be another const in PdoEventStoreProjector, or even at interface
level.
…On Jun 29, 2017 11:49 PM, "Fritz Gerneth" ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/Projection/PdoEventStoreProjector.php
<#96 (comment)>:
> @@ -134,6 +134,11 @@
private $sleep;
/**
+ * @var bool
+ */
+ private $triggerPcntlSignalDispatch;
+
+ /**
Not sure I follow, could you ellaborate? :)
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#96 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAYEvJaokUyioOndD8mOSZdkxGJrAechks5sI8ehgaJpZM4OI_dg>
.
|
Certainly can add some documentation. Any prefered location or just create a new file "Using from CLI"? For testing - unfortunately I don't have any idea that does not require dirty hacks. The two problems I see:
I sure could change this to remove the dependency on |
@@ -38,6 +38,10 @@ | |||
|
|||
final class PdoEventStoreProjector implements Projector | |||
{ | |||
public const OPTION_PCNTL_DISPATCH = 'trigger_pcntl_dispatch'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the consts should go here: https://github.com/prooph/event-store/blob/master/src/Projection/Projector.php#L25
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's useful for all implementations, not specific to pdo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought about that too, they definitely belong there and are helpful for others. This would require a new release of the event-store and update the minimum version required in this package though (else the constants in the projection managers are not defined). If you prefer this I certainly can draft this up.
@fritz-gerneth A unit test is not possible, I agree, but we could add an integration test. So spin up an in-memory event-store, run some test projection on it, send a kill signal and see if it stopped gracefully. hint:
|
Go for it!
…On Jun 30, 2017 04:14, "Fritz Gerneth" ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/Projection/PdoEventStoreProjector.php
<#96 (comment)>:
> @@ -38,6 +38,10 @@
final class PdoEventStoreProjector implements Projector
{
+ public const OPTION_PCNTL_DISPATCH = 'trigger_pcntl_dispatch';
Thought about that too, they definitely belong there and are helpful for
others. This would require a new release of the event-store and update the
minimum version required in this package though (else the constants in the
projection managers are not defined). If you prefer this I certainly can
draft this up.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#96 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAYEvHWjyO9hg8-d6FLFUmGCegGcXxULks5sJAWNgaJpZM4OI_dg>
.
|
* Created process inherits env variables from this process. | ||
* Script returns with non-standard code SIGUSR1 from the handler and -1 else | ||
*/ | ||
$projectionProcess = proc_open($command, $descriptorSpec, $pipes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This turned out to be harder than I thought and brought me down a road I certainly don't want to head to :)
Problem with exec is that it waits for the command to finish and doesn't return the pid. We could resolve this by sending the command to the background (php ... &
) or return the pid (php ... & echo $!;
). But still then, it doesn't return if the output is not redirected to /dev/null
(see comment in documentation). SO I opted for the proc*
family instead.
The test itself is rather simple - we return a non-standard exit code in our callback instead of the default one. Disabling the flag on the projection makes this test fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like that test-case, just some notes.
@@ -151,6 +161,7 @@ public function __construct( | |||
$this->persistBlockSize = $persistBlockSize; | |||
$this->sleep = $sleep; | |||
$this->status = ProjectionStatus::IDLE(); | |||
$this->triggerPcntlSignalDispatch = $triggerPcntlSignalDispatch && extension_loaded('pcntl'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if $triggerPcntlSignalDispatch is set to true but extension is missing, we should maybe throw an exception instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would limit portability of projections across systems (e.g. when a library defines a projection with this flag enabled, while the user's system doesn't have it enabled). Personally I prefer the degraded functionality approach, but it's your call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** | ||
* @test | ||
*/ | ||
public function it_dispatches_pcntl_signals_when_enabled(): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move these tests to the AbstractReadModelProjectorTest in the event-store repo. This way the test can be reused across all event-store implementations. If you think InMemoryEventStore is not worth adding this feature, we simply skip the tests for it.
|
||
require __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
$readModel = new class() implements \Prooph\EventStore\Projection\ReadModel { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import Prooph\EventStore\Projection\ReadModel
@codeliner your thoughts?
On Jun 30, 2017 9:41 PM, "Fritz Gerneth" <[email protected]> wrote:
*@fritz-gerneth* commented on this pull request.
------------------------------
In src/Projection/PdoEventStoreReadModelProjector.php
<#96 (comment)>:
@@ -151,6 +161,7 @@ public function __construct(
$this->persistBlockSize = $persistBlockSize;
$this->sleep = $sleep;
$this->status = ProjectionStatus::IDLE();
+ $this->triggerPcntlSignalDispatch =
$triggerPcntlSignalDispatch && extension_loaded('pcntl');
I think this would limit portability of projections across systems (e.g.
when a library defines a projection with this flag enabled, while the
user's system doesn't have it enabled). Personally I prefer the degraded
functionality approach, but it's your call.
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#96 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAYEvBAKXhhXyiCF2VFoKa23_AkgkEDtks5sJPsggaJpZM4OI_dg>
.
|
Require https://github.com/prooph/event-store/releases/tag/v7.2.0 and update according to changes made there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nearly finished :)
@@ -164,6 +170,7 @@ public function __construct( | |||
$this->persistBlockSize = $persistBlockSize; | |||
$this->sleep = $sleep; | |||
$this->status = ProjectionStatus::IDLE(); | |||
$this->triggerPcntlSignalDispatch = $triggerPcntlSignalDispatch && extension_loaded('pcntl'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -857,4 +866,11 @@ private function prepareStreamPositions(): void | |||
|
|||
$this->streamPositions = array_merge($streamPositions, $this->streamPositions); | |||
} | |||
|
|||
private function triggerPcntlSignalDispatch(): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this private function and call it directly. It has only a single usage.
@@ -151,6 +161,7 @@ public function __construct( | |||
$this->persistBlockSize = $persistBlockSize; | |||
$this->sleep = $sleep; | |||
$this->status = ProjectionStatus::IDLE(); | |||
$this->triggerPcntlSignalDispatch = $triggerPcntlSignalDispatch && extension_loaded('pcntl'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -807,4 +816,11 @@ private function prepareStreamPositions(): void | |||
|
|||
$this->streamPositions = array_merge($streamPositions, $this->streamPositions); | |||
} | |||
|
|||
private function triggerPcntlSignalDispatch(): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here. we don't need it as method.
@@ -0,0 +1,74 @@ | |||
<?php | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docheader missing
@@ -0,0 +1,45 @@ | |||
<?php | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docheader missing
thanks a lot! 👍 |
Currently there is no way to gracefully shut down a running projection when any OS signals are received. Setting the projection is
stopping
state via a custom CLI script is not always an option (e.g. when projections and others are managed by supervisord).I think how the different signals should be handled should be left to the programmer, I have included a short example for reference below. In any case, to support this feature the projection loop at least needs to trigger the signal dispatch function.
Some remarks on my approach:
declare(ticks=1)
is not required anymore to my knowledge, it got replaced bypcntl_signal_dispatch
false
to remain fully backwards compatibletriggerPcntlSignalDispatch
call within the loop has quite a few implications. It might even make sense to trigger this beforeusleep
.