hubcio commented on code in PR #3368:
URL: https://github.com/apache/iggy/pull/3368#discussion_r3323385003


##########
scripts/run-examples-from-readme.sh:
##########
@@ -284,6 +284,49 @@ run_python_examples() {
     return "${EXAMPLES_EXIT_CODE}"
 }
 
+# shellcheck disable=SC2329
+run_php_examples() {
+    resolve_server_binary "${TARGET}"
+
+    local php_bin="${PHP:-php}"
+    if [ -z "${PHP_IGGY_EXTENSION:-}" ]; then
+        local extension_candidate
+        for extension_candidate in \
+            target/debug/libiggy_php.so \
+            target/debug/libiggy_php.dylib \
+            target/debug/iggy_php.dll \
+            foreign/php/target/debug/libiggy_php.so \
+            foreign/php/target/debug/libiggy_php.dylib \
+            foreign/php/target/debug/iggy_php.dll; do
+            if [ -f "${extension_candidate}" ]; then
+                PHP_IGGY_EXTENSION="${extension_candidate}"

Review Comment:
   this sets `PHP_IGGY_EXTENSION` to a repo-root-relative path, but 
`run_language_examples` cds into `examples/php` before the readme command evals 
`php -d extension="${PHP_IGGY_EXTENSION:-...}"`. the var is now set so the `:-` 
fallback is skipped, and the relative path resolves against `examples/php/` -> 
file missing -> extension fails to load -> `Iggy\Client` undefined -> fatal. 
the `[ ! -f ]` check above runs while still at repo root so it passes and masks 
it. CI is fine since the workflow exports an absolute `realpath`, but 
`./scripts/run-examples-from-readme.sh --language php` run locally hits it. 
fix: `PHP_IGGY_EXTENSION="$(pwd)/${extension_candidate}"`. also the 
`iggy_php.dll` candidates are dead here (no windows runner) and can be dropped.



##########
examples/php/src/common.php:
##########
@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+declare(strict_types=1);
+
+use Iggy\Client;
+use Iggy\PollingStrategy;
+use Iggy\ReceiveMessage;
+use Iggy\SendMessage;
+
+function iggy_connection_string(): string
+{
+    $configured = getenv('IGGY_CONNECTION_STRING');
+    if ($configured !== false && $configured !== '') {
+        return $configured;
+    }
+
+    $host = getenv('IGGY_HOST') ?: '127.0.0.1';
+    $port = getenv('IGGY_PORT') ?: '8090';
+    $username = rawurlencode(getenv('IGGY_USERNAME') ?: 'iggy');
+    $password = rawurlencode(getenv('IGGY_PASSWORD') ?: 'iggy');
+
+    return "iggy+tcp://{$username}:{$password}@{$host}:{$port}";
+}
+
+function iggy_client(): Client
+{
+    $client = Client::fromConnectionString(iggy_connection_string());
+    $client->connect();
+
+    return $client;
+}
+
+function ensure_stream_and_topic(Client $client, string $stream, string 
$topic): void
+{
+    if ($client->getStream($stream) === null) {
+        $client->createStream($stream);
+    }
+
+    if ($client->getTopic($stream, $topic) === null) {
+        $client->createTopic($stream, $topic, 1, null, null, null, null);
+    }
+}
+
+function send_payloads(Client $client, string $stream, string $topic, array 
$payloads): void
+{
+    $messages = array_map(
+        static fn (string $payload): SendMessage => new SendMessage($payload),
+        $payloads,
+    );
+
+    $client->sendMessages($stream, $topic, 0, $messages);
+}
+
+function print_polled_messages(Client $client, string $stream, string $topic, 
int $count): void
+{
+    $messages = $client->pollMessages($stream, $topic, 0, 
PollingStrategy::first(), $count, true);
+
+    if (count($messages) < $count) {
+        throw new RuntimeException("Expected {$count} messages, received " . 
count($messages));
+    }
+
+    foreach ($messages as $message) {
+        if (!$message instanceof ReceiveMessage) {

Review Comment:
   `pollMessages()` always returns an array of `ReceiveMessage`, so this guard 
can never be false and the `continue` is unreachable. drop it and iterate 
directly.



##########
examples/php/src/common.php:
##########
@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+declare(strict_types=1);
+
+use Iggy\Client;
+use Iggy\PollingStrategy;
+use Iggy\ReceiveMessage;
+use Iggy\SendMessage;
+
+function iggy_connection_string(): string
+{
+    $configured = getenv('IGGY_CONNECTION_STRING');
+    if ($configured !== false && $configured !== '') {
+        return $configured;
+    }
+
+    $host = getenv('IGGY_HOST') ?: '127.0.0.1';
+    $port = getenv('IGGY_PORT') ?: '8090';
+    $username = rawurlencode(getenv('IGGY_USERNAME') ?: 'iggy');
+    $password = rawurlencode(getenv('IGGY_PASSWORD') ?: 'iggy');
+
+    return "iggy+tcp://{$username}:{$password}@{$host}:{$port}";
+}
+
+function iggy_client(): Client
+{
+    $client = Client::fromConnectionString(iggy_connection_string());
+    $client->connect();
+
+    return $client;
+}
+
+function ensure_stream_and_topic(Client $client, string $stream, string 
$topic): void
+{
+    if ($client->getStream($stream) === null) {
+        $client->createStream($stream);
+    }
+
+    if ($client->getTopic($stream, $topic) === null) {
+        $client->createTopic($stream, $topic, 1, null, null, null, null);

Review Comment:
   the 4 trailing `null`s match the stub defaults, so `createTopic($stream, 
$topic, 1)` is equivalent and cleaner. the python example skips them too.



##########
examples/php/README.md:
##########
@@ -0,0 +1,38 @@
+# Iggy PHP Examples
+
+This directory contains sample applications that show how to use the Apache
+Iggy PHP SDK extension.
+
+## Running Examples
+
+Start the server from the repository root:
+
+```bash
+cargo run --bin iggy-server -- --fresh --with-default-root-credentials
+```
+
+From `examples/php`, build the PHP extension and point PHP at it:
+
+```bash
+(cd ../../foreign/php && cargo build)
+export 
PHP_IGGY_EXTENSION="$(pwd)/../../foreign/php/target/debug/libiggy_php.so"
+```
+
+On macOS, use `../../foreign/php/target/debug/libiggy_php.dylib` instead.
+
+### Getting Started
+
+```bash
+php -d 
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
 getting-started/producer.php
+php -d 
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
 getting-started/consumer.php
+```
+
+### Basic Usage
+
+```bash
+php -d 
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
 basic/producer.php
+php -d 
extension="${PHP_IGGY_EXTENSION:-../../foreign/php/target/debug/libiggy_php.so}"
 basic/consumer.php
+```
+
+The examples use `IGGY_CONNECTION_STRING` when it is set. Otherwise they 
connect

Review Comment:
   the examples also fall back to `IGGY_HOST`, `IGGY_PORT`, `IGGY_USERNAME` and 
`IGGY_PASSWORD` when `IGGY_CONNECTION_STRING` is unset, but only the connection 
string is documented here. worth a line so people know the individual vars work 
too.



##########
scripts/run-examples-from-readme.sh:
##########
@@ -284,6 +284,49 @@ run_python_examples() {
     return "${EXAMPLES_EXIT_CODE}"
 }
 
+# shellcheck disable=SC2329
+run_php_examples() {
+    resolve_server_binary "${TARGET}"
+
+    local php_bin="${PHP:-php}"
+    if [ -z "${PHP_IGGY_EXTENSION:-}" ]; then
+        local extension_candidate
+        for extension_candidate in \
+            target/debug/libiggy_php.so \
+            target/debug/libiggy_php.dylib \
+            target/debug/iggy_php.dll \
+            foreign/php/target/debug/libiggy_php.so \
+            foreign/php/target/debug/libiggy_php.dylib \
+            foreign/php/target/debug/iggy_php.dll; do
+            if [ -f "${extension_candidate}" ]; then
+                PHP_IGGY_EXTENSION="${extension_candidate}"
+                break
+            fi
+        done
+        export PHP_IGGY_EXTENSION
+    fi
+
+    if [ -z "${PHP_IGGY_EXTENSION:-}" ] || [ ! -f "${PHP_IGGY_EXTENSION}" ]; 
then
+        echo "Error: PHP extension not found. Build foreign/php first or set 
PHP_IGGY_EXTENSION."
+        exit 1
+    fi
+
+    TRANSFORM_COMMAND() {
+        local command="$1"
+        printf '%s\n' "${command/#php /\"${php_bin}\" }"
+    }
+
+    run_language_examples \
+        "PHP" \
+        "examples/php" \
+        "README.md" \
+        "^php " \
+        "" \
+        "" \
+        0 \

Review Comment:
   non-blocking and the other runners pass `0` too, so fine to leave - but `0` 
means no per-command timeout, and `connect()` retries unbounded by default. if 
the server dies after startup a stalled connect rides all the way to the 60-min 
job timeout instead of failing fast. python passes `10`. could be a small 
repo-wide follow-up.



##########
examples/php/basic/producer.php:
##########
@@ -0,0 +1,37 @@
+<?php
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+declare(strict_types=1);
+
+require_once __DIR__ . '/../src/common.php';
+
+$stream = 'php-basic-stream';
+$topic = 'php-basic-topic';
+$client = iggy_client();
+
+ensure_stream_and_topic($client, $stream, $topic);
+send_payloads($client, $stream, $topic, [

Review Comment:
   small consistency thing - the getting-started producer builds payloads via 
`example_payloads()` while this one uses an inline array. could call 
`example_payloads('basic', 3)` here so both follow one style.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to