Skip to content

Commit 2c28667

Browse files
authored
feat(php): add SDK examples component (#3368)
1 parent f139f0e commit 2c28667

9 files changed

Lines changed: 356 additions & 3 deletions

File tree

.github/config/components.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,18 @@ components:
402402
- "scripts/utils.sh"
403403
tasks: ["examples-python"]
404404

405+
examples-php:
406+
depends_on:
407+
- "rust-server"
408+
- "rust-sdk" # All SDKs depend on core SDK changes
409+
- "sdk-php"
410+
- "ci-infrastructure"
411+
paths:
412+
- "examples/php/**"
413+
- "scripts/run-examples-from-readme.sh"
414+
- "scripts/utils.sh"
415+
tasks: ["examples-php"]
416+
405417
examples-node:
406418
depends_on:
407419
- "rust-server"

.github/workflows/_test_examples.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ jobs:
6565
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-python'
6666
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
6767

68+
- name: Install PHP build dependencies
69+
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-php'
70+
shell: bash
71+
run: |
72+
sudo apt-get update
73+
sudo apt-get install -y --no-install-recommends \
74+
clang \
75+
libclang-dev \
76+
libhwloc-dev \
77+
libssl-dev \
78+
php8.3-cli \
79+
php8.3-dev \
80+
pkg-config
81+
82+
php_bin="$(command -v php8.3)"
83+
php_config="$(command -v php-config8.3)"
84+
{
85+
echo "PHP=${php_bin}"
86+
echo "PHP_CONFIG=${php_config}"
87+
} >> "$GITHUB_ENV"
88+
"${php_bin}" --version
89+
"${php_config}" --version
90+
6891
- name: Cache uv
6992
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-python'
7093
uses: actions/cache@v5
@@ -123,6 +146,20 @@ jobs:
123146
fi
124147
fi
125148
149+
- name: Build PHP extension for examples
150+
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-php'
151+
shell: bash
152+
run: |
153+
export CARGO_TARGET_DIR="${GITHUB_WORKSPACE}/target"
154+
cargo build --manifest-path foreign/php/Cargo.toml
155+
extension="$(find target/debug -maxdepth 1 -name 'libiggy_php.so' -print -quit)"
156+
if [ -z "$extension" ]; then
157+
echo "PHP extension was not produced"
158+
exit 1
159+
fi
160+
echo "PHP_IGGY_EXTENSION=$(realpath "$extension")" >> "$GITHUB_ENV"
161+
ls -lh "$extension"
162+
126163
- name: Build Node SDK for examples
127164
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-node'
128165
run: |
@@ -150,6 +187,10 @@ jobs:
150187
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-python'
151188
run: ./scripts/run-examples-from-readme.sh --language python
152189

190+
- name: Run PHP examples
191+
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-php'
192+
run: ./scripts/run-examples-from-readme.sh --language php
193+
153194
- name: Run Node.js examples
154195
if: startsWith(inputs.component, 'examples-') && inputs.task == 'examples-node'
155196
run: ./scripts/run-examples-from-readme.sh --language node

examples/php/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Iggy PHP Examples
2+
3+
This directory contains sample applications that show how to use the Apache
4+
Iggy PHP SDK extension.
5+
6+
## Running Examples
7+
8+
Start the server from the repository root:
9+
10+
```bash
11+
cargo run --bin iggy-server -- --fresh --with-default-root-credentials
12+
```
13+
14+
From `examples/php`, build the PHP extension and point PHP at it:
15+
16+
```bash
17+
(cd ../../foreign/php && cargo build)
18+
export PHP_IGGY_EXTENSION="$(pwd)/../../foreign/php/target/debug/libiggy_php.so"
19+
```
20+
21+
On macOS, use `../../foreign/php/target/debug/libiggy_php.dylib` instead.
22+
23+
### Getting Started
24+
25+
```bash
26+
php -d extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}" getting-started/producer.php
27+
php -d extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}" getting-started/consumer.php
28+
```
29+
30+
### Basic Usage
31+
32+
```bash
33+
php -d extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}" basic/producer.php
34+
php -d extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}" basic/consumer.php
35+
```
36+
37+
The examples use `IGGY_CONNECTION_STRING` when it is set. Otherwise they build
38+
`iggy+tcp://iggy:iggy@127.0.0.1:8090` from `IGGY_HOST`, `IGGY_PORT`,
39+
`IGGY_USERNAME`, and `IGGY_PASSWORD`, which can be set individually.

examples/php/basic/consumer.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
declare(strict_types=1);
23+
24+
require_once __DIR__ . '/../src/common.php';
25+
26+
$stream = 'php-basic-stream';
27+
$topic = 'php-basic-topic';
28+
$client = iggy_client();
29+
30+
ensure_stream_and_topic($client, $stream, $topic);
31+
print_polled_messages($client, $stream, $topic, 3);

examples/php/basic/producer.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
declare(strict_types=1);
23+
24+
require_once __DIR__ . '/../src/common.php';
25+
26+
$stream = 'php-basic-stream';
27+
$topic = 'php-basic-topic';
28+
$client = iggy_client();
29+
30+
ensure_stream_and_topic($client, $stream, $topic);
31+
send_payloads($client, $stream, $topic, example_payloads('basic', 3));
32+
33+
echo "Sent 3 PHP basic messages", PHP_EOL;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
declare(strict_types=1);
23+
24+
require_once __DIR__ . '/../src/common.php';
25+
26+
$stream = 'php-getting-started-stream';
27+
$topic = 'php-getting-started-topic';
28+
$client = iggy_client();
29+
30+
ensure_stream_and_topic($client, $stream, $topic);
31+
print_polled_messages($client, $stream, $topic, 5);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
declare(strict_types=1);
23+
24+
require_once __DIR__ . '/../src/common.php';
25+
26+
$stream = 'php-getting-started-stream';
27+
$topic = 'php-getting-started-topic';
28+
$client = iggy_client();
29+
30+
ensure_stream_and_topic($client, $stream, $topic);
31+
send_payloads($client, $stream, $topic, example_payloads('getting-started', 5));
32+
33+
echo "Sent 5 PHP getting-started messages", PHP_EOL;

examples/php/src/common.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
declare(strict_types=1);
23+
24+
use Iggy\Client;
25+
use Iggy\PollingStrategy;
26+
use Iggy\SendMessage;
27+
28+
function iggy_connection_string(): string
29+
{
30+
$configured = getenv('IGGY_CONNECTION_STRING');
31+
if ($configured !== false && $configured !== '') {
32+
return $configured;
33+
}
34+
35+
$host = getenv('IGGY_HOST') ?: '127.0.0.1';
36+
$port = getenv('IGGY_PORT') ?: '8090';
37+
$username = rawurlencode(getenv('IGGY_USERNAME') ?: 'iggy');
38+
$password = rawurlencode(getenv('IGGY_PASSWORD') ?: 'iggy');
39+
40+
return "iggy+tcp://{$username}:{$password}@{$host}:{$port}";
41+
}
42+
43+
function iggy_client(): Client
44+
{
45+
$client = Client::fromConnectionString(iggy_connection_string());
46+
$client->connect();
47+
48+
return $client;
49+
}
50+
51+
function ensure_stream_and_topic(Client $client, string $stream, string $topic): void
52+
{
53+
if ($client->getStream($stream) === null) {
54+
$client->createStream($stream);
55+
}
56+
57+
if ($client->getTopic($stream, $topic) === null) {
58+
$client->createTopic($stream, $topic, 1);
59+
}
60+
}
61+
62+
function send_payloads(Client $client, string $stream, string $topic, array $payloads): void
63+
{
64+
$messages = array_map(
65+
static fn (string $payload): SendMessage => new SendMessage($payload),
66+
$payloads,
67+
);
68+
69+
$client->sendMessages($stream, $topic, 0, $messages);
70+
}
71+
72+
function print_polled_messages(Client $client, string $stream, string $topic, int $count): void
73+
{
74+
$messages = $client->pollMessages($stream, $topic, 0, PollingStrategy::first(), $count, true);
75+
76+
if (count($messages) < $count) {
77+
throw new RuntimeException("Expected {$count} messages, received " . count($messages));
78+
}
79+
80+
foreach ($messages as $message) {
81+
echo "Received message at offset {$message->offset()}: {$message->payload()}", PHP_EOL;
82+
}
83+
}
84+
85+
function example_payloads(string $prefix, int $count): array
86+
{
87+
return array_map(
88+
static fn (int $index): string => "{$prefix}-message-{$index}",
89+
range(1, $count),
90+
);
91+
}

0 commit comments

Comments
 (0)