Skip to content

Commit d60ce5f

Browse files
authored
Merge pull request #945 from durable-workflow/fix/942-full-contract-qualification
Preserve update lock bounds and qualify service scheduling contracts
2 parents efde90b + c51f806 commit d60ce5f

6 files changed

Lines changed: 31 additions & 5 deletions

File tree

‎.github/workflows/php.yml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,20 @@ jobs:
780780
QUEUE_CONNECTION: redis
781781
XDEBUG_MODE: off
782782

783+
- name: Run service scheduling and completion contracts
784+
run: >-
785+
vendor/bin/phpunit tests/Unit/V2/DefaultServiceControlPlaneWorkflowBindingTest.php
786+
tests/Unit/V2/ServiceCallEffectIdentityTest.php
787+
tests/Unit/V2/WebhookInputValidationTest.php
788+
tests/Unit/V2/WorkflowExecutorServiceOperationTest.php
789+
tests/Unit/V2/DefaultWorkflowTaskBridgeServiceOperationTest.php
790+
tests/Unit/V2/ServiceCallSchedulerTest.php
791+
--fail-on-warning --log-junit build/test-results/pr-smoke-service-scheduling.xml
792+
env:
793+
DB_CONNECTION: mysql
794+
QUEUE_CONNECTION: redis
795+
XDEBUG_MODE: off
796+
783797
- name: Upload pull-request MySQL smoke timing report
784798
if: ${{ always() && github.server_url == 'https://github.com' }}
785799
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7

‎src/V2/Support/DefaultServiceControlPlane.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,10 @@ private function dispatchWorkflowUpdate(
13871387
$commandOptions['wait_for'] ??= $call->operation_mode === ServiceCallOperationMode::Sync->value
13881388
? 'completed'
13891389
: 'accepted';
1390+
if ($call->getConnection()->transactionLevel() > 0) {
1391+
$commandOptions['wait_for'] = UpdateWaitPolicy::WAIT_FOR_ACCEPTED;
1392+
unset($commandOptions['wait_timeout_seconds']);
1393+
}
13901394

13911395
try {
13921396
$result = $this->workflows()

‎tests/Unit/V2/ServiceCallEffectIdentityTest.php‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ private function currentClaim(WorkflowStub $caller): array
442442
'handler_target_reference' => 'change',
443443
]);
444444
$control = new DefaultServiceControlPlane(new DefaultWorkflowControlPlane());
445-
DB::transaction(static fn (): array => $control->execute('billing', 'effects', 'apply', [
445+
$options = ServiceCallScheduler::withAfterCommitAuthority([
446446
'namespace' => 'billing',
447447
'caller_namespace' => $run->namespace,
448448
'caller_workflow_instance_id' => $caller->id(),
@@ -451,7 +451,8 @@ private function currentClaim(WorkflowStub $caller): array
451451
'idempotency_key' => 'effect-identity-' . $caller->id(),
452452
'wait_for' => 'completed',
453453
'wait_timeout_seconds' => 60,
454-
]));
454+
]);
455+
DB::transaction(static fn (): array => $control->execute('billing', 'effects', 'apply', $options));
455456
$claim = ServiceCallScheduler::claim(WorkflowServiceCall::query()->sole()->id);
456457
$this->assertNotNull($claim);
457458
$identity = ServiceCallEffectIdentity::forCurrentClaim($claim);

‎tests/Unit/V2/ServiceCallSchedulerTest.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ public function testCallerContextAndIdempotencyTransactionDoNotScheduleAnHttpExe
112112
return $instanceId === 'accepted-target'
113113
&& $name === 'approve'
114114
&& WorkflowServiceCall::query()->getModel()->getConnection()->transactionLevel() === 1
115-
&& $options['wait_for'] === 'completed'
116-
&& $options['wait_timeout_seconds'] === 60;
115+
&& $options['wait_for'] === 'accepted'
116+
&& ! array_key_exists('wait_timeout_seconds', $options);
117117
})
118118
->andReturn([
119119
'accepted' => true,

‎tests/Unit/V2/WebhookInputValidationTest.php‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ public function testMalformedRequestReportsItsFieldBeforeChangingDurableRecords(
8181
'name' => 'Ada',
8282
], $payload);
8383
}
84+
if (str_ends_with($path, '/complete')) {
85+
$this->withHeader('X-Durable-Workflow-Protocol-Version', '1.20');
86+
}
8487
$before = $this->records();
8588
$writes = [];
8689
DB::listen(static function (QueryExecuted $event) use (&$writes): void {

‎tests/Unit/V2/WorkflowExecutorServiceOperationTest.php‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Workflow\V2\Support\RunServiceOperationAuthorizer;
3131
use Workflow\V2\Support\RunTimelineProjector;
3232
use Workflow\V2\Support\ServiceCallPrincipal;
33+
use Workflow\V2\Support\ServiceCallScheduler;
3334
use Workflow\V2\Support\ServiceOperationOptions;
3435
use Workflow\V2\Support\ServiceOperationResult;
3536
use Workflow\V2\Support\WorkerCompatibilityFleet;
@@ -138,8 +139,11 @@ public function testPublicExecutionRecordsTheBoundaryOutcomeAndReplaysWithoutCal
138139
}
139140
$this->assertInstanceOf(ServiceCallPrincipal::class, $service->executions[0][3]['principal']);
140141
$service->executions[0][3]['principal'] = $service->executions[0][3]['principal']->toAuditArray();
142+
$this->assertTrue(ServiceCallScheduler::hasAfterCommitAuthority($service->executions[0][3]));
141143
$this->assertSame(
142-
$this->ordered(['billing', 'invoices', 'create', $expectedOptions]),
144+
$this->ordered(
145+
['billing', 'invoices', 'create', ServiceCallScheduler::withAfterCommitAuthority($expectedOptions)]
146+
),
143147
$this->ordered($service->executions[0])
144148
);
145149
$event = WorkflowHistoryEvent::query()->where('workflow_run_id', $run->id)->whereIn('event_type', [

0 commit comments

Comments
 (0)