Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
* logged failed discovery refresh in `checkDiscovery` instead of silently swallowing the exception
* fixed discovery retry rate after a failure: a separate `lastDiscoveryAttempt` timer gates retries by `discoveryInterval()`, so a broken discovery no longer triggers `discover()` on every API request

## 1.16.1
* added resilient internal endpoint discovery (`YdbPlatform\Ydb\Internal\Discovery`) that always targets the original bootstrap endpoint and recreates the gRPC channel with `force_new` on retries to bust the c-core DNS cache and survive bootstrap IP changes
* added discovery tuning config keys: `discoveryTimeoutMs` (default 1000), `discoveryAttemptTimeoutMs` (default 300), `discoveryInitialTimeoutMs` (default 5000; set to `PHP_INT_MAX` to wait indefinitely on startup)
Expand Down
2 changes: 1 addition & 1 deletion src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use YdbPlatform\Ydb\Retry\Retry;
use YdbPlatform\Ydb\Retry\RetryParams;

class Table
class Table
{
use Traits\RequestTrait;
use Traits\ParseResultTrait;
Expand Down
39 changes: 32 additions & 7 deletions src/Traits/RequestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,19 @@ trait RequestTrait
protected $ydb;

/**
* @var int
* @var int Timestamp of the last SUCCESSFUL discovery. Drives the regular
* refresh schedule via discoveryInterval().
*/
protected $lastDiscovery = 0;

/**
* @var int Timestamp of the last FAILED discovery attempt. Used to avoid
* calling discover() on every API request while it is down — under
* load each request would otherwise pay ~discoveryTimeoutMs on top
* until discovery recovers.
*/
protected $lastDiscoveryAttempt = 0;



/**
Expand Down Expand Up @@ -315,13 +324,29 @@ protected function resetLastRequest()
}

protected function checkDiscovery(){
if ($this->ydb->needDiscovery() && time()-$this->lastDiscovery>$this->ydb->discoveryInterval()){
try{
$this->lastDiscovery = time();
$this->ydb->discover();
} catch (\Exception $e){
if (!$this->ydb->needDiscovery()) {
return;
}
$now = time();
$interval = $this->ydb->discoveryInterval();

// Scheduled refresh is gated by the last success; retries after a
// failure are gated by lastDiscoveryAttempt so a broken discovery
// does not get called on every single API request.
if ($now - $this->lastDiscovery <= $interval) {
return;
}
if ($now - $this->lastDiscoveryAttempt <= $interval) {
return;
}

}
$this->lastDiscoveryAttempt = $now;
try {
$this->logger()->debug('YDB: discovery for update ydb nodes list.');
$this->ydb->discover();
$this->lastDiscovery = $now;
} catch (\Exception $e) {
$this->logger()->warning('YDB: discovery refresh failed: ' . $e->getMessage());
}
}

Expand Down
Loading