Skip to content

Commit 9e75eb3

Browse files
committed
Add Stream Api
1 parent 575372d commit 9e75eb3

File tree

5 files changed

+1202
-177
lines changed

5 files changed

+1202
-177
lines changed

index.php

Lines changed: 97 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,199 +1,119 @@
11
<?php
2+
// manual_loop_test.php
23

3-
use Rcalicdan\FiberAsync\Api\File;
4-
use Rcalicdan\FiberAsync\Defer\Defer;
4+
require_once 'vendor/autoload.php';
55

6-
require 'vendor/autoload.php';
6+
use Rcalicdan\FiberAsync\Api\AsyncStream;
77

8-
if ($_SERVER["REQUEST_METHOD"] == "POST") {
9-
$requestTime = microtime(true);
10-
error_log("=== REQUEST STARTED ===");
11-
error_log("Registering terminate callback at " . date('Y-m-d H:i:s.u'));
8+
echo "🧪 Manual Event Loop Management Test\n";
9+
echo "====================================\n";
1210

13-
Defer::terminate(function () use ($requestTime) {
14-
$terminateStart = microtime(true);
15-
$delayFromRequest = $terminateStart - $requestTime;
16-
17-
error_log("=== TERMINATE CALLBACK STARTED ===");
18-
error_log("Terminate callback started at " . date('Y-m-d H:i:s.u'));
19-
error_log("Delay from request: " . number_format($delayFromRequest, 3) . " seconds");
20-
21-
sleep(5);
11+
// Test 1: Using run_stateful instead of run
12+
echo "Test 1: Using run_stateful\n";
13+
echo "--------------------------\n";
2214

23-
try {
24-
File::write('txt.txt', "Hello World from terminate callback - " . date('Y-m-d H:i:s'))->await();
25-
$totalTime = microtime(true) - $terminateStart;
26-
error_log("File written successfully after " . number_format($totalTime, 3) . " seconds");
27-
} catch (Exception $e) {
28-
error_log("Error in terminate callback: " . $e->getMessage());
15+
try {
16+
echo "🚀 Testing run_stateful...\n";
17+
18+
$result = run_stateful(function() {
19+
echo " 📝 Opening file...\n";
20+
$stream = await(AsyncStream::open('stateful_test.txt', 'w'));
21+
22+
echo " ✍️ Writing...\n";
23+
await(AsyncStream::write($stream, "Stateful test"));
24+
25+
echo " 🚿 Flushing...\n";
26+
await(AsyncStream::flush($stream));
27+
28+
echo " 🔒 Closing...\n";
29+
AsyncStream::close($stream);
30+
31+
echo " 🧹 Cleanup...\n";
32+
if (file_exists('stateful_test.txt')) {
33+
unlink('stateful_test.txt');
2934
}
30-
31-
$totalExecutionTime = microtime(true) - $requestTime;
32-
error_log("Terminate callback completed at " . date('Y-m-d H:i:s.u'));
33-
error_log("Total time from request: " . number_format($totalExecutionTime, 3) . " seconds");
34-
error_log("=== TERMINATE CALLBACK ENDED ===");
35-
});
36-
37-
Defer::global(function () use ($requestTime) {
38-
$globalStart = microtime(true);
39-
$delayFromRequest = $globalStart - $requestTime;
40-
error_log("Global defer executed at " . date('Y-m-d H:i:s.u'));
41-
error_log("Global defer delay from request: " . number_format($delayFromRequest, 3) . " seconds");
35+
36+
echo " ✅ Done\n";
37+
return true;
4238
});
39+
40+
echo "✅ run_stateful test: " . ($result ? 'PASS' : 'FAIL') . "\n\n";
41+
42+
} catch (Exception $e) {
43+
echo "❌ Error with run_stateful: " . $e->getMessage() . "\n\n";
44+
}
4345

44-
$stats = Defer::getStats();
45-
error_log("Defer stats: " . json_encode($stats, JSON_PRETTY_PRINT));
46-
47-
$responseTime = microtime(true);
48-
error_log("Response being sent at " . date('Y-m-d H:i:s.u'));
49-
error_log("Response time: " . number_format(($responseTime - $requestTime) * 1000, 2) . " ms");
50-
error_log("=== RESPONSE SENT ===");
46+
// Test 2: Using async + run combination
47+
echo "Test 2: Using async function with run\n";
48+
echo "-------------------------------------\n";
5149

52-
echo "<div style='padding: 20px; font-family: Arial, sans-serif;'>";
53-
echo "<h2>✅ Form Submitted Successfully!</h2>";
54-
echo "<p><strong>Response sent immediately</strong> - The background task is now running.</p>";
55-
echo "<p>Check <code>txt.txt</code> file in 5+ seconds and your error log for detailed timing.</p>";
50+
try {
51+
echo "🚀 Creating async function...\n";
5652

57-
echo "<h3>Environment Information:</h3>";
58-
echo "<div style='background: #f5f5f5; padding: 10px; border-radius: 5px; font-family: monospace;'>";
59-
echo "<strong>SAPI:</strong> " . $stats['environment']['sapi'] . "<br>";
60-
echo "<strong>FastCGI Environment:</strong> " . ($stats['environment']['fastcgi'] ? 'Yes' : 'No') . "<br>";
61-
echo "<strong>fastcgi_finish_request:</strong> " . ($stats['environment']['fastcgi_finish_request'] ? 'Available' : 'Not Available') . "<br>";
62-
echo "<strong>Output Buffering Level:</strong> " . $stats['environment']['output_buffering'] . "<br>";
63-
echo "<strong>Global Defers:</strong> " . $stats['global_defers'] . "<br>";
64-
echo "<strong>Terminate Callbacks:</strong> " . $stats['terminate_callbacks'] . "<br>";
65-
echo "<strong>Memory Usage:</strong> " . number_format($stats['memory_usage'] / 1024 / 1024, 2) . " MB<br>";
66-
echo "</div>";
53+
// Create the async function first
54+
$result = async(function() {
55+
echo " 📝 In async function - Opening file...\n";
56+
$stream = await(AsyncStream::open('async_func_test.txt', 'w'));
57+
58+
echo " ✍️ Writing...\n";
59+
await(AsyncStream::write($stream, "Async function test"));
60+
61+
echo " 🚿 Flushing...\n";
62+
await(AsyncStream::flush($stream));
63+
64+
echo " 🔒 Closing...\n";
65+
AsyncStream::close($stream);
66+
67+
echo " 🧹 Cleanup...\n";
68+
if (file_exists('async_func_test.txt')) {
69+
unlink('async_func_test.txt');
70+
}
71+
72+
echo " ✅ Async function done\n";
73+
return true;
74+
})->await();
6775

68-
echo "<h3>What Should Happen:</h3>";
69-
echo "<ul>";
70-
echo "<li>✅ You see this response immediately (not after 5 seconds)</li>";
71-
echo "<li>🔄 Background task runs after response is sent</li>";
72-
echo "<li>📝 File <code>txt.txt</code> appears in ~5+ seconds</li>";
73-
echo "<li>📋 Detailed timing in error log</li>";
74-
echo "</ul>";
75-
echo "</div>";
76-
77-
} else {
78-
echo "<div style='padding: 20px; font-family: Arial, sans-serif;'>";
79-
echo "<h1>Defer Terminate Test</h1>";
80-
echo "<p>This test demonstrates Laravel-style defer functionality that executes <strong>after</strong> the HTTP response is sent.</p>";
76+
echo "🔄 Running async function...\n";
8177

82-
// Show current environment info
83-
$stats = Defer::getStats();
84-
echo "<h3>Current Environment:</h3>";
85-
echo "<div style='background: #f0f8ff; padding: 10px; border-radius: 5px; font-family: monospace;'>";
86-
echo "<strong>PHP SAPI:</strong> " . PHP_SAPI . "<br>";
87-
echo "<strong>FastCGI Available:</strong> " . (function_exists('fastcgi_finish_request') ? 'Yes' : 'No') . "<br>";
88-
echo "<strong>OS:</strong> " . PHP_OS_FAMILY . "<br>";
89-
echo "<strong>PHP Version:</strong> " . PHP_VERSION . "<br>";
90-
echo "</div>";
78+
echo "✅ Async function test: " . ($result ? 'PASS' : 'FAIL') . "\n\n";
9179

92-
echo "<p><strong>Click submit to test:</strong></p>";
93-
echo "</div>";
80+
} catch (Exception $e) {
81+
echo "❌ Error with async function: " . $e->getMessage() . "\n\n";
9482
}
9583

96-
?>
84+
// Test 3: Reset AsyncStream between operations
85+
echo "Test 3: Reset AsyncStream between operations\n";
86+
echo "--------------------------------------------\n";
9787

98-
<!DOCTYPE html>
99-
<html lang="en">
100-
<head>
101-
<meta charset="UTF-8">
102-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
103-
<title>Defer Terminate Test</title>
104-
<style>
105-
body {
106-
font-family: Arial, sans-serif;
107-
max-width: 800px;
108-
margin: 0 auto;
109-
padding: 20px;
110-
line-height: 1.6;
111-
}
112-
.form-container {
113-
background: #f9f9f9;
114-
padding: 20px;
115-
border-radius: 8px;
116-
margin: 20px 0;
117-
}
118-
button {
119-
background: #007cba;
120-
color: white;
121-
padding: 12px 24px;
122-
border: none;
123-
border-radius: 4px;
124-
font-size: 16px;
125-
cursor: pointer;
126-
}
127-
button:hover {
128-
background: #005a87;
129-
}
130-
.timing-info {
131-
background: #e8f5e8;
132-
padding: 15px;
133-
border-radius: 5px;
134-
margin: 20px 0;
135-
}
136-
</style>
137-
<script>
138-
let startTime;
88+
try {
89+
echo "🔄 Resetting AsyncStream...\n";
90+
AsyncStream::reset();
91+
92+
echo "🚀 Testing after reset...\n";
93+
$result = run_with_timeout(function() {
94+
echo " 📝 Opening file after reset...\n";
95+
$stream = await(AsyncStream::open('reset_test.txt', 'w'));
96+
97+
echo " ✍️ Writing...\n";
98+
await(AsyncStream::write($stream, "Reset test"));
13999

140-
function startTiming() {
141-
startTime = Date.now();
142-
document.getElementById('status').innerHTML =
143-
'<div style="color: #666;">⏳ Request sent, waiting for response...</div>';
100+
echo " 🔒 Closing...\n";
101+
AsyncStream::close($stream);
102+
103+
echo " 🧹 Cleanup...\n";
104+
if (file_exists('reset_test.txt')) {
105+
unlink('reset_test.txt');
144106
}
145107

146-
window.onload = function() {
147-
<?php if ($_SERVER["REQUEST_METHOD"] == "POST"): ?>
148-
const endTime = Date.now();
149-
const responseTime = endTime - (startTime || endTime);
150-
151-
document.getElementById('timing-result').innerHTML =
152-
'<div class="timing-info">' +
153-
'<h4>✅ Response Timing Verified!</h4>' +
154-
'<p>This response was received <strong>immediately</strong>, not after the 5-second sleep.</p>' +
155-
'<p>The background task is running separately and will complete in ~5+ seconds.</p>' +
156-
'</div>';
157-
158-
// Show a countdown for when to check the file
159-
let countdown = 6;
160-
const countdownElement = document.createElement('div');
161-
countdownElement.style.cssText = 'background: #fff3cd; padding: 10px; border-radius: 5px; margin: 10px 0;';
162-
document.body.appendChild(countdownElement);
163-
164-
const timer = setInterval(() => {
165-
countdown--;
166-
if (countdown > 0) {
167-
countdownElement.innerHTML = `<strong>⏰ Check txt.txt file in ${countdown} seconds...</strong>`;
168-
} else {
169-
countdownElement.innerHTML = '<strong>🔍 Check txt.txt file now! It should have been created.</strong>';
170-
countdownElement.style.background = '#d4edda';
171-
clearInterval(timer);
172-
}
173-
}, 1000);
174-
<?php endif; ?>
175-
};
176-
</script>
177-
</head>
178-
<body>
179-
<div class="form-container">
180-
<form method="post" onsubmit="startTiming()">
181-
<button type="submit">🚀 Test Defer Terminate</button>
182-
</form>
183-
<div id="status"></div>
184-
</div>
108+
echo " ✅ Reset test done\n";
109+
return true;
110+
}, 3.0);
185111

186-
<div id="timing-result"></div>
112+
echo "✅ Reset test: " . ($result ? 'PASS' : 'FAIL') . "\n\n";
187113

188-
<div style="background: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0; font-size: 14px;">
189-
<h4>How to Verify It's Working:</h4>
190-
<ol>
191-
<li><strong>Immediate Response:</strong> You should see the response instantly (not after 5 seconds)</li>
192-
<li><strong>Background Execution:</strong> The <code>txt.txt</code> file will appear in ~5-8 seconds</li>
193-
<li><strong>Check Error Log:</strong> Detailed timing information will be logged</li>
194-
</ol>
195-
196-
<p><strong>💡 Tip:</strong> Open your browser's developer tools (F12) and watch the Network tab to see the actual response time.</p>
197-
</div>
198-
</body>
199-
</html>
114+
} catch (Exception $e) {
115+
echo "❌ Error with reset test: " . $e->getMessage() . "\n\n";
116+
}
117+
118+
echo "🏁 Manual loop management tests completed\n";
119+
exit(0);

0 commit comments

Comments
 (0)