1
1
<?php
2
+ // manual_loop_test.php
2
3
3
- use Rcalicdan \FiberAsync \Api \File ;
4
- use Rcalicdan \FiberAsync \Defer \Defer ;
4
+ require_once 'vendor/autoload.php ' ;
5
5
6
- require ' vendor/autoload.php ' ;
6
+ use Rcalicdan \ FiberAsync \ Api \ AsyncStream ;
7
7
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" ;
12
10
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" ;
22
14
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 ' );
29
34
}
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 ;
42
38
});
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
+ }
43
45
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" ;
51
49
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" ;
56
52
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 ();
67
75
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" ;
81
77
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" ;
91
79
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 " ;
94
82
}
95
83
96
- ?>
84
+ // Test 3: Reset AsyncStream between operations
85
+ echo "Test 3: Reset AsyncStream between operations \n" ;
86
+ echo "-------------------------------------------- \n" ;
97
87
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 " ));
139
99
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 ' );
144
106
}
145
107
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 );
185
111
186
- <div id="timing- result"></div>
112
+ echo " ✅ Reset test: " . ( $ result ? ' PASS ' : ' FAIL ' ) . "\n\n" ;
187
113
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