@@ -594,11 +594,18 @@ class TAcquireRateLimiterResourceRPC : public TRateLimiterRequest<TAcquireRateLi
594594 SendRequest ();
595595 }
596596
597+ // Always race when "cancel after" time is not set.
598+ // If "cancel after" is not set, quoter service can spend resource and say "OK", but we here reply with TIMEOUT.
597599 void OnOperationTimeout (const TActorContext& ctx) {
598600 Send (MakeQuoterServiceID (), new TEvQuota::TEvRpcTimeout (GetProtoRequest ()->coordination_node_path (), GetProtoRequest ()->resource_path ()), 0 , 0 );
599601 TBase::OnOperationTimeout (ctx);
600602 }
601603
604+ // Do nothing here, because quoter service replies after "cancel after" time passes.
605+ void OnCancelOperation (const TActorContext& ctx) {
606+ Y_UNUSED (ctx);
607+ }
608+
602609 STFUNC (StateFunc) {
603610 switch (ev->GetTypeRewrite ()) {
604611 hFunc (TEvQuota::TEvClearance, Handle);
@@ -637,22 +644,37 @@ class TAcquireRateLimiterResourceRPC : public TRateLimiterRequest<TAcquireRateLi
637644 true ));
638645 }
639646
647+ StatusIds::StatusCode QuoterDeadlineStatusCode () {
648+ if (const TDuration cancelAfter = GetCancelAfter (); cancelAfter && cancelAfter < GetOperationTimeout ()) {
649+ return StatusIds::CANCELLED;
650+ }
651+ return StatusIds::TIMEOUT;
652+ }
653+
640654 void SendLeaf (const TEvQuota::TResourceLeaf& leaf) {
655+ TDuration deadline = GetOperationTimeout ();
656+ // CancelAfter is an intelligent way to say quoter service that we can wait maximum time.
657+ // After that time quoter service sends EResult::Deadline.
658+ // It says that the system lacks the resource.
659+ if (const TDuration cancelAfter = GetCancelAfter (); cancelAfter && cancelAfter < deadline) {
660+ deadline = cancelAfter;
661+ }
662+
641663 Send (MakeQuoterServiceID (),
642- new TEvQuota::TEvRequest (TEvQuota::EResourceOperator::And, { leaf }, GetOperationTimeout () ), 0 , 0 );
664+ new TEvQuota::TEvRequest (TEvQuota::EResourceOperator::And, { leaf }, deadline ), 0 , 0 );
643665 }
644666
645667 void Handle (TEvQuota::TEvClearance::TPtr& ev) {
646668 switch (ev->Get ()->Result ) {
647669 case TEvQuota::TEvClearance::EResult::Success:
648670 Reply (StatusIds::SUCCESS, TActivationContext::AsActorContext ());
649- break ;
671+ break ;
650672 case TEvQuota::TEvClearance::EResult::UnknownResource:
651673 Reply (StatusIds::BAD_REQUEST, TActivationContext::AsActorContext ());
652- break ;
674+ break ;
653675 case TEvQuota::TEvClearance::EResult::Deadline:
654- Reply (StatusIds::TIMEOUT , TActivationContext::AsActorContext ());
655- break ;
676+ Reply (QuoterDeadlineStatusCode () , TActivationContext::AsActorContext ());
677+ break ;
656678 default :
657679 Reply (StatusIds::INTERNAL_ERROR, TActivationContext::AsActorContext ());
658680 }
0 commit comments