public override void Initialize(string projectToken, string appVersion, string target) { this.projectToken = projectToken; this.appVersion = appVersion; deviceProperties = Device.GetProperties(); customerIds = storage.GetIds(); commandQueue = new PersistentBulkCommandQueue("events", Constants.BULK_LIMIT); sender = new Sender.Sender((target != null) ? target : Constants.DEFAULT_TARGET, commandQueue); }
/// <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); // 2. Send the bulk API request UnityWebRequest req = new UnityWebRequest(httpTarget, "POST"); req.uploadHandler = (UploadHandler) new UploadHandlerRaw(httpBodyBytes); req.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer(); req.SetRequestHeader("Content-Type", "application/json"); yield return(req.SendWebRequest()); // 3A: Check response for errors if (!string.IsNullOrEmpty(req.error)) { consecutiveFailedRequests++; } else { // 3B. Parse the API response var responseBody = req.downloadHandler.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)); } }
public Sender(string target, PersistentBulkCommandQueue commandQueue) { this.StartCoroutine(APISendLoop(target, commandQueue)); _target = target; }