예제 #1
0
            /// <summary>
            /// Handler for back-off, if retry is not possible it returns <c>false</c>. Otherwise it blocks for some time (miliseconds)
            /// and returns <c>true</c>, so call is retried.
            /// </summary>
            /// <param name="args">The arguments object to handler call.</param>
            /// <returns>If request could be retried.</returns>
            public async Task <bool> HandleResponseAsync(HandleUnsuccessfulResponseArgs args)
            {
                if (!args.SupportsRetry || _backoff.MaxNumOfRetries < args.CurrentFailedTry)
                {
                    return(false);
                }

                if (IsTransientError(args.Response.StatusCode, _service.DeserializeError(args.Response).Result))
                {
                    var delay = _backoff.GetNextBackOff(args.CurrentFailedTry);
                    if (delay > _maxTimeSpan || delay < TimeSpan.Zero)
                    {
                        return(false);
                    }

                    await Task.Delay(delay, args.CancellationToken);

                    Logger.Log("Back-Off waited " + delay.TotalMilliseconds + "ms before next retry...", EventType.Debug);

                    return(true);
                }

                return(false);
            }
예제 #2
0
        public async Task InsertDataAsync(IList <TableDataInsertAllRequest.RowsData> rows,
                                          CancellationToken cancellationToken)
        {
            ExpandTableIdIfNecessary();
            await EnsureTableExistsAsync(cancellationToken);

            var req = new TableDataInsertAllRequest
            {
                Rows = rows
            };
            var rowsCount = req.Rows.Count;
            var retry     = 1;

            while (retry < _BackOff.MaxNumOfRetries)
            {
                try
                {
                    var response = await _BQSvc.Tabledata.InsertAll(req,
                                                                    Config.ProjectId, Config.DatasetId, TableIdExpanded)
                                   .ExecuteAsync(cancellationToken);

                    if (response.InsertErrors == null || !response.InsertErrors.Any())
                    {
                        return;
                    }

                    var messages = response.InsertErrors
                                   .Zip(req.Rows, (x, r) => x.Errors.Select(e => new { x, r, e }).ToArray())
                                   .SelectMany(xs => xs)
                                   .Where(x => x.e.Reason != "stopped")
                                   .Select(x =>
                    {
                        return(string.Format(@"Index:{0}
DebugInfo:{1}
ETag:{2}
Location:{3}
Message:{4}
Reason:{5}
PostRawJSON:{6}",
                                             x.x.Index, x.e.DebugInfo, x.e.ETag, x.e.Location,
                                             x.e.Message, x.e.Reason,
                                             JsonConvert.SerializeObject(x.r.Json, Formatting.None)));
                    });
                    this.healthReporter.ReportWarning(String.Join("\n", messages), EventFlowContextIdentifiers.Output);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (GoogleApiException ex)
                {
                    string errorMessage = nameof(BigQueryOutput) + ": insert has failed." + Environment.NewLine + ex.ToString();
                    this.healthReporter.ReportWarning(errorMessage, EventFlowContextIdentifiers.Output);

                    if (ex.HttpStatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        return; // something wrong in authentication. no retry
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = nameof(BigQueryOutput) + ": insert has failed." + Environment.NewLine + ex.ToString();
                    this.healthReporter.ReportWarning(errorMessage, EventFlowContextIdentifiers.Output);
                    return;
                }

                retry++;
                await Task.Delay(_BackOff.GetNextBackOff(retry));
            }

            this.healthReporter.ReportWarning(nameof(BigQueryOutput) + ": Retry over.", EventFlowContextIdentifiers.Output);
        }
예제 #3
0
        /// <param name="retryStrategy">If not null, try retry.</param>
        public async Task InsertAllAsync <T>(BigqueryService service, IEnumerable <T> data, IBackOff retryStrategy = null, Func <T, string> insertIdSelector = null, JsonSerializerSettings serializerSettings = null)
        {
            if (insertIdSelector == null)
            {
                insertIdSelector = _ => Guid.NewGuid().ToString();
            }

            var rows = data
                       .Select(x => new Google.Apis.Bigquery.v2.Data.TableDataInsertAllRequest.RowsData
            {
                InsertId = insertIdSelector(x),
                Json     = JsonConvert.DeserializeObject <Dictionary <string, object> >(JsonConvert.SerializeObject(x, serializerSettings))
            })
                       .Where(x => x.Json != null)
                       .ToArray();

            if (!rows.Any())
            {
                return;
            }

            var request = service.Tabledata.InsertAll(new TableDataInsertAllRequest
            {
                Rows = rows
            }, this.project_id, this.dataset_id, this.table_id);

            var retry = 0;
            TableDataInsertAllResponse response = null;
            Exception lastError;

            do
            {
                try
                {
                    lastError = null;
                    response  = await request.ExecuteAsync().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    lastError = ex;
                }

                if (retryStrategy == null)
                {
                    break;
                }
                if (response != null && response.InsertErrors == null)
                {
                    break;
                }

                retry++;
                var nextDelay = retryStrategy.GetNextBackOff(retry);
                if (nextDelay == TimeSpan.MinValue)
                {
                    break;
                }

                await Task.Delay(nextDelay).ConfigureAwait(false);
            } while (true);

            if (lastError != null)
            {
                var exception = new InsertAllFailedException("", lastError)
                {
                    RetryCount         = retry,
                    InternalErrorInfos = new InsertAllFailedException.ErrorInfo[0],
                };

                throw exception;
            }

            if (response.InsertErrors != null && response.InsertErrors.Any())
            {
                var errorMessages = response.InsertErrors.Zip(rows, (x, r) =>
                {
                    return(x.Errors.Select(e =>
                    {
                        return new InsertAllFailedException.ErrorInfo
                        {
                            Index = x.Index,
                            DebugInfo = e.DebugInfo,
                            ETag = e.ETag,
                            Location = e.Location,
                            Message = e.Message,
                            Reason = e.Reason,
                            PostRawJSON = JsonConvert.SerializeObject(r.Json, Formatting.None)
                        };
                    }));
                }).SelectMany(xs => xs);

                var exception = new InsertAllFailedException
                {
                    RetryCount         = retry,
                    InternalErrorInfos = errorMessages.ToArray()
                };

                throw exception;
            }
        }
예제 #4
0
        public async Task InsertDataAsync(IList <TableDataInsertAllRequest.RowsData> rows)
        {
            ExpandTableIdIfNecessary();
            await EnsureTableExistsAsync();

            var req = new TableDataInsertAllRequest
            {
                Rows = rows
            };
            var rowsCount = req.Rows.Count;
            var retry     = 1;

            while (retry < _BackOff.MaxNumOfRetries)
            {
                try
                {
                    BigQuerySinkEventSource.Log.BigQueryInsertBegan(rowsCount);

                    var response = await _BQSvc.Tabledata.InsertAll(req,
                                                                    ProjectId, DatasetId, TableIdExpanded).ExecuteAsync();

                    if (response.InsertErrors == null || !response.InsertErrors.Any())
                    {
                        BigQuerySinkEventSource.Log.BigQueryInserted(rowsCount);
                        return;
                    }

                    var messages = response.InsertErrors
                                   .Zip(req.Rows, (x, r) => x.Errors.Select(e => new { x, r, e }).ToArray())
                                   .SelectMany(xs => xs)
                                   .Where(x => x.e.Reason != "stopped")
                                   .Select(x =>
                    {
                        return(string.Format(@"Index:{0}
DebugInfo:{1}
ETag:{2}
Location:{3}
Message:{4}
Reason:{5}
PostRawJSON:{6}",
                                             x.x.Index, x.e.DebugInfo, x.e.ETag, x.e.Location,
                                             x.e.Message, x.e.Reason,
                                             JsonConvert.SerializeObject(x.r.Json, Formatting.None)));
                    });
                    BigQuerySinkEventSource.Log.BigQueryInsertFault(String.Join("\n", messages), retry);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (GoogleApiException ex)
                {
                    BigQuerySinkEventSource.Log.BigQueryInsertFault(ex.ToString(), retry);
                    if (ex.HttpStatusCode == System.Net.HttpStatusCode.Unauthorized)
                    {
                        return; // something wrong in authentication. no retry
                    }
                }
                catch (Exception ex)
                {
                    BigQuerySinkEventSource.Log.BigQueryInsertFault(ex.ToString(), retry);
                    return;
                }

                retry++;
                await Task.Delay(_BackOff.GetNextBackOff(retry));
            }

            BigQuerySinkEventSource.Log.BigQueryRetryOver(req.ToString());
        }