/// <summary> /// Asynchronously retrieves logs from storage and flags them to avoid duplicate retrievals on subsequent calls /// </summary> /// <param name="channelName">Name of the channel to retrieve logs from</param> /// <param name="limit">The maximum number of logs to retrieve</param> /// <param name="logs">A list to which the retrieved logs will be added</param> /// <returns>A batch ID for the set of returned logs; null if no logs are found</returns> /// <exception cref="StorageException"/> public Task <string> GetLogsAsync(string channelName, int limit, List <Log> logs) { return(AddTaskToQueue(() => { logs?.Clear(); var retrievedLogs = new List <Log>(); AppCenterLog.Debug(AppCenterLog.LogTag, $"Trying to get up to {limit} logs from storage for {channelName}"); var idPairs = new List <Tuple <Guid?, long> >(); var failedToDeserializeALog = false; var retrievedEntries = _storageAdapter.GetAsync <LogEntry>(entry => entry.Channel == channelName, limit) .GetAwaiter().GetResult(); foreach (var entry in retrievedEntries) { if (_pendingDbIdentifiers.Contains(entry.Id)) { continue; } try { var log = LogSerializer.DeserializeLog(entry.Log); retrievedLogs.Add(log); idPairs.Add(Tuple.Create(log.Sid, Convert.ToInt64(entry.Id))); } catch (JsonException e) { AppCenterLog.Error(AppCenterLog.LogTag, "Cannot deserialize a log in storage", e); failedToDeserializeALog = true; _storageAdapter.DeleteAsync <LogEntry>(row => row.Id == entry.Id) .GetAwaiter().GetResult(); } } if (failedToDeserializeALog) { AppCenterLog.Warn(AppCenterLog.LogTag, "Deleted logs that could not be deserialized"); } if (idPairs.Count == 0) { AppCenterLog.Debug(AppCenterLog.LogTag, $"No available logs in storage for channel '{channelName}'"); return null; } // Process the results var batchId = Guid.NewGuid().ToString(); ProcessLogIds(channelName, batchId, idPairs); logs?.AddRange(retrievedLogs); return batchId; })); }
/// <summary> /// Asynchronously retrieves logs from storage and flags them to avoid duplicate retrievals on subsequent calls /// </summary> /// <param name="channelName">Name of the channel to retrieve logs from</param> /// <param name="limit">The maximum number of logs to retrieve</param> /// <param name="logs">A list to which the retrieved logs will be added</param> /// <returns>A batch ID for the set of returned logs; null if no logs are found</returns> /// <exception cref="StorageException"/> public async Task <string> GetLogsAsync(string channelName, int limit, List <Log> logs) { var task = new Task <string>(() => { logs?.Clear(); var retrievedLogs = new List <Log>(); MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Trying to get up to {limit} logs from storage for {channelName}"); var idPairs = new List <Tuple <Guid?, long> >(); var failedToDeserializeALog = false; var retrievedEntries = _storageAdapter.GetAsync <LogEntry>(entry => entry.Channel == channelName, limit) .Result; foreach (var entry in retrievedEntries) { if (_pendingDbIdentifiers.Contains(entry.Id)) { continue; } try { var log = LogSerializer.DeserializeLog(entry.Log); retrievedLogs.Add(log); idPairs.Add(Tuple.Create(log.Sid, Convert.ToInt64(entry.Id))); } catch (JsonException e) { MobileCenterLog.Error(MobileCenterLog.LogTag, "Cannot deserialize a log in storage", e); failedToDeserializeALog = true; _storageAdapter.DeleteAsync <LogEntry>(row => row.Id == entry.Id) .Wait(); } } if (failedToDeserializeALog) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "Deleted logs that could not be deserialized"); } if (idPairs.Count == 0) { MobileCenterLog.Debug(MobileCenterLog.LogTag, $"No available logs in storage for channel '{channelName}'"); return(null); } // Process the results var batchId = Guid.NewGuid().ToString(); ProcessLogIds(channelName, batchId, idPairs); logs?.AddRange(retrievedLogs); return(batchId); }); try { _queue.Add(task); } catch (InvalidOperationException) { throw new StorageException("The operation has been cancelled"); } _flushSemaphore.Release(); return(await task.ConfigureAwait(false)); }