@@ -47,6 +47,14 @@ class AISCommand final : public LLHTTPClient::ResponderWithCompleted
4747public:
4848 typedef boost::function<void ()> command_func_type;
4949 // AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
50+
51+ // Limit max in flight requests to 2. Server was aggressively throttling otherwise.
52+ constexpr static U8 sMaxActiveAISCommands = 4 ;
53+ static U8 sActiveAISCommands ;
54+ static std::queue< boost::intrusive_ptr< AISCommand > > sPendingAISCommands ;
55+
56+ virtual AIHTTPTimeoutPolicy const & getHTTPTimeoutPolicy (void ) const { return AISAPIResponder_timeout; }
57+
5058 AISCommand (AISAPI::COMMAND_TYPE type, const char * name, const LLUUID& targetId, AISAPI::completion_t callback) :
5159 mCommandFunc (NULL ),
5260 mRetryPolicy (new LLAdaptiveRetryPolicy(1.0 , 32.0 , 2.0 , 10 )),
@@ -55,13 +63,30 @@ class AISCommand final : public LLHTTPClient::ResponderWithCompleted
5563 mName (name),
5664 mType (type)
5765 {}
58-
59- virtual AIHTTPTimeoutPolicy const & getHTTPTimeoutPolicy (void ) const { return AISAPIResponder_timeout; }
66+ virtual ~AISCommand ()
67+ {
68+ if (mActive )
69+ {
70+ --sActiveAISCommands ;
71+ while (sActiveAISCommands < sMaxActiveAISCommands && !sPendingAISCommands .empty ())
72+ {
73+ sPendingAISCommands .front ()->dispatch ();
74+ sPendingAISCommands .pop ();
75+ }
76+ }
77+ }
6078
6179 void run ( command_func_type func )
6280 {
63- LL_WARNS (" Inventory" ) << " Sending request for " << getName () <<" : " << mURL << LL_ENDL;
64- (mCommandFunc = func)();
81+ mCommandFunc = func;
82+ if (sActiveAISCommands >= sMaxActiveAISCommands )
83+ {
84+ sPendingAISCommands .push (this );
85+ }
86+ else
87+ {
88+ dispatch ();
89+ }
6590 }
6691
6792 char const * getName (void ) const override
@@ -70,6 +95,16 @@ class AISCommand final : public LLHTTPClient::ResponderWithCompleted
7095 }
7196
7297private:
98+ void dispatch ()
99+ {
100+ if (LLApp::isQuitting ())
101+ {
102+ return ;
103+ }
104+ ++sActiveAISCommands ;
105+ mActive = true ;
106+ (mCommandFunc )();
107+ }
73108 void markComplete ()
74109 {
75110 // Command func holds a reference to self, need to release it
@@ -84,6 +119,11 @@ class AISCommand final : public LLHTTPClient::ResponderWithCompleted
84119 F32 seconds_to_wait;
85120 if (mRetryPolicy ->shouldRetry (seconds_to_wait))
86121 {
122+ if (mStatus == 503 )
123+ {
124+ // Pad delay a bit more since we're getting throttled.
125+ seconds_to_wait += 10 .f + ll_frand (4 .f );
126+ }
87127 LL_WARNS (" Inventory" ) << " Retrying in " << seconds_to_wait << " seconds due to inventory error for " << getName () <<" : " << dumpResponse () << LL_ENDL;
88128 doAfterInterval (mCommandFunc ,seconds_to_wait);
89129 return true ;
@@ -116,9 +156,13 @@ class AISCommand final : public LLHTTPClient::ResponderWithCompleted
116156 AISAPI::completion_t mCompletionFunc ;
117157 const LLUUID mTargetId ;
118158 const char * mName ;
159+ bool mActive = false ;
119160 AISAPI::COMMAND_TYPE mType ;
120161};
121162
163+ U8 AISCommand::sActiveAISCommands = 0 ;
164+ std::queue< boost::intrusive_ptr< AISCommand > > AISCommand::sPendingAISCommands ;
165+
122166// =========================================================================
123167const std::string AISAPI::INVENTORY_CAP_NAME (" InventoryAPIv3" );
124168const std::string AISAPI::LIBRARY_CAP_NAME (" LibraryAPIv3" );
@@ -333,11 +377,8 @@ void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithCompleted* responde
333377
334378 if (!responder->isGoodStatus (status) || !result.isMap ())
335379 {
336- if (!result.isMap ())
337- {
338- LL_WARNS (" Inventory" ) << " Inventory error: " << HTTP_INTERNAL_ERROR_OTHER << " : " << " Malformed response contents" << LL_ENDL;
339- }
340- else if (status == 410 ) // GONE
380+ LL_WARNS (" Inventory" ) << " Inventory error: " << status << " : " << responder->getReason () << LL_ENDL;
381+ if (status == 410 ) // GONE
341382 {
342383 // Item does not exist or was already deleted from server.
343384 // parent folder is out of sync
@@ -370,7 +411,10 @@ void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithCompleted* responde
370411 gInventory .onObjectDeletedFromServer (targetId);
371412 }
372413 }
373- LL_WARNS (" Inventory" ) << " Inventory error: " << status << " : " << responder->getReason () << LL_ENDL;
414+ }
415+ if (!result.isMap ())
416+ {
417+ LL_WARNS (" Inventory" ) << " Inventory error: Malformed response contents" << LL_ENDL;
374418 }
375419 LL_WARNS (" Inventory" ) << ll_pretty_print_sd (result) << LL_ENDL;
376420 }
0 commit comments