示例#1
0
        /// <summary>
        /// Periodically performs the following steps:
        ///  0. keep alive the session
        // 	 1. collect the freshest command bulk
        //     2. try-send bulk
        // 	 3. validate response
        // 	 4. parse response and enqueue for retry if needed
        // 	 5. wait for N seconds (N grows with the number of consecutive connection failures)
        /// </summary>
        /// <returns>The send loop enumerator.</returns>
        private IEnumerator APISendLoop(string target, PersistentBulkCommandQueue commandQueue)
        {
            const int WAIT_FOR_DEFAULT = 3;
            var httpTarget = target + Constants.BULK_URL;
            int consecutiveFailedRequests = 0;

            while (true)
            {
                // Decide if we process retry commands or new commands in this round
                List<object> commands = commandQueue.BulkDequeue(true);

                if (commands.Count > 0)
                {
                    // 1B: Prepare the http components
                    var httpBody = Json.Serialize(new Dictionary<string,object> {{"commands", commands}});
                    byte[] httpBodyBytes = Encoding.UTF8.GetBytes(httpBody);
                    Dictionary<string,string> httpHeaders = new Dictionary<string,string>{ {"Content-type", "application/json"} };

                    // 2. Send the bulk API request
                    WWW req = new WWW(httpTarget, httpBodyBytes, httpHeaders); //TODO: we could add a timeout functionality
                    yield return req;

                    // 3A: Check response for errors
                    if (!string.IsNullOrEmpty(req.error))
                    {
                        consecutiveFailedRequests++;
                    }
                    else
                    {
                        // 3B. Parse the API response
                        var responseBody = req.text;
                        Dictionary<string, object> apiResponse = (Dictionary<string, object>) Json.Deserialize(responseBody);
                        bool success = (bool) apiResponse["success"];
                        if(success)
                        {
                            consecutiveFailedRequests = 0;

                            // 4A: extract retry-commands and queue them back (if any)
                            var retryCommands = ExtractRetryCommands(apiResponse,commands);
                            commandQueue.MultiDequeue(commands.Count); //remove every command from this request
                            commandQueue.MultiPush(retryCommands);     //re-add failed commands with the highest priority
                        }
                        else
                        {
                            consecutiveFailedRequests++;
                        }
                    }

                }

                // 5. Detemine wait time and go idle.
                float waitSeconds = (float)System.Math.Pow(WAIT_FOR_DEFAULT, System.Math.Sqrt(consecutiveFailedRequests+1));
                if(consecutiveFailedRequests == 0 && commandQueue.ElementCount > 0)
                {
                    waitSeconds = 0f;
                }
                waitSeconds = System.Math.Min (waitSeconds, Constants.BULK_MAX - 3f);

                yield return new WaitForSeconds(waitSeconds);
            }
        }
示例#2
0
 public Sender(string target, PersistentBulkCommandQueue commandQueue)
 {
     this.StartCoroutine (APISendLoop(target, commandQueue));
 }