Skip to content

Commit f29bf1e

Browse files
qyryqGazizonoki
authored andcommitted
Moved "TFederatedWriteSession: take into account AllowFallback setting; use retry policy" commit from ydb repo
1 parent 94c9a31 commit f29bf1e

File tree

2 files changed

+90
-29
lines changed

2 files changed

+90
-29
lines changed

src/client/federated_topic/impl/federated_write_session.cpp

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -129,50 +129,92 @@ void TFederatedWriteSessionImpl::OpenSubSessionImpl(std::shared_ptr<TDbInfo> db)
129129
CurrentDatabase = db;
130130
}
131131

132-
std::shared_ptr<TDbInfo> TFederatedWriteSessionImpl::SelectDatabaseImpl() {
133-
std::vector<std::shared_ptr<TDbInfo>> availableDatabases;
132+
std::pair<std::shared_ptr<TDbInfo>, EStatus> SelectDatabaseByHash(
133+
NTopic::TFederatedWriteSessionSettings const& settings,
134+
std::vector<std::shared_ptr<TDbInfo>> const& dbInfos
135+
) {
134136
ui64 totalWeight = 0;
137+
std::vector<std::shared_ptr<TDbInfo>> available;
135138

136-
for (const auto& db : FederationState->DbInfos) {
137-
if (db->status() != TDbInfo::Status::DatabaseInfo_Status_AVAILABLE) {
138-
continue;
139-
}
140-
141-
if (Settings.PreferredDatabase_ && (AsciiEqualsIgnoreCase(db->name(), *Settings.PreferredDatabase_) ||
142-
AsciiEqualsIgnoreCase(db->id(), *Settings.PreferredDatabase_))) {
143-
return db;
144-
} else if (AsciiEqualsIgnoreCase(FederationState->SelfLocation, db->location())) {
145-
return db;
146-
} else {
147-
availableDatabases.push_back(db);
139+
for (const auto& db : dbInfos) {
140+
if (db->status() == TDbInfo::Status::DatabaseInfo_Status_AVAILABLE) {
141+
available.push_back(db);
148142
totalWeight += db->weight();
149143
}
150144
}
151145

152-
if (availableDatabases.empty() || totalWeight == 0) {
153-
// close session, return error
154-
return nullptr;
146+
if (available.empty() || totalWeight == 0) {
147+
return {nullptr, EStatus::NOT_FOUND};
155148
}
156149

157-
std::sort(availableDatabases.begin(), availableDatabases.end(), [](const std::shared_ptr<TDbInfo>& lhs, const std::shared_ptr<TDbInfo>& rhs){
158-
return lhs->weight() > rhs->weight()
159-
|| lhs->weight() == rhs->weight() && lhs->name() < rhs->name();
160-
});
150+
std::sort(available.begin(), available.end(), [](auto const& lhs, auto const& rhs) { return lhs->name() < rhs->name(); });
161151

162-
ui64 hashValue = THash<std::string>()(Settings.Path_);
163-
hashValue = CombineHashes(hashValue, THash<std::string>()(Settings.ProducerId_));
152+
ui64 hashValue = THash<std::string>()(settings.Path_);
153+
hashValue = CombineHashes(hashValue, THash<std::string>()(settings.ProducerId_));
164154
hashValue %= totalWeight;
165155

166156
ui64 borderWeight = 0;
167-
for (const auto& db : availableDatabases) {
157+
for (auto const& db : available) {
168158
borderWeight += db->weight();
169159
if (hashValue < borderWeight) {
170-
return db;
160+
return {db, EStatus::SUCCESS};
171161
}
172162
}
173163
Y_UNREACHABLE();
174164
}
175165

166+
std::pair<std::shared_ptr<TDbInfo>, EStatus> SelectDatabase(
167+
NTopic::TFederatedWriteSessionSettings const& settings,
168+
std::vector<std::shared_ptr<TDbInfo>> const& dbInfos, std::string const& selfLocation
169+
) {
170+
/* Logic of the function should follow this table:
171+
| PreferredDb | Preferred state | Local state | AllowFallback | Return |
172+
|-------------+-----------------+-------------+---------------+-------------|
173+
| set | not found | - | any | NOT_FOUND |
174+
| set | available | - | any | preferred |
175+
| set | unavailable | - | false | UNAVAILABLE |
176+
| set | unavailable | - | true | by hash |
177+
| unset | - | not found | false | NOT_FOUND |
178+
| unset | - | not found | true | by hash |
179+
| unset | - | available | any | local |
180+
| unset | - | unavailable | false | UNAVAILABLE |
181+
| unset | - | unavailable | true | by hash |
182+
*/
183+
184+
decltype(begin(dbInfos)) it;
185+
if (settings.PreferredDatabase_) {
186+
it = std::find_if(begin(dbInfos), end(dbInfos), [&preferred = settings.PreferredDatabase_](auto const& db) {
187+
return AsciiEqualsIgnoreCase(*preferred, db->name()) || AsciiEqualsIgnoreCase(*preferred, db->id());
188+
});
189+
if (it == end(dbInfos)) {
190+
return {nullptr, EStatus::NOT_FOUND};
191+
}
192+
} else {
193+
it = std::find_if(begin(dbInfos), end(dbInfos), [&selfLocation](auto const& db) {
194+
return AsciiEqualsIgnoreCase(selfLocation, db->location());
195+
});
196+
if (it == end(dbInfos)) {
197+
if (!settings.AllowFallback_) {
198+
return {nullptr, EStatus::NOT_FOUND};
199+
}
200+
return SelectDatabaseByHash(settings, dbInfos);
201+
}
202+
}
203+
204+
auto db = *it;
205+
if (db->status() == TDbInfo::Status::DatabaseInfo_Status_AVAILABLE) {
206+
return {db, EStatus::SUCCESS};
207+
}
208+
if (!settings.AllowFallback_) {
209+
return {nullptr, EStatus::UNAVAILABLE};
210+
}
211+
return SelectDatabaseByHash(settings, dbInfos);
212+
}
213+
214+
std::pair<std::shared_ptr<TDbInfo>, EStatus> TFederatedWriteSessionImpl::SelectDatabaseImpl() {
215+
return SelectDatabase(Settings, FederationState->DbInfos, FederationState->SelfLocation);
216+
}
217+
176218
void TFederatedWriteSessionImpl::OnFederatedStateUpdateImpl() {
177219
if (!FederationState->Status.IsSuccess()) {
178220
CloseImpl(FederationState->Status.GetStatus(), NYql::TIssues(FederationState->Status.GetIssues()));
@@ -181,13 +223,23 @@ void TFederatedWriteSessionImpl::OnFederatedStateUpdateImpl() {
181223

182224
Y_ABORT_UNLESS(!FederationState->DbInfos.empty());
183225

184-
auto preferrableDb = SelectDatabaseImpl();
226+
auto [preferrableDb, status] = SelectDatabaseImpl();
185227

186228
if (!preferrableDb) {
187-
CloseImpl(EStatus::UNAVAILABLE,
188-
NYql::TIssues{NYql::TIssue("Fail to select database: no available database with positive weight")});
229+
if (!RetryState) {
230+
RetryState = Settings.RetryPolicy_->CreateRetryState();
231+
}
232+
if (auto delay = RetryState->GetNextRetryDelay(status)) {
233+
LOG_LAZY(Log, TLOG_NOTICE, GetLogPrefix() << "Retry to update federation state in " << delay);
234+
ScheduleFederatedStateUpdateImpl(*delay);
235+
} else {
236+
std::string message = "Failed to select database: no available database";
237+
LOG_LAZY(Log, TLOG_ERR, GetLogPrefix() << message);
238+
CloseImpl(status, NYql::TIssues{NYql::TIssue(message)});
239+
}
189240
return;
190241
}
242+
RetryState.reset();
191243

192244
if (!DatabasesAreSame(preferrableDb, CurrentDatabase)) {
193245
LOG_LAZY(Log, TLOG_INFO, GetLogPrefix()

src/client/federated_topic/impl/federated_write_session.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
namespace NYdb::NFederatedTopic {
1212

13+
std::pair<std::shared_ptr<TDbInfo>, EStatus> SelectDatabaseByHash(
14+
NTopic::TFederatedWriteSessionSettings const& settings,
15+
std::vector<std::shared_ptr<TDbInfo>> const& dbInfos);
16+
17+
std::pair<std::shared_ptr<TDbInfo>, EStatus> SelectDatabase(
18+
NTopic::TFederatedWriteSessionSettings const& settings,
19+
std::vector<std::shared_ptr<TDbInfo>> const& dbInfos, std::string const& selfLocation);
20+
1321
class TFederatedWriteSessionImpl : public NTopic::TContinuationTokenIssuer,
1422
public NTopic::TEnableSelfContext<TFederatedWriteSessionImpl> {
1523
friend class TFederatedWriteSession;
@@ -77,7 +85,7 @@ class TFederatedWriteSessionImpl : public NTopic::TContinuationTokenIssuer,
7785
void Start();
7886
void OpenSubSessionImpl(std::shared_ptr<TDbInfo> db);
7987

80-
std::shared_ptr<TDbInfo> SelectDatabaseImpl();
88+
std::pair<std::shared_ptr<TDbInfo>, EStatus> SelectDatabaseImpl();
8189

8290
void OnFederatedStateUpdateImpl();
8391
void ScheduleFederatedStateUpdateImpl(TDuration delay);
@@ -97,6 +105,7 @@ class TFederatedWriteSessionImpl : public NTopic::TContinuationTokenIssuer,
97105
const NTopic::TTopicClientSettings SubClientSetttings;
98106
std::shared_ptr<std::unordered_map<NTopic::ECodec, THolder<NTopic::ICodec>>> ProvidedCodecs;
99107

108+
NTopic::IRetryPolicy::IRetryState::TPtr RetryState;
100109
std::shared_ptr<TFederatedDbObserver> Observer;
101110
NThreading::TFuture<void> AsyncInit;
102111
std::shared_ptr<TFederatedDbState> FederationState;

0 commit comments

Comments
 (0)