Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ start with the repository playground instead of the conformance matrix.
`--runtime-url`, `--namespace`, and `--task-queue`; provide its separate
worker and client role credentials through the named process environment
variables described by `scripts/playground <language> --help`.
- The [PHP on Cloud example](README.md#php-on-cloud) shows the complete
managed invocation and explains the Laravel bridge versus embedded runtime.
- Treat the printed effective contract and `Worker ready` checkpoint as the
source of truth for workflow type, activity type, task queue, worker command,
start command, and expected result. Do not repeat scenario identities in an
Expand Down
30 changes: 26 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Runnable examples for Durable Workflow 2.0. Start a PHP-authored workflow
that calls Python and Rust activities through a standalone Server, build a
workflow with any first-party SDK, or run the workflow engine inside Laravel.

Already have a Cloud namespace? Start with [PHP on Cloud](#php-on-cloud).

[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/durable-workflow/sample-app?quickstart=1)

## Choose a path
Expand Down Expand Up @@ -61,6 +63,12 @@ isolated local Server and Waterline, waits for the worker registration, starts
the workflow, verifies its result and history, and prints the matching
Waterline run URL. Existing authored files are preserved.

The generated workflow and activity are yours to edit. `.playground/` and the
default evidence files are ignored by Git; the evidence is a run report, not
application source. To keep authored code in your project, choose a directory
with `--source`, review the generated files, and commit only your source, not
credentials or run reports. Existing files are preserved on subsequent runs.

Create a caller-owned project elsewhere with `--source`:

```bash
Expand All @@ -82,24 +90,38 @@ scripts/playground down rust

### Managed runtime

#### PHP on Cloud

The same authored project can run against Durable Workflow Cloud or another
existing runtime. Supply role-specific credentials without putting them in
source control:
existing runtime, without starting a local Server or Waterline. Use the exact
runtime URL and namespace shown by Cloud; do not append `/api`. Supply the
runtime worker and client SDK credentials, not a Cloud control-plane API key:

```bash
export DURABLE_WORKFLOW_WORKER_TOKEN='<worker credential>'
export DURABLE_WORKFLOW_CLIENT_TOKEN='<client credential>'

scripts/playground rust \
scripts/playground php \
--runtime managed \
--runtime-url 'https://runtime.example/namespaces/example' \
--namespace 'example' \
--task-queue 'my-rust-worker'
--task-queue 'my-php-worker'
```

The worker receives only the worker credential, and the client receives only
the client credential. The runner prints the workflow type, activity type,
task queue, worker command, start command, and expected result before it runs.
Expect `Worker ready: target=managed`, followed by `Completed php workflow`
and the result containing `workflow_runtime: php` and `activity_runtime: php`.
Use `python` or `rust` in place of `php` for the other SDKs.

This PHP path is **service mode using the Laravel bridge**, not the embedded
workflow engine. Laravel provides configuration, dependency injection, PSR
logging, and the SDK test fake. The SDK worker polls Cloud; Laravel's embedded
queue worker is not its executor. The generated `bootstrap.php` and activity
use Laravel, while the core PHP SDK also supports framework-free processes.
For those, use `scripts/playground scaffold php --standalone --source <dir>`
to inspect the installed SDK's own worker/client examples.

## Embedded Laravel

Expand Down
7 changes: 7 additions & 0 deletions scripts/playground
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,13 @@ def journey(
if effective_task_queue:
scenario["task_queue"] = effective_task_queue
created = scaffold(language, source_dir, scenario=scenario)
print(f"Editable {language} source: {source_dir}", flush=True)
print(f"Generated run evidence: {evidence_path}", flush=True)
print(
"Edit the generated source for your application. The default .playground/ "
"directory is Git-ignored; use --source for your project directory.",
flush=True,
)
project = os.environ.get("PLAYGROUND_COMPOSE_PROJECT", "sample-app-playground")
task_queue = str(scenario["task_queue"])
worker_id = f"sample-app-playground-{language}-worker-{suffix}"
Expand Down
4 changes: 4 additions & 0 deletions tests/Unit/PlaygroundContractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,10 @@ class FakeWorker:
$this->assertStringContainsString('managed-harness=["php", "python", "rust"]', $output);
$this->assertSame(3, substr_count($output, 'Worker ready: target=managed'));
$this->assertSame(3, substr_count($output, '"runtime_target":"managed"'));
foreach (['php', 'python', 'rust'] as $language) {
$this->assertStringContainsString("Editable {$language} source: {$temporaryDirectory}/{$language}", $output);
$this->assertStringContainsString("Generated run evidence: {$temporaryDirectory}/{$language}.json", $output);
}
$this->assertStringNotContainsString('worker-secret', $output);
$this->assertStringNotContainsString('client-secret', $output);
} finally {
Expand Down
Loading