/// <summary> /// Try to cancel a job. /// </summary> /// <param name="batchJobId">ID of the batch job to cancel.</param> /// <exception cref="AdWordsApiException">Thrown if an API error occurred /// when cancelling the job.</exception> public void TryToCancelJob(long batchJobId) { BatchJobService batchJobService = (BatchJobService)User.GetService(AdWordsService.v201802.BatchJobService); try { BatchJobOperation batchJobSetOperation = new BatchJobOperation() { @operator = Operator.SET, operand = new ApiBatchJob() { id = batchJobId, status = BatchJobStatus.CANCELING } }; batchJobService.mutate(new BatchJobOperation[] { batchJobSetOperation }); } catch (AdWordsApiException) { // Rethrow the API exception. throw; } }
/// <summary> /// Waits while the batch job is pending. /// </summary> /// <param name="batchJobService">The batch job service.</param> /// <param name="batchJob">The batch job.</param> /// <param name="isPending">True, if the job status is pending, false /// otherwise.</param> /// <param name="pollAttempts">The poll attempts to make while waiting for /// batchjob completion or cancellation.</param> private BatchJob WaitWhileJobIsPending(BatchJobService batchJobService, BatchJob batchJob, out bool isPending, out long pollAttempts) { pollAttempts = 0; isPending = true; do { int sleepMillis = (int)Math.Pow(2, pollAttempts) * POLL_INTERVAL_SECONDS_BASE * 1000; Console.WriteLine("Sleeping {0} millis...", sleepMillis); Thread.Sleep(sleepMillis); Selector selector = new Selector() { fields = new string[] { BatchJob.Fields.Id, BatchJob.Fields.Status, BatchJob.Fields.DownloadUrl, BatchJob.Fields.ProcessingErrors, BatchJob.Fields.ProgressStats }, predicates = new Predicate[] { Predicate.Equals(BatchJob.Fields.Id, batchJob.id) } }; batchJob = batchJobService.get(selector).entries[0]; Console.WriteLine("Batch job ID {0} has status '{1}'.", batchJob.id, batchJob.status); isPending = PENDING_STATUSES.Contains(batchJob.status); } while (isPending && ++pollAttempts <= MAX_RETRIES); return(batchJob); }
/// <summary> /// Wait for the job to complete. /// </summary> /// <param name="batchJobId">ID of the job to wait for completion.</param> /// <param name="numMilliSecondsToWait">The number of milliseconds to wait for job /// completion.</param> /// <param name="callback">The callback to be called whenever the method polls the /// server for job status.</param> /// <returns><c>false</c>, if the job is still pending, true otherwise.</returns> public bool WaitForPendingJob(long batchJobId, int numMilliSecondsToWait, WaitCallback callback) { BatchJobService batchJobService = (BatchJobService)User.GetService(AdWordsService.v201802.BatchJobService); long totalMillisecondsWaited = 0; long pollAttempts = 0; bool cancelWait = false; bool isPending = true; do { int sleepMillis = (int)Math.Pow(2, pollAttempts) * POLL_INTERVAL_SECONDS_BASE * 1000; if (totalMillisecondsWaited + sleepMillis > numMilliSecondsToWait) { sleepMillis = (int)(numMilliSecondsToWait - totalMillisecondsWaited); } Thread.Sleep(sleepMillis); totalMillisecondsWaited += sleepMillis; pollAttempts++; Selector selector = new Selector() { fields = new string[] { ApiBatchJob.Fields.Id, ApiBatchJob.Fields.Status, ApiBatchJob.Fields.DownloadUrl, ApiBatchJob.Fields.ProcessingErrors, ApiBatchJob.Fields.ProgressStats }, predicates = new Predicate[] { Predicate.Equals(ApiBatchJob.Fields.Id, batchJobId) } }; ApiBatchJob batchJob = batchJobService.get(selector).entries[0]; isPending = PENDING_STATUSES.Contains(batchJob.status); if (callback != null) { cancelWait = callback(batchJob, totalMillisecondsWaited); } } while (isPending && totalMillisecondsWaited < numMilliSecondsToWait && !cancelWait); return(!isPending); }
/// <summary> /// Cancels the job. /// </summary> /// <param name="batchJobService">The batch job service.</param> /// <param name="batchJob">The batch job.</param> private BatchJob CancelJob(BatchJobService batchJobService, BatchJob batchJob) { try { batchJob.status = BatchJobStatus.CANCELING; BatchJobOperation batchJobSetOperation = new BatchJobOperation() { @operator = Operator.SET, operand = batchJob }; batchJob = batchJobService.mutate( new BatchJobOperation[] { batchJobSetOperation }).value[0]; Console.WriteLine("Requested cancellation of batch job with ID {0}.", batchJob.id); } catch (AdWordsApiException e) { ApiException innerException = e.ApiException as ApiException; if (innerException == null) { // This means that the API call failed, but not due to an error on // the operations. You can still examine the innerException property // of the original exception to get more details. throw new Exception("Failed to retrieve ApiError. See inner exception for more " + "details.", e); } // Examine each ApiError received from the server. foreach (ApiError apiError in innerException.errors) { if (apiError is BatchJobError) { BatchJobError batchJobError = (BatchJobError)apiError; if (batchJobError.reason == BatchJobErrorReason.INVALID_STATE_CHANGE) { Console.WriteLine("Attempt to cancel batch job with ID {0} was rejected because " + "the job already completed or was canceled.", batchJob.id); continue; } } } throw; } return(batchJob); }
/// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { using (BatchJobService batchJobService = (BatchJobService)user.GetService(AdWordsService.v201806.BatchJobService)) { try { // Create a BatchJob. BatchJobOperation addOp = new BatchJobOperation() { @operator = Operator.ADD, operand = new BatchJob() }; BatchJob batchJob = batchJobService.mutate(new BatchJobOperation[] { addOp }).value[0]; // Get the upload URL from the new job. string uploadUrl = batchJob.uploadUrl.url; Console.WriteLine( "Created BatchJob with ID {0}, status '{1}' and upload URL {2}.", batchJob.id, batchJob.status, batchJob.uploadUrl.url); BatchJobUtilities batchJobUploadHelper = new BatchJobUtilities(user); // Create a resumable Upload URL to upload the operations. string resumableUploadUrl = batchJobUploadHelper.GetResumableUploadUrl(uploadUrl); BatchUploadProgress uploadProgress = batchJobUploadHelper.BeginStreamUpload(resumableUploadUrl); // Create and add an operation to create a new budget. BudgetOperation budgetOperation = BuildBudgetOperation(); uploadProgress = batchJobUploadHelper.StreamUpload(uploadProgress, new List <Operation>() { budgetOperation }); // Create and add operations to create new campaigns. List <Operation> campaignOperations = new List <Operation>(); campaignOperations.AddRange( BuildCampaignOperations(budgetOperation.operand.budgetId)); uploadProgress = batchJobUploadHelper.StreamUpload(uploadProgress, campaignOperations); // Create and add operations to create new ad groups. List <Operation> adGroupOperations = new List <Operation>(); foreach (CampaignOperation campaignOperation in campaignOperations) { adGroupOperations.AddRange( BuildAdGroupOperations(campaignOperation.operand.id)); } uploadProgress = batchJobUploadHelper.StreamUpload(uploadProgress, adGroupOperations); // Create and add operations to create new ad group ads (expanded text ads). List <Operation> adOperations = new List <Operation>(); foreach (AdGroupOperation adGroupOperation in adGroupOperations) { adOperations.AddRange( BuildAdGroupAdOperations(adGroupOperation.operand.id)); } uploadProgress = batchJobUploadHelper.StreamUpload(uploadProgress, adOperations); // Create and add operations to create new ad group criteria (keywords). List <Operation> keywordOperations = new List <Operation>(); foreach (AdGroupOperation adGroupOperation in adGroupOperations) { keywordOperations.AddRange( BuildAdGroupCriterionOperations(adGroupOperation.operand.id)); } uploadProgress = batchJobUploadHelper.StreamUpload(uploadProgress, keywordOperations); // Mark the upload as complete. batchJobUploadHelper.EndStreamUpload(uploadProgress); bool isCompleted = batchJobUploadHelper.WaitForPendingJob(batchJob.id, TIME_TO_WAIT_FOR_COMPLETION, delegate(BatchJob waitBatchJob, long timeElapsed) { Console.WriteLine("[{0} seconds]: Batch job ID {1} has status '{2}'.", timeElapsed / 1000, waitBatchJob.id, waitBatchJob.status); batchJob = waitBatchJob; return(false); }); if (!isCompleted) { throw new TimeoutException( "Job is still in pending state after waiting for " + TIME_TO_WAIT_FOR_COMPLETION + " seconds."); } if (batchJob.processingErrors != null) { foreach (BatchJobProcessingError processingError in batchJob .processingErrors) { Console.WriteLine(" Processing error: {0}, {1}, {2}, {3}, {4}", processingError.ApiErrorType, processingError.trigger, processingError.errorString, processingError.fieldPath, processingError.reason); } } if (batchJob.downloadUrl != null && batchJob.downloadUrl.url != null) { BatchJobMutateResponse mutateResponse = batchJobUploadHelper.Download(batchJob.downloadUrl.url); Console.WriteLine("Downloaded results from {0}.", batchJob.downloadUrl.url); foreach (MutateResult mutateResult in mutateResponse.rval) { string outcome = mutateResult.errorList == null ? "SUCCESS" : "FAILURE"; Console.WriteLine(" Operation [{0}] - {1}", mutateResult.index, outcome); } } } catch (Exception e) { throw new System.ApplicationException( "Failed to add campaigns using batch job.", e); } } }
/// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="adGroupId">Id of the ad groups to which keywords are /// added.</param> public void Run(AdWordsUser user, long adGroupId) { using (BatchJobService batchJobService = (BatchJobService)user.GetService( AdWordsService.v201708.BatchJobService)) { BatchJobOperation addOp = new BatchJobOperation() { @operator = Operator.ADD, operand = new BatchJob() }; try { BatchJob batchJob = batchJobService.mutate(new BatchJobOperation[] { addOp }).value[0]; Console.WriteLine("Created BatchJob with ID {0}, status '{1}' and upload URL {2}.", batchJob.id, batchJob.status, batchJob.uploadUrl.url); List <AdGroupCriterionOperation> operations = CreateOperations(adGroupId); // Create a BatchJobUtilities instance for uploading operations. Use a // chunked upload. BatchJobUtilities batchJobUploadHelper = new BatchJobUtilities(user, true, CHUNK_SIZE); // Create a resumable Upload URL to upload the operations. string resumableUploadUrl = batchJobUploadHelper.GetResumableUploadUrl( batchJob.uploadUrl.url); // Use the BatchJobUploadHelper to upload all operations. batchJobUploadHelper.Upload(resumableUploadUrl, operations.ToArray()); // A flag to determine if the job was requested to be cancelled. This // typically comes from the user. bool wasCancelRequested = false; bool isComplete = batchJobUploadHelper.WaitForPendingJob(batchJob.id, TIME_TO_WAIT_FOR_COMPLETION, delegate(BatchJob waitBatchJob, long timeElapsed) { Console.WriteLine("[{0} seconds]: Batch job ID {1} has status '{2}'.", timeElapsed / 1000, waitBatchJob.id, waitBatchJob.status); batchJob = waitBatchJob; return(wasCancelRequested); }); // Optional: Cancel the job if it has not completed after waiting for // TIME_TO_WAIT_FOR_COMPLETION. bool shouldWaitForCancellation = false; if (!isComplete && wasCancelRequested) { BatchJobError cancellationError = null; try { batchJobUploadHelper.TryToCancelJob(batchJob.id); } catch (AdWordsApiException e) { cancellationError = GetBatchJobError(e); } if (cancellationError == null) { Console.WriteLine("Successfully requested job cancellation."); shouldWaitForCancellation = true; } else { Console.WriteLine("Job cancellation failed. Error says: {0}.", cancellationError.reason); } if (shouldWaitForCancellation) { isComplete = batchJobUploadHelper.WaitForPendingJob(batchJob.id, TIME_TO_WAIT_FOR_COMPLETION, delegate(BatchJob waitBatchJob, long timeElapsed) { Console.WriteLine("[{0} seconds]: Batch job ID {1} has status '{2}'.", timeElapsed / 1000, waitBatchJob.id, waitBatchJob.status); batchJob = waitBatchJob; return(false); }); } } if (!isComplete) { throw new TimeoutException("Job is still in pending state after waiting for " + TIME_TO_WAIT_FOR_COMPLETION + " seconds."); } if (batchJob.processingErrors != null) { foreach (BatchJobProcessingError processingError in batchJob.processingErrors) { Console.WriteLine(" Processing error: {0}, {1}, {2}, {3}, {4}", processingError.ApiErrorType, processingError.trigger, processingError.errorString, processingError.fieldPath, processingError.reason); } } if (batchJob.downloadUrl != null && batchJob.downloadUrl.url != null) { BatchJobMutateResponse mutateResponse = batchJobUploadHelper.Download( batchJob.downloadUrl.url); Console.WriteLine("Downloaded results from {0}.", batchJob.downloadUrl.url); foreach (MutateResult mutateResult in mutateResponse.rval) { String outcome = mutateResult.errorList == null ? "SUCCESS" : "FAILURE"; Console.WriteLine(" Operation [{0}] - {1}", mutateResult.index, outcome); } } else { Console.WriteLine("No results available for download."); } } catch (Exception e) { throw new System.ApplicationException("Failed to create keywords using batch job.", e); } } }
/// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> public void Run(AdWordsUser user) { // Get the BatchJobService. BatchJobService batchJobService = (BatchJobService)user.GetService( AdWordsService.v201509.BatchJobService); try { // Create a BatchJob. BatchJobOperation addOp = new BatchJobOperation() { @operator = Operator.ADD, operand = new BatchJob() }; BatchJob batchJob = batchJobService.mutate(new BatchJobOperation[] { addOp }).value[0]; // Get the upload URL from the new job. string uploadUrl = batchJob.uploadUrl.url; Console.WriteLine("Created BatchJob with ID {0}, status '{1}' and upload URL {2}.", batchJob.id, batchJob.status, batchJob.uploadUrl.url); // Create the mutate request that will be sent to the upload URL. List <Operation> operations = new List <Operation>(); // Create and add an operation to create a new budget. BudgetOperation budgetOperation = BuildBudgetOperation(); operations.Add(budgetOperation); // Create and add operations to create new campaigns. List <CampaignOperation> campaignOperations = BuildCampaignOperations(budgetOperation.operand.budgetId); operations.AddRange(campaignOperations); // Create and add operations to create new ad groups. List <AdGroupOperation> adGroupOperations = new List <AdGroupOperation>(); foreach (CampaignOperation campaignOperation in campaignOperations) { adGroupOperations.AddRange(BuildAdGroupOperations(campaignOperation.operand.id)); } operations.AddRange(adGroupOperations); // Create and add operations to create new ad group criteria (keywords). foreach (AdGroupOperation adGroupOperation in adGroupOperations) { operations.AddRange(BuildAdGroupAdOperations(adGroupOperation.operand.id)); } // Create and add operations to create new ad group ads (text ads). foreach (AdGroupOperation adGroupOperation in adGroupOperations) { operations.AddRange(BuildAdGroupCriterionOperations(adGroupOperation.operand.id)); } BatchJobUtilities batchJobUploadHelper = new BatchJobUtilities(user); // Use the BatchJobUploadHelper to upload all operations. batchJobUploadHelper.Upload(uploadUrl, operations.ToArray()); long pollAttempts = 0; bool isPending = true; do { int sleepMillis = (int)Math.Pow(2, pollAttempts) * POLL_INTERVAL_SECONDS_BASE * 1000; Console.WriteLine("Sleeping {0} millis...", sleepMillis); Thread.Sleep(sleepMillis); Selector selector = new Selector() { fields = new string[] { BatchJob.Fields.Id, BatchJob.Fields.Status, BatchJob.Fields.DownloadUrl, BatchJob.Fields.ProcessingErrors, BatchJob.Fields.ProgressStats }, predicates = new Predicate[] { Predicate.Equals(BatchJob.Fields.Id, batchJob.id) } }; batchJob = batchJobService.get(selector).entries[0]; Console.WriteLine("Batch job ID {0} has status '{1}'.", batchJob.id, batchJob.status); isPending = PENDING_STATUSES.Contains(batchJob.status); } while (isPending && ++pollAttempts <= MAX_RETRIES); if (isPending) { throw new TimeoutException("Job is still in pending state after polling " + MAX_RETRIES + " times."); } if (batchJob.processingErrors != null) { foreach (BatchJobProcessingError processingError in batchJob.processingErrors) { Console.WriteLine(" Processing error: {0}, {1}, {2}, {3}, {4}", processingError.ApiErrorType, processingError.trigger, processingError.errorString, processingError.fieldPath, processingError.reason); } } if (batchJob.downloadUrl != null && batchJob.downloadUrl.url != null) { BatchJobMutateResponse mutateResponse = batchJobUploadHelper.Download( batchJob.downloadUrl.url); Console.WriteLine("Downloaded results from {0}.", batchJob.downloadUrl.url); foreach (MutateResult mutateResult in mutateResponse.rval) { String outcome = mutateResult.errorList == null ? "SUCCESS" : "FAILURE"; Console.WriteLine(" Operation [{0}] - {1}", mutateResult.index, outcome); } } } catch (Exception e) { throw new System.ApplicationException("Failed to add campaigns using batch job.", e); } }
/// <summary> /// Runs the code example. /// </summary> /// <param name="user">The AdWords user.</param> /// <param name="adGroupId">Id of the ad groups to which keywords are /// added.</param> public void Run(AdWordsUser user, long adGroupId) { // Get the MutateJobService. BatchJobService batchJobService = (BatchJobService)user.GetService( AdWordsService.v201603.BatchJobService); BatchJobOperation addOp = new BatchJobOperation() { @operator = Operator.ADD, operand = new BatchJob() }; try { BatchJob batchJob = batchJobService.mutate(new BatchJobOperation[] { addOp }).value[0]; Console.WriteLine("Created BatchJob with ID {0}, status '{1}' and upload URL {2}.", batchJob.id, batchJob.status, batchJob.uploadUrl.url); List <AdGroupCriterionOperation> operations = CreateOperations(adGroupId); // Create a BatchJobUtilities instance for uploading operations. Use a // chunked upload. BatchJobUtilities batchJobUploadHelper = new BatchJobUtilities(user, true, CHUNK_SIZE); // Create a resumable Upload URL to upload the operations. string resumableUploadUrl = batchJobUploadHelper.GetResumableUploadUrl( batchJob.uploadUrl.url); // Use the BatchJobUploadHelper to upload all operations. batchJobUploadHelper.Upload(resumableUploadUrl, operations.ToArray()); long pollAttempts = 0; bool isPending = false; batchJob = WaitWhileJobIsPending(batchJobService, batchJob, out isPending, out pollAttempts); // A flag to determine if the job was requested to be cancelled. This // typically comes from the user. bool wasCancelRequested = false; // Optional: Cancel the job if it has not completed after retrying // MAX_RETRIES times. if (isPending && !wasCancelRequested && pollAttempts == MAX_RETRIES) { batchJob = CancelJob(batchJobService, batchJob); batchJob = WaitWhileJobIsPending(batchJobService, batchJob, out isPending, out pollAttempts); } if (isPending) { throw new TimeoutException("Job is still in pending state after polling " + MAX_RETRIES + " times."); } if (batchJob.processingErrors != null) { foreach (BatchJobProcessingError processingError in batchJob.processingErrors) { Console.WriteLine(" Processing error: {0}, {1}, {2}, {3}, {4}", processingError.ApiErrorType, processingError.trigger, processingError.errorString, processingError.fieldPath, processingError.reason); } } if (batchJob.downloadUrl != null && batchJob.downloadUrl.url != null) { BatchJobMutateResponse mutateResponse = batchJobUploadHelper.Download( batchJob.downloadUrl.url); Console.WriteLine("Downloaded results from {0}.", batchJob.downloadUrl.url); foreach (MutateResult mutateResult in mutateResponse.rval) { String outcome = mutateResult.errorList == null ? "SUCCESS" : "FAILURE"; Console.WriteLine(" Operation [{0}] - {1}", mutateResult.index, outcome); } } else { Console.WriteLine("No results available for download."); } } catch (Exception e) { throw new System.ApplicationException("Failed to create keywords using batch job.", e); } }