Skip to content
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
db99b9b
fix(sentry): optimize HttpClient memory usage and error handling
huangdijia Sep 12, 2025
e1f73f0
fix(HttpClient): improve channel initialization and request handling …
huangdijia Sep 13, 2025
0c75dec
fix(HttpClient): prevent redundant loop initialization in channel man…
huangdijia Sep 13, 2025
6889d4d
fix(sentry): increase HTTP concurrent limit to improve request handling
huangdijia Sep 13, 2025
1eaaa87
fix(HttpClient): increase default concurrent limit to improve request…
huangdijia Sep 13, 2025
93a1026
fix(HttpClient): add memory usage and channel size logging in loop in…
huangdijia Sep 13, 2025
fdf031a
fix(HttpClient): rename variable for clarity in error handling
huangdijia Sep 13, 2025
15cc22a
fix(HttpClient): exit loop if channel is closing or pop fails
huangdijia Sep 13, 2025
9ec9e21
fix(HttpClient): comment out memory usage and channel size logging in…
huangdijia Sep 13, 2025
a4a6a67
fix(HttpClient): use func_get_args() for pushing requests to the channel
huangdijia Sep 13, 2025
51bd63a
fix(sentry): reduce default HTTP concurrent limit from 1000 to 100
huangdijia Sep 13, 2025
4cc0b5c
更新 HttpClient.php
huangdijia Sep 13, 2025
433b9f5
fix(HttpClient): rename closure variable to callable for clarity
huangdijia Sep 14, 2025
c30d560
fix(HttpClient): refactor request channel push and restore close method
huangdijia Sep 14, 2025
54ad2f2
fix(HttpClient): clear callable and args variables after use
huangdijia Sep 14, 2025
e7e11e3
fix(HttpClient): update request pushing to use explicit parameters
huangdijia Sep 15, 2025
e78deb2
fix(HttpClient): ensure channel is closed after request processing
huangdijia Sep 15, 2025
ec1d335
fix(HttpClient): simplify channel initialization and loop handling
huangdijia Sep 15, 2025
708c21e
Revert "fix(HttpClient): simplify channel initialization and loop han…
huangdijia Sep 15, 2025
52dd80b
fix(HttpClient): refactor channel initialization and loop handling
huangdijia Sep 15, 2025
a80204a
fix(HttpClient): update channel reference in memory usage logging
huangdijia Sep 15, 2025
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
89 changes: 52 additions & 37 deletions src/sentry/src/HttpClient/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

namespace FriendsOfHyperf\Sentry\HttpClient;

use Closure;
use Hyperf\Coordinator\Constants;
use Hyperf\Coordinator\CoordinatorManager;
use Hyperf\Coroutine\Concurrent;
Expand All @@ -22,6 +21,8 @@
use Sentry\Options;
use Throwable;

use function Hyperf\Tappable\tap;

class HttpClient extends \Sentry\HttpClient\HttpClient
{
protected ?Channel $chan = null;
Expand All @@ -47,62 +48,66 @@ public function __construct(

public function sendRequest(Request $request, Options $options): Response
{
// Start the loop if not started yet
$this->loop();

// Push the request to the channel
$chan = $this->chan;
$chan->push(fn () => parent::sendRequest($request, $options));
$chan?->push([$request, $options]);

return new Response(202, ['X-Sentry-Request-Status' => ['Queued']], '');
}

public function close(): void
{
$chan = $this->chan;
$this->chan = null;

$chan?->close();
}

protected function loop(): void
{
if ($this->chan != null) {
return;
}

// The worker already exited
if ($this->workerExited) {
return;
}

$this->chan = new Channel($this->channelSize);

Coroutine::create(function () {
try {
while (true) {
// Initialize the channel and start the loop
$this->chan ??= tap(new Channel($this->channelSize), function () {
// Dump memory usage and channel size
// Coroutine::create(function () {
// while (! $this->chan?->isClosing()) {
// dump('Memory Usage(MB): ' . memory_get_usage(true) / 1024 / 1024);
// dump('Channel Size: ' . $this->chan?->getLength());
// sleep(1);
// }
// });

// Start the loop
Coroutine::create(function () {
try {
while (true) {
/** @var Closure|null $closure */
$closure = $this->chan?->pop();
if (! $closure) {
break 2;
}
try {
if ($this->concurrent) {
$this->concurrent->create($closure);
} else {
Coroutine::create($closure);
while (true) {
// If the channel is closing or pop failed, exit the loop
if (! $args = $this->chan?->pop()) {
break 2;
}
try {
$callable = fn () => parent::sendRequest(...$args);
if ($this->concurrent) {
$this->concurrent->create($callable);
} else {
Coroutine::create($callable);
}
} catch (Throwable) {
break;
} finally {
$callable = null;
$args = null;
}
} catch (Throwable) {
break;
} finally {
$closure = null;
}
}
} catch (Throwable $e) {
} finally {
$this->close();
}
} catch (Throwable $e) {
} finally {
$this->close();
}
});
});

// Wait for the worker exit event
$this->waitingWorkerExit ??= Coroutine::create(function () {
try {
CoordinatorManager::until(Constants::WORKER_EXIT)->yield();
Expand All @@ -112,4 +117,14 @@ protected function loop(): void
}
});
}

protected function close(): void
{
$chan = $this->chan;
$chan?->close();

if ($this->chan === $chan) {
$this->chan = null;
}
}
}